OSDN Git Service

V 3.2
[fast-forth/master.git] / MSP430-FORTH / PROG100k.f
1 \ -*- coding: utf-8 -*-
2
3 ; -----------------------------------
4 ; PROG100k.f = 76 x RC5toLCD.f
5 ; -----------------------------------
6 ; download source file sized to compile 100 kbytes
7 ; -----------------------------------
8
9 \ TARGET SELECTION
10 \ MSP_EXP430FR5739  MSP_EXP430FR5969    MSP_EXP430FR5994    MSP_EXP430FR6989
11 \ MSP_EXP430FR2355
12 \
13 \ MY_MSP430FR5738   MY_MSP430FR5738_1 MY_MSP430FR5738_2   
14 \ MY_MSP430FR5948   MY_MSP430FR5948_1   
15 \
16 \
17 \ Copyright (C) <2016>  <J.M. THOORENS>
18 \
19 \ This program is free software: you can redistribute it and/or modify
20 \ it under the terms of the GNU General Public License as published by
21 \ the Free Software Foundation, either version 3 of the License, or
22 \ (at your option) any later version.
23 \
24 \ This program is distributed in the hope that it will be useful,
25 \ but WITHOUT ANY WARRANTY\ without even the implied warranty of
26 \ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27 \ GNU General Public License for more details.
28 \
29 \ You should have received a copy of the GNU General Public License
30 \ along with this program.  If not, see <http://www.gnu.org/licenses/>.
31 \
32 \
33 \ ===========================================================================
34 \ remember: for good downloading to target, all lines must be ended with CR+LF !
35 \ ===========================================================================
36 \
37 \
38 \ REGISTERS USAGE
39 \ R4 to R7 must be saved before use and restored after
40 \ scratch registers Y to S are free for use
41 \ under interrupt, IP is free for use
42 \ interrupts reset SR register !
43 \
44 \ PUSHM order : PSP,TOS, IP,  S,  T,  W,  X,  Y, rEXIT,rDOVAR,rDOCON, rDODOES, R3, SR,RSP, PC
45 \ PUSHM order : R15,R14,R13,R12,R11,R10, R9, R8,  R7  ,  R6  ,  R5  ,   R4   , R3, R2, R1, R0
46 \
47 \ example : PUSHM #6,IP pushes IP,S,T,W,X,Y registers to return stack
48 \
49 \ POPM  order :  PC,RSP, SR, R3, rDODOES,rDOCON,rDOVAR,rEXIT,  Y,  X,  W,  T,  S, IP,TOS,PSP
50 \ POPM  order :  R0, R1, R2, R3,   R4   ,  R5  ,  R6  ,  R7 , R8, R9,R10,R11,R12,R13,R14,R15
51 \
52 \ example : POPM #6,IP   pop Y,X,W,T,S,IP registers from return stack
53 \
54 \ ASSEMBLER conditionnal usage after IF UNTIL WHILE : S< S>= U< U>= 0= 0<> 0>=
55 \ ASSEMBLER conditionnal usage before ?JMP ?GOTO    : S< S>= U< U>= 0= 0<> 0< 
56 \
57 \ FORTH conditionnal    : 0= 0< = < > U<
58 \
59 \ display on a LCD 2x20 CHAR the code sent by an IR remote under philips RC5 protocol
60 \ target : any TI MSP-EXP430FRxxxx launchpad (FRAM)
61 \ LPM_MODE = LPM0 because use SMCLK for LCDVo
62 \
63 \ DEMO : driver for IR remote compatible with the PHILIPS RC5 protocol
64 \ plus : driver for 5V LCD 2x20 characters display with 4 bits data interface
65 \        without usage of an auxiliary 5V to feed the LCD_Vo
66 \        and without potentiometer to adjust the LCD contrast :
67 \        to adjust LCD contrast, just press S1 (-) or S2 (+)
68 \        LCDVo current consumption ~ 500 uA.
69 \
70 \ ===================================================================================
71 \ notice : adjust WDT_TIM_EX0,LCD_TIM_CTL,LCD_TIM_EX0 and 20_us to the target frequency if <> 8MHz !
72 \ ===================================================================================
73 \
74 \
75 \ layout : I/O are defined in the launchpad.pat file (don't work with ChipStick_FR2433)
76 \
77 \  GND  <-------+---0V0---------->  1 LCD_Vss
78 \  VCC  >------ | --3V6-----+---->  2 LCD_Vdd
79 \               |           |
80 \              ___    470n ---
81 \               ^          ---
82 \              / \ 1N4148   |
83 \              ---          |
84 \          100n |    2k2    |
85 \ LCD_TIM_.2 >---||--+--^/\/\/v--+---->  3 LCD_Vo (= 0V6 without modulation)
86 \       ------------------------->  4 LCD_RW
87 \       ------------------------->  5 LCD_RW
88 \       ------------------------->  6 LCD_EN
89 \       <------------------------> 11 LCD_DB4
90 \       <------------------------> 12 LCD_DB5
91 \       <------------------------> 13 LCD_DB5
92 \       <------------------------> 14 LCD_DB7
93 \
94 \       <----- LCD contrast + <---    Sw1   <--- (finger) :-)
95 \       <----- LCD contrast - <---    Sw2   <--- (finger) :-)
96 \
97 \ rc5   <--- OUT IR_Receiver (1 TSOP32236)
98
99 RST_STATE
100
101 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
102
103 [UNDEFINED] MARKER [IF]
104 \  https://forth-standard.org/standard/core/MARKER
105 \  MARKER
106 \ ( "<spaces>name" -- )
107 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
108 \ with the execution semantics defined below.
109
110 \ name Execution: ( -- )
111 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
112 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
113 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
114 \ not necessarily provided. No other contextual information such as numeric base is affected
115 \
116 : MARKER
117 CREATE
118 HI2LO
119 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
120 SUB #2,Y            \ 1 Y = LFA
121 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
122 ADD #4,&DP          \ 3 add 2 cells
123 LO2HI
124 DOES>
125 HI2LO
126 MOV @RSP+,IP        \ -- PFA
127 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
128 MOV @TOS,&INIDP     \       set DP value for RST_STATE
129 MOV @PSP+,TOS       \ --
130 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
131 ENDCODE
132 [THEN]
133
134 MARKER {RC5TOLCD}
135
136 [UNDEFINED] @ [IF]
137 \ https://forth-standard.org/standard/core/Fetch
138 \ @     c-addr -- char   fetch char from memory
139 CODE @
140 MOV @TOS,TOS
141 MOV @IP+,PC
142 ENDCODE
143 [THEN]
144
145 [UNDEFINED] CONSTANT [IF]
146 \ https://forth-standard.org/standard/core/CONSTANT
147 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
148 : CONSTANT 
149 CREATE
150 HI2LO
151 MOV TOS,-2(W)           \   PFA = n
152 MOV @PSP+,TOS
153 MOV @RSP+,IP
154 MOV @IP+,PC
155 ENDCODE
156 [THEN]
157
158 [UNDEFINED] STATE [IF]
159 \ https://forth-standard.org/standard/core/STATE
160 \ STATE   -- a-addr       holds compiler state
161 STATEADR CONSTANT STATE
162 [THEN]
163
164 [UNDEFINED] = [IF]
165 \ https://forth-standard.org/standard/core/Equal
166 \ =      x1 x2 -- flag         test x1=x2
167 CODE =
168 SUB @PSP+,TOS   \ 2
169 0<> IF          \ 2
170     AND #0,TOS  \ 1
171     MOV @IP+,PC \ 4
172 THEN
173 XOR #-1,TOS     \ 1 flag Z = 1
174 MOV @IP+,PC     \ 4
175 ENDCODE
176 [THEN]
177
178 [UNDEFINED] IF [IF]
179 \ https://forth-standard.org/standard/core/IF
180 \ IF       -- IFadr    initialize conditional forward branch
181 CODE IF       \ immediate
182 SUB #2,PSP              \
183 MOV TOS,0(PSP)          \
184 MOV &DP,TOS             \ -- HERE
185 ADD #4,&DP            \           compile one word, reserve one word
186 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
187 ADD #2,TOS              \ -- HERE+2=IFadr
188 MOV @IP+,PC
189 ENDCODE IMMEDIATE
190 [THEN]
191
192 [UNDEFINED] THEN [IF]
193 \ https://forth-standard.org/standard/core/THEN
194 \ THEN     IFadr --                resolve forward branch
195 CODE THEN               \ immediate
196 MOV &DP,0(TOS)          \ -- IFadr
197 MOV @PSP+,TOS           \ --
198 MOV @IP+,PC
199 ENDCODE IMMEDIATE
200 [THEN]
201
202 [UNDEFINED] ELSE [IF]
203 \ https://forth-standard.org/standard/core/ELSE
204 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
205 CODE ELSE     \ immediate
206 ADD #4,&DP              \ make room to compile two words
207 MOV &DP,W               \ W=HERE+4
208 MOV #BRAN,-4(W)
209 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
210 SUB #2,W                \ HERE+2
211 MOV W,TOS               \ -- ELSEadr
212 MOV @IP+,PC
213 ENDCODE IMMEDIATE
214 [THEN]
215
216 [UNDEFINED] DEFER [IF]
217 \ https://forth-standard.org/standard/core/DEFER
218 \ DEFER "<spaces>name"   --
219 \ Skip leading space delimiters. Parse name delimited by a space.
220 \ Create a definition for name with the execution semantics defined below.
221
222 \ name Execution:   --
223 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
224 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
225 : DEFER
226 CREATE
227 HI2LO
228 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
229 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
230 MOV @RSP+,IP
231 MOV @IP+,PC
232 ENDCODE
233 [THEN]
234
235 [UNDEFINED] DEFER! [IF]
236 \ https://forth-standard.org/standard/core/DEFERStore
237 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
238 CODE DEFER!             \ xt2 xt1 --
239 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
240 MOV @PSP+,TOS           \ --
241 MOV @IP+,PC
242 ENDCODE
243 [THEN]
244
245 [UNDEFINED] IS [IF]
246 \ https://forth-standard.org/standard/core/IS
247 \ IS <name>        xt --
248 \ used as is :
249 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
250 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
251 \ or in a definition : ... ['] U. IS DISPLAY ...
252 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
253 \
254 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
255 : IS
256 STATE @
257 IF  POSTPONE ['] POSTPONE DEFER! 
258 ELSE ' DEFER! 
259 THEN
260 ; IMMEDIATE
261 [THEN]
262
263 [UNDEFINED] >BODY [IF]
264 \ https://forth-standard.org/standard/core/toBODY
265 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
266 CODE >BODY
267 ADD #4,TOS
268 MOV @IP+,PC
269 ENDCODE
270 [THEN]
271
272 \ CODE 20uS           \ n --      8MHz version
273 \ BEGIN               \ 4 + 16 ~ loop
274 \     MOV #39,rDOCON   \ 39
275 \     BEGIN           \ 4 ~ loop
276 \         NOP
277 \         SUB #1,rDOCON
278 \     0=  UNTIL
279 \     SUB #1,TOS      \ 1
280 \ 0= UNTIL
281 \ MOV #XDOCON,rDOCON  \ 2
282 \ MOV @PSP+,TOS
283 \ MOV @RSP+,IP        \
284 \ ENDCODE
285
286 CODE 20_US                      \ n --      n * 20 us
287 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
288     BEGIN
289         BIT #1,&LCD_TIM_CTL     \ 3
290     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
291     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
292     SUB #1,TOS                  \ 1
293 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
294 MOV @PSP+,TOS                   \ 2
295 MOV @IP+,PC                     \ 4
296 ENDCODE
297
298 CODE TOP_LCD                    \ LCD Sample
299 \                               \ if write : %xxxx_WWWW --
300 \                               \ if read  : -- %0000_RRRR
301     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
302     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
303 0= IF                           \ write LCD bits pattern
304     AND.B #LCD_DB,TOS           \ 
305     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
306     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
307     MOV @PSP+,TOS               \
308     MOV @IP+,PC
309 THEN                            \ read LCD bits pattern
310     SUB #2,PSP
311     MOV TOS,0(PSP)
312     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
313     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
314     AND.B #LCD_DB,TOS           \
315     MOV @IP+,PC
316 ENDCODE
317
318 CODE LCD_WRC                    \ char --         Write Char
319     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
320 BW1 SUB #2,PSP                  \
321     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
322     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
323     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
324     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
325 COLON                           \ high level word starts here 
326     TOP_LCD 2 20_US             \ write high nibble first
327     TOP_LCD 2 20_US 
328 ;
329
330 CODE LCD_WRF                    \ func --         Write Fonction
331     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
332     GOTO BW1
333 ENDCODE
334
335 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
336 : LCD_HOME $02 LCD_WRF 100 20_us ;
337
338 \ [UNDEFINED] OR [IF]
339
340 \ \ https://forth-standard.org/standard/core/OR
341 \ \ C OR     x1 x2 -- x3           logical OR
342 \ CODE OR
343 \ BIS @PSP+,TOS
344 \ MOV @IP+,PC
345 \ ENDCODE
346
347 \ [THEN]
348
349 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
350 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
351 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
352 \ : LCD_FN_SET        $20 OR LCD_WrF ;
353 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
354 \ : LCD_GOTO          $80 OR LCD_WrF ;
355
356
357 \ CODE LCD_RDS                    \ -- status       Read Status
358 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
359 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
360 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
361 \ COLON                           \ starts a FORTH word
362 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
363 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
364 \ HI2LO                           \ switch from FORTH to assembler
365 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
366 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
367 \     MOV @RSP+,IP                \ restore IP saved by COLON
368 \     MOV @IP+,PC                 \
369 \ ENDCODE
370
371 \ CODE LCD_RDC                    \ -- char         Read Char
372 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
373 \     GOTO BW1
374 \ ENDCODE
375
376
377 \ ******************************\
378 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
379 \ ******************************\
380 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
381 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
382 BIT.B #SW2,&SW2_IN              \ test switch S2
383 0= IF                           \ case of switch S2 pressed
384     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
385     U< IF
386         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
387     THEN
388 ELSE
389     BIT.B #SW1,&SW1_IN          \ test switch S1 input
390     0= IF                       \ case of Switch S1 pressed
391         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
392         U>= IF                  \
393            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
394         THEN                    \
395     THEN                        \
396 THEN                            \
397 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
398 RET                             \ 5
399 ENDASM
400
401 \ ******************************\
402 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
403 \ ******************************\
404 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
405 \ ******************************\
406 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
407 \                               \       SMclock = 8|16|24 MHz
408 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
409 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
410 \                               \       SR(9)=new Toggle bit memory (ADD on)
411 \ ******************************\
412 \ RC5_FirstStartBitHalfCycle:   \
413 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
414 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
415 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
416 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
417 \ [THEN]
418 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
419     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
420 [THEN]
421 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
422     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
423 [THEN]
424 MOV #1778,X                     \ RC5_Period * 1us
425 MOV #14,W                       \ count of loop
426 BEGIN                           \
427 \ ******************************\
428 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
429 \ ******************************\                   |
430 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
431 \ RC5_Compute_3/4_Period:       \                   |
432     RRUM    #1,X                \ X=1/2 cycle       |
433     MOV     X,Y                 \                   ^
434     RRUM    #1,Y                \ Y=1/4
435     ADD     X,Y                 \ Y=3/4 cycle
436     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
437     U>= UNTIL                   \ 2
438 \ ******************************\
439 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
440 \ ******************************\
441     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
442     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
443     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
444     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
445     SUB     #1,W                \ decrement count loop
446 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
447 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
448 0<> WHILE                       \ ----> out of loop ----+
449     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
450     BEGIN                       \                       |
451         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
452         CMP Y,X                 \ 1                     |   cycle time out of bound ?
453         U>= IF                  \ 2                 ^   |   yes:
454         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
455         GOTO BW1                \                   |   |      quit on truncated RC5 message
456         THEN                    \                   |   |
457         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
458     0<> UNTIL                   \ 2                 |   |
459 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
460 \ ******************************\                       |
461 \ RC5_SampleEndOf:              \ <---------------------+
462 \ ******************************\
463 BIC #$30,&RC5_TIM_CTL           \   stop timer
464 \ ******************************\
465 \ RC5_ComputeNewRC5word         \
466 \ ******************************\
467 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
468 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
469 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
470 \ ******************************\
471 \ RC5_ComputeC6bit              \
472 \ ******************************\
473 BIT     #BIT14,T                \ test /C6 bit in T
474 0= IF   BIS #BIT6,X             \ set C6 bit in X
475 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
476 \ ******************************\
477 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
478 \ ******************************\
479 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
480 \ ******************************\
481 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
482 XOR     @RSP,T                  \ (new XOR old) Toggle bits
483 BIT     #UF10,T                 \ repeated RC5_command ?
484 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
485 XOR #UF10,0(RSP)                \ 5 toggle bit memory
486 \ ******************************\
487 \ Display IR_RC5 code           \
488 \ ******************************\
489 SUB #8,PSP                      \ TOS -- x x x x TOS
490 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
491 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
492 MOV #$10,&BASEADR               \                                               set hexadecimal base
493 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
494 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
495 LO2HI                           \                                               switch from assembler to FORTH
496     LCD_CLEAR                   \                                               set LCD cursor at home
497     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
498     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
499     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
500     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
501 HI2LO                           \     --                                        switch from FORTH to assembler
502 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
503 MOV @PSP+,TOS                   \     -- TOS
504 RET
505 ENDASM
506
507 \ ******************************\
508 ASM BACKGROUND                  \
509 \ ******************************\
510 BEGIN
511 \     ...                         \ insert here your background task
512 \     ...                         \
513 \     ...                         \
514     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
515     BIS &LPM_MODE,SR            \
516 \ ******************************\
517 \ here start all interrupts     \
518 \ ******************************\
519 \ here return all interrupts    \
520 \ ******************************\
521 AGAIN                           \
522 ENDASM                          \
523 \ ******************************\
524
525 \ ------------------------------\
526 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
527 \ ------------------------------\
528 \     ...                         \ init specific I/O sys as you want
529 \     ...                         \ before executing default WARM
530     MOV #WARM,X                 \ ['] WARM 
531     ADD #4,X                    \ >BODY
532     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
533 ENDASM
534 \ ------------------------------\
535
536 \ ------------------------------\
537 CODE STOP                       \ stops multitasking, must to be used before downloading app
538 \ ------------------------------\
539 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
540     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
541     MOV X,-2(X)                 \ restore the default background: SLEEP
542     MOV #WARM,X
543     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
544     BIC.B #RC5,&IR_IE           \ clear RC5_Int
545     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
546     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
547     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
548     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
549     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
550 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
551 ECHO                            \
552 ." RC5toLCD is removed,"
553 ."  type START to restart"
554  WARM                           \ performs reset to reset all interrupt vectors.    
555 ;
556 \ ------------------------------\
557
558 \ ------------------------------\
559 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
560 \ ------------------------------\
561 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
562 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
563 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
564 \                           --       \ID input divider \ 10 = /4
565 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
566 \                                 -  \TBCLR TimerB Clear
567 \                                  - \TBIE
568 \                                   -\TBIFG
569 \ -------------------------------\
570 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
571 \                  --                 \CM Capture Mode
572 \                    --               \CCIS
573 \                       -             \SCS
574 \                        --           \CLLD
575 \                          -          \CAP
576 \                            ---      \OUTMOD \ 011 = set/reset
577 \                               -     \CCIE
578 \                                 -   \CCI
579 \                                  -  \OUT
580 \                                   - \COV
581 \                                    -\CCIFG
582 \ -------------------------------\
583 \ LCD_TIM_CCRx                   \
584 \ -------------------------------\
585 \ LCD_TIM_EX0                    \ 
586 \ ------------------------------\
587 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
588 \ ------------------------------\
589 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
590 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
591 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
592     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
593 [THEN]
594 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
595     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
596 [THEN]
597     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
598 \ ------------------------------\
599 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
600 \ ------------------------------\
601 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
602     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
603 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
604 \ ------------------------------\
605     BIS.B #LCDVo,&LCDVo_DIR     \
606     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
607 \ ------------------------------\
608     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
609     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
610 \ ------------------------------\
611     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
612     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
613 \ ******************************\
614 \ init RC5_Int                  \
615 \ ******************************\
616     BIS.B #RC5,&IR_IE           \ enable RC5_Int
617     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
618     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
619 \ ******************************\
620 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
621 \ ******************************\
622 \              %01 0001 0100    \ TAxCTL
623 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
624 \                  --           \ ID        divided by 1
625 \                    --         \ MC        MODE = up to TAxCCRn
626 \                        -      \ TACLR     clear timer count
627 \                         -     \ TAIE
628 \                          -    \ TAIFG
629 \ ------------------------------\
630 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
631 \ ------------------------------\
632 \                        000    \ TAxEX0
633 \                        ---    \ TAIDEX    pre divisor
634 \ ------------------------------\
635 \          %0000 0000 0000 0101 \ TAxCCR0
636     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
637 \ ------------------------------\
638 \          %0000 0000 0001 0000 \ TAxCCTL0
639 \                   -           \ CAP capture/compare mode = compare
640 \                        -      \ CCIEn
641 \                             - \ CCIFGn
642     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
643 \ ------------------------------\
644     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
645 \ ------------------------------\
646 \ define LPM mode for ACCEPT    \
647 \ ------------------------------\
648 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
649 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
650 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
651 \ ------------------------------\
652 \ activate I/O                  \
653 \ ------------------------------\
654 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
655 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
656 \ ------------------------------\
657 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
658 \ ------------------------------\
659 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
660 \ CMP #2,Y                        \ Power_ON event
661 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
662 CMP #4,Y                        \
663 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
664 \ CMP #6,Y                        \
665 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
666 \ CMP #$0A,Y                      \
667 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
668 \ CMP #$16,Y                      \
669 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
670 \ ------------------------------\
671 COLON                           \
672 \ ------------------------------\
673 \ Init LCD 2x20                 \
674 \ ------------------------------\
675     #1000 20_US                 \ 1- wait 20 ms
676     %011 TOP_LCD                \ 2- send DB5=DB4=1
677     #205 20_US                  \ 3- wait 4,1 ms
678     %011 TOP_LCD                \ 4- send again DB5=DB4=1
679     #5 20_US                    \ 5- wait 0,1 ms
680     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
681     #2 20_US                    \    wait 40 us = LCD cycle
682     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
683     #2 20_US                    \    wait 40 us = LCD cycle
684     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
685     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
686     LCD_CLEAR                   \ 10- "LCD_Clear"
687     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
688     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
689     LCD_CLEAR                   \ 10- "LCD_Clear"
690     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
691     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
692     CR ." I love you"           \ display message on LCD
693     ['] CR >BODY IS CR          \ CR executes its default value
694     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
695     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
696     PWR_STATE ABORT             \ init DP and continues with ABORT
697 ;                               \
698 \ ------------------------------\
699
700 \ ------------------------------\
701 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
702 \ ------------------------------\
703 MOV #SLEEP,X                    \ replace default background process SLEEP
704 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
705 MOV #WARM,X                     \ replace default WARM
706 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
707 MOV X,PC                        \ then execute new WARM
708 ENDCODE 
709 \ ------------------------------\
710
711 ECHO
712             ; downloading RC5toLCD.4th is done
713 RST_HERE    ; this app is protected against <reset>
714
715
716 RST_STATE
717
718 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
719
720 [UNDEFINED] MARKER [IF]
721 \  https://forth-standard.org/standard/core/MARKER
722 \  MARKER
723 \ ( "<spaces>name" -- )
724 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
725 \ with the execution semantics defined below.
726
727 \ name Execution: ( -- )
728 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
729 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
730 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
731 \ not necessarily provided. No other contextual information such as numeric base is affected
732 \
733 : MARKER
734 CREATE
735 HI2LO
736 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
737 SUB #2,Y            \ 1 Y = LFA
738 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
739 ADD #4,&DP          \ 3 add 2 cells
740 LO2HI
741 DOES>
742 HI2LO
743 MOV @RSP+,IP        \ -- PFA
744 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
745 MOV @TOS,&INIDP     \       set DP value for RST_STATE
746 MOV @PSP+,TOS       \ --
747 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
748 ENDCODE
749 [THEN]
750
751 MARKER {RC5TOLCD}
752
753 [UNDEFINED] @ [IF]
754 \ https://forth-standard.org/standard/core/Fetch
755 \ @     c-addr -- char   fetch char from memory
756 CODE @
757 MOV @TOS,TOS
758 MOV @IP+,PC
759 ENDCODE
760 [THEN]
761
762 [UNDEFINED] CONSTANT [IF]
763 \ https://forth-standard.org/standard/core/CONSTANT
764 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
765 : CONSTANT 
766 CREATE
767 HI2LO
768 MOV TOS,-2(W)           \   PFA = n
769 MOV @PSP+,TOS
770 MOV @RSP+,IP
771 MOV @IP+,PC
772 ENDCODE
773 [THEN]
774
775 [UNDEFINED] STATE [IF]
776 \ https://forth-standard.org/standard/core/STATE
777 \ STATE   -- a-addr       holds compiler state
778 STATEADR CONSTANT STATE
779 [THEN]
780
781 [UNDEFINED] = [IF]
782 \ https://forth-standard.org/standard/core/Equal
783 \ =      x1 x2 -- flag         test x1=x2
784 CODE =
785 SUB @PSP+,TOS   \ 2
786 0<> IF          \ 2
787     AND #0,TOS  \ 1
788     MOV @IP+,PC \ 4
789 THEN
790 XOR #-1,TOS     \ 1 flag Z = 1
791 MOV @IP+,PC     \ 4
792 ENDCODE
793 [THEN]
794
795 [UNDEFINED] IF [IF]
796 \ https://forth-standard.org/standard/core/IF
797 \ IF       -- IFadr    initialize conditional forward branch
798 CODE IF       \ immediate
799 SUB #2,PSP              \
800 MOV TOS,0(PSP)          \
801 MOV &DP,TOS             \ -- HERE
802 ADD #4,&DP            \           compile one word, reserve one word
803 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
804 ADD #2,TOS              \ -- HERE+2=IFadr
805 MOV @IP+,PC
806 ENDCODE IMMEDIATE
807 [THEN]
808
809 [UNDEFINED] THEN [IF]
810 \ https://forth-standard.org/standard/core/THEN
811 \ THEN     IFadr --                resolve forward branch
812 CODE THEN               \ immediate
813 MOV &DP,0(TOS)          \ -- IFadr
814 MOV @PSP+,TOS           \ --
815 MOV @IP+,PC
816 ENDCODE IMMEDIATE
817 [THEN]
818
819 [UNDEFINED] ELSE [IF]
820 \ https://forth-standard.org/standard/core/ELSE
821 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
822 CODE ELSE     \ immediate
823 ADD #4,&DP              \ make room to compile two words
824 MOV &DP,W               \ W=HERE+4
825 MOV #BRAN,-4(W)
826 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
827 SUB #2,W                \ HERE+2
828 MOV W,TOS               \ -- ELSEadr
829 MOV @IP+,PC
830 ENDCODE IMMEDIATE
831 [THEN]
832
833 [UNDEFINED] DEFER [IF]
834 \ https://forth-standard.org/standard/core/DEFER
835 \ DEFER "<spaces>name"   --
836 \ Skip leading space delimiters. Parse name delimited by a space.
837 \ Create a definition for name with the execution semantics defined below.
838
839 \ name Execution:   --
840 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
841 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
842 : DEFER
843 CREATE
844 HI2LO
845 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
846 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
847 MOV @RSP+,IP
848 MOV @IP+,PC
849 ENDCODE
850 [THEN]
851
852 [UNDEFINED] DEFER! [IF]
853 \ https://forth-standard.org/standard/core/DEFERStore
854 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
855 CODE DEFER!             \ xt2 xt1 --
856 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
857 MOV @PSP+,TOS           \ --
858 MOV @IP+,PC
859 ENDCODE
860 [THEN]
861
862 [UNDEFINED] IS [IF]
863 \ https://forth-standard.org/standard/core/IS
864 \ IS <name>        xt --
865 \ used as is :
866 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
867 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
868 \ or in a definition : ... ['] U. IS DISPLAY ...
869 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
870 \
871 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
872 : IS
873 STATE @
874 IF  POSTPONE ['] POSTPONE DEFER! 
875 ELSE ' DEFER! 
876 THEN
877 ; IMMEDIATE
878 [THEN]
879
880 [UNDEFINED] >BODY [IF]
881 \ https://forth-standard.org/standard/core/toBODY
882 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
883 CODE >BODY
884 ADD #4,TOS
885 MOV @IP+,PC
886 ENDCODE
887 [THEN]
888
889 \ CODE 20uS           \ n --      8MHz version
890 \ BEGIN               \ 4 + 16 ~ loop
891 \     MOV #39,rDOCON   \ 39
892 \     BEGIN           \ 4 ~ loop
893 \         NOP
894 \         SUB #1,rDOCON
895 \     0=  UNTIL
896 \     SUB #1,TOS      \ 1
897 \ 0= UNTIL
898 \ MOV #XDOCON,rDOCON  \ 2
899 \ MOV @PSP+,TOS
900 \ MOV @RSP+,IP        \
901 \ ENDCODE
902
903 CODE 20_US                      \ n --      n * 20 us
904 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
905     BEGIN
906         BIT #1,&LCD_TIM_CTL     \ 3
907     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
908     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
909     SUB #1,TOS                  \ 1
910 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
911 MOV @PSP+,TOS                   \ 2
912 MOV @IP+,PC                     \ 4
913 ENDCODE
914
915 CODE TOP_LCD                    \ LCD Sample
916 \                               \ if write : %xxxx_WWWW --
917 \                               \ if read  : -- %0000_RRRR
918     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
919     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
920 0= IF                           \ write LCD bits pattern
921     AND.B #LCD_DB,TOS           \ 
922     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
923     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
924     MOV @PSP+,TOS               \
925     MOV @IP+,PC
926 THEN                            \ read LCD bits pattern
927     SUB #2,PSP
928     MOV TOS,0(PSP)
929     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
930     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
931     AND.B #LCD_DB,TOS           \
932     MOV @IP+,PC
933 ENDCODE
934
935 CODE LCD_WRC                    \ char --         Write Char
936     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
937 BW1 SUB #2,PSP                  \
938     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
939     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
940     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
941     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
942 COLON                           \ high level word starts here 
943     TOP_LCD 2 20_US             \ write high nibble first
944     TOP_LCD 2 20_US 
945 ;
946
947 CODE LCD_WRF                    \ func --         Write Fonction
948     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
949     GOTO BW1
950 ENDCODE
951
952 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
953 : LCD_HOME $02 LCD_WRF 100 20_us ;
954
955 \ [UNDEFINED] OR [IF]
956
957 \ \ https://forth-standard.org/standard/core/OR
958 \ \ C OR     x1 x2 -- x3           logical OR
959 \ CODE OR
960 \ BIS @PSP+,TOS
961 \ MOV @IP+,PC
962 \ ENDCODE
963
964 \ [THEN]
965
966 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
967 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
968 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
969 \ : LCD_FN_SET        $20 OR LCD_WrF ;
970 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
971 \ : LCD_GOTO          $80 OR LCD_WrF ;
972
973
974 \ CODE LCD_RDS                    \ -- status       Read Status
975 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
976 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
977 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
978 \ COLON                           \ starts a FORTH word
979 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
980 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
981 \ HI2LO                           \ switch from FORTH to assembler
982 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
983 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
984 \     MOV @RSP+,IP                \ restore IP saved by COLON
985 \     MOV @IP+,PC                 \
986 \ ENDCODE
987
988 \ CODE LCD_RDC                    \ -- char         Read Char
989 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
990 \     GOTO BW1
991 \ ENDCODE
992
993
994 \ ******************************\
995 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
996 \ ******************************\
997 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
998 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
999 BIT.B #SW2,&SW2_IN              \ test switch S2
1000 0= IF                           \ case of switch S2 pressed
1001     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
1002     U< IF
1003         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
1004     THEN
1005 ELSE
1006     BIT.B #SW1,&SW1_IN          \ test switch S1 input
1007     0= IF                       \ case of Switch S1 pressed
1008         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
1009         U>= IF                  \
1010            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
1011         THEN                    \
1012     THEN                        \
1013 THEN                            \
1014 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
1015 RET                             \ 5
1016 ENDASM
1017
1018 \ ******************************\
1019 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
1020 \ ******************************\
1021 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
1022 \ ******************************\
1023 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
1024 \                               \       SMclock = 8|16|24 MHz
1025 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
1026 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
1027 \                               \       SR(9)=new Toggle bit memory (ADD on)
1028 \ ******************************\
1029 \ RC5_FirstStartBitHalfCycle:   \
1030 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
1031 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
1032 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
1033 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
1034 \ [THEN]
1035 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
1036     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
1037 [THEN]
1038 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
1039     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
1040 [THEN]
1041 MOV #1778,X                     \ RC5_Period * 1us
1042 MOV #14,W                       \ count of loop
1043 BEGIN                           \
1044 \ ******************************\
1045 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
1046 \ ******************************\                   |
1047 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
1048 \ RC5_Compute_3/4_Period:       \                   |
1049     RRUM    #1,X                \ X=1/2 cycle       |
1050     MOV     X,Y                 \                   ^
1051     RRUM    #1,Y                \ Y=1/4
1052     ADD     X,Y                 \ Y=3/4 cycle
1053     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
1054     U>= UNTIL                   \ 2
1055 \ ******************************\
1056 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
1057 \ ******************************\
1058     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
1059     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
1060     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
1061     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
1062     SUB     #1,W                \ decrement count loop
1063 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
1064 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
1065 0<> WHILE                       \ ----> out of loop ----+
1066     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
1067     BEGIN                       \                       |
1068         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
1069         CMP Y,X                 \ 1                     |   cycle time out of bound ?
1070         U>= IF                  \ 2                 ^   |   yes:
1071         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
1072         GOTO BW1                \                   |   |      quit on truncated RC5 message
1073         THEN                    \                   |   |
1074         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
1075     0<> UNTIL                   \ 2                 |   |
1076 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
1077 \ ******************************\                       |
1078 \ RC5_SampleEndOf:              \ <---------------------+
1079 \ ******************************\
1080 BIC #$30,&RC5_TIM_CTL           \   stop timer
1081 \ ******************************\
1082 \ RC5_ComputeNewRC5word         \
1083 \ ******************************\
1084 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
1085 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
1086 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
1087 \ ******************************\
1088 \ RC5_ComputeC6bit              \
1089 \ ******************************\
1090 BIT     #BIT14,T                \ test /C6 bit in T
1091 0= IF   BIS #BIT6,X             \ set C6 bit in X
1092 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
1093 \ ******************************\
1094 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
1095 \ ******************************\
1096 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
1097 \ ******************************\
1098 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
1099 XOR     @RSP,T                  \ (new XOR old) Toggle bits
1100 BIT     #UF10,T                 \ repeated RC5_command ?
1101 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
1102 XOR #UF10,0(RSP)                \ 5 toggle bit memory
1103 \ ******************************\
1104 \ Display IR_RC5 code           \
1105 \ ******************************\
1106 SUB #8,PSP                      \ TOS -- x x x x TOS
1107 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
1108 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
1109 MOV #$10,&BASEADR               \                                               set hexadecimal base
1110 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
1111 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
1112 LO2HI                           \                                               switch from assembler to FORTH
1113     LCD_CLEAR                   \                                               set LCD cursor at home
1114     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
1115     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
1116     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
1117     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
1118 HI2LO                           \     --                                        switch from FORTH to assembler
1119 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
1120 MOV @PSP+,TOS                   \     -- TOS
1121 RET
1122 ENDASM
1123
1124 \ ******************************\
1125 ASM BACKGROUND                  \
1126 \ ******************************\
1127 BEGIN
1128 \     ...                         \ insert here your background task
1129 \     ...                         \
1130 \     ...                         \
1131     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
1132     BIS &LPM_MODE,SR            \
1133 \ ******************************\
1134 \ here start all interrupts     \
1135 \ ******************************\
1136 \ here return all interrupts    \
1137 \ ******************************\
1138 AGAIN                           \
1139 ENDASM                          \
1140 \ ******************************\
1141
1142 \ ------------------------------\
1143 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
1144 \ ------------------------------\
1145 \     ...                         \ init specific I/O sys as you want
1146 \     ...                         \ before executing default WARM
1147     MOV #WARM,X                 \ ['] WARM 
1148     ADD #4,X                    \ >BODY
1149     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
1150 ENDASM
1151 \ ------------------------------\
1152
1153 \ ------------------------------\
1154 CODE STOP                       \ stops multitasking, must to be used before downloading app
1155 \ ------------------------------\
1156 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
1157     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
1158     MOV X,-2(X)                 \ restore the default background: SLEEP
1159     MOV #WARM,X
1160     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
1161     BIC.B #RC5,&IR_IE           \ clear RC5_Int
1162     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
1163     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
1164     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
1165     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
1166     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
1167 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
1168 ECHO                            \
1169 ." RC5toLCD is removed,"
1170 ."  type START to restart"
1171  WARM                           \ performs reset to reset all interrupt vectors.    
1172 ;
1173 \ ------------------------------\
1174
1175 \ ------------------------------\
1176 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
1177 \ ------------------------------\
1178 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
1179 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
1180 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
1181 \                           --       \ID input divider \ 10 = /4
1182 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
1183 \                                 -  \TBCLR TimerB Clear
1184 \                                  - \TBIE
1185 \                                   -\TBIFG
1186 \ -------------------------------\
1187 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
1188 \                  --                 \CM Capture Mode
1189 \                    --               \CCIS
1190 \                       -             \SCS
1191 \                        --           \CLLD
1192 \                          -          \CAP
1193 \                            ---      \OUTMOD \ 011 = set/reset
1194 \                               -     \CCIE
1195 \                                 -   \CCI
1196 \                                  -  \OUT
1197 \                                   - \COV
1198 \                                    -\CCIFG
1199 \ -------------------------------\
1200 \ LCD_TIM_CCRx                   \
1201 \ -------------------------------\
1202 \ LCD_TIM_EX0                    \ 
1203 \ ------------------------------\
1204 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
1205 \ ------------------------------\
1206 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
1207 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
1208 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
1209     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
1210 [THEN]
1211 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
1212     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
1213 [THEN]
1214     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
1215 \ ------------------------------\
1216 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
1217 \ ------------------------------\
1218 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
1219     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
1220 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
1221 \ ------------------------------\
1222     BIS.B #LCDVo,&LCDVo_DIR     \
1223     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
1224 \ ------------------------------\
1225     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
1226     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
1227 \ ------------------------------\
1228     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
1229     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
1230 \ ******************************\
1231 \ init RC5_Int                  \
1232 \ ******************************\
1233     BIS.B #RC5,&IR_IE           \ enable RC5_Int
1234     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
1235     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
1236 \ ******************************\
1237 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
1238 \ ******************************\
1239 \              %01 0001 0100    \ TAxCTL
1240 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
1241 \                  --           \ ID        divided by 1
1242 \                    --         \ MC        MODE = up to TAxCCRn
1243 \                        -      \ TACLR     clear timer count
1244 \                         -     \ TAIE
1245 \                          -    \ TAIFG
1246 \ ------------------------------\
1247 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
1248 \ ------------------------------\
1249 \                        000    \ TAxEX0
1250 \                        ---    \ TAIDEX    pre divisor
1251 \ ------------------------------\
1252 \          %0000 0000 0000 0101 \ TAxCCR0
1253     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
1254 \ ------------------------------\
1255 \          %0000 0000 0001 0000 \ TAxCCTL0
1256 \                   -           \ CAP capture/compare mode = compare
1257 \                        -      \ CCIEn
1258 \                             - \ CCIFGn
1259     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
1260 \ ------------------------------\
1261     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
1262 \ ------------------------------\
1263 \ define LPM mode for ACCEPT    \
1264 \ ------------------------------\
1265 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
1266 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1267 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1268 \ ------------------------------\
1269 \ activate I/O                  \
1270 \ ------------------------------\
1271 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
1272 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
1273 \ ------------------------------\
1274 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
1275 \ ------------------------------\
1276 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
1277 \ CMP #2,Y                        \ Power_ON event
1278 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
1279 CMP #4,Y                        \
1280 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
1281 \ CMP #6,Y                        \
1282 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
1283 \ CMP #$0A,Y                      \
1284 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
1285 \ CMP #$16,Y                      \
1286 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
1287 \ ------------------------------\
1288 COLON                           \
1289 \ ------------------------------\
1290 \ Init LCD 2x20                 \
1291 \ ------------------------------\
1292     #1000 20_US                 \ 1- wait 20 ms
1293     %011 TOP_LCD                \ 2- send DB5=DB4=1
1294     #205 20_US                  \ 3- wait 4,1 ms
1295     %011 TOP_LCD                \ 4- send again DB5=DB4=1
1296     #5 20_US                    \ 5- wait 0,1 ms
1297     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
1298     #2 20_US                    \    wait 40 us = LCD cycle
1299     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
1300     #2 20_US                    \    wait 40 us = LCD cycle
1301     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
1302     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
1303     LCD_CLEAR                   \ 10- "LCD_Clear"
1304     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
1305     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
1306     LCD_CLEAR                   \ 10- "LCD_Clear"
1307     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
1308     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
1309     CR ." I love you"           \ display message on LCD
1310     ['] CR >BODY IS CR          \ CR executes its default value
1311     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
1312     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
1313     PWR_STATE ABORT             \ init DP and continues with ABORT
1314 ;                               \
1315 \ ------------------------------\
1316
1317 \ ------------------------------\
1318 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
1319 \ ------------------------------\
1320 MOV #SLEEP,X                    \ replace default background process SLEEP
1321 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
1322 MOV #WARM,X                     \ replace default WARM
1323 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
1324 MOV X,PC                        \ then execute new WARM
1325 ENDCODE 
1326 \ ------------------------------\
1327
1328 ECHO
1329             ; downloading RC5toLCD.4th is done
1330 RST_HERE    ; this app is protected against <reset>
1331
1332
1333 RST_STATE
1334
1335 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
1336
1337 [UNDEFINED] MARKER [IF]
1338 \  https://forth-standard.org/standard/core/MARKER
1339 \  MARKER
1340 \ ( "<spaces>name" -- )
1341 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
1342 \ with the execution semantics defined below.
1343
1344 \ name Execution: ( -- )
1345 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
1346 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
1347 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
1348 \ not necessarily provided. No other contextual information such as numeric base is affected
1349 \
1350 : MARKER
1351 CREATE
1352 HI2LO
1353 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
1354 SUB #2,Y            \ 1 Y = LFA
1355 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
1356 ADD #4,&DP          \ 3 add 2 cells
1357 LO2HI
1358 DOES>
1359 HI2LO
1360 MOV @RSP+,IP        \ -- PFA
1361 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
1362 MOV @TOS,&INIDP     \       set DP value for RST_STATE
1363 MOV @PSP+,TOS       \ --
1364 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
1365 ENDCODE
1366 [THEN]
1367
1368 MARKER {RC5TOLCD}
1369
1370 [UNDEFINED] @ [IF]
1371 \ https://forth-standard.org/standard/core/Fetch
1372 \ @     c-addr -- char   fetch char from memory
1373 CODE @
1374 MOV @TOS,TOS
1375 MOV @IP+,PC
1376 ENDCODE
1377 [THEN]
1378
1379 [UNDEFINED] CONSTANT [IF]
1380 \ https://forth-standard.org/standard/core/CONSTANT
1381 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
1382 : CONSTANT 
1383 CREATE
1384 HI2LO
1385 MOV TOS,-2(W)           \   PFA = n
1386 MOV @PSP+,TOS
1387 MOV @RSP+,IP
1388 MOV @IP+,PC
1389 ENDCODE
1390 [THEN]
1391
1392 [UNDEFINED] STATE [IF]
1393 \ https://forth-standard.org/standard/core/STATE
1394 \ STATE   -- a-addr       holds compiler state
1395 STATEADR CONSTANT STATE
1396 [THEN]
1397
1398 [UNDEFINED] = [IF]
1399 \ https://forth-standard.org/standard/core/Equal
1400 \ =      x1 x2 -- flag         test x1=x2
1401 CODE =
1402 SUB @PSP+,TOS   \ 2
1403 0<> IF          \ 2
1404     AND #0,TOS  \ 1
1405     MOV @IP+,PC \ 4
1406 THEN
1407 XOR #-1,TOS     \ 1 flag Z = 1
1408 MOV @IP+,PC     \ 4
1409 ENDCODE
1410 [THEN]
1411
1412 [UNDEFINED] IF [IF]
1413 \ https://forth-standard.org/standard/core/IF
1414 \ IF       -- IFadr    initialize conditional forward branch
1415 CODE IF       \ immediate
1416 SUB #2,PSP              \
1417 MOV TOS,0(PSP)          \
1418 MOV &DP,TOS             \ -- HERE
1419 ADD #4,&DP            \           compile one word, reserve one word
1420 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
1421 ADD #2,TOS              \ -- HERE+2=IFadr
1422 MOV @IP+,PC
1423 ENDCODE IMMEDIATE
1424 [THEN]
1425
1426 [UNDEFINED] THEN [IF]
1427 \ https://forth-standard.org/standard/core/THEN
1428 \ THEN     IFadr --                resolve forward branch
1429 CODE THEN               \ immediate
1430 MOV &DP,0(TOS)          \ -- IFadr
1431 MOV @PSP+,TOS           \ --
1432 MOV @IP+,PC
1433 ENDCODE IMMEDIATE
1434 [THEN]
1435
1436 [UNDEFINED] ELSE [IF]
1437 \ https://forth-standard.org/standard/core/ELSE
1438 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
1439 CODE ELSE     \ immediate
1440 ADD #4,&DP              \ make room to compile two words
1441 MOV &DP,W               \ W=HERE+4
1442 MOV #BRAN,-4(W)
1443 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
1444 SUB #2,W                \ HERE+2
1445 MOV W,TOS               \ -- ELSEadr
1446 MOV @IP+,PC
1447 ENDCODE IMMEDIATE
1448 [THEN]
1449
1450 [UNDEFINED] DEFER [IF]
1451 \ https://forth-standard.org/standard/core/DEFER
1452 \ DEFER "<spaces>name"   --
1453 \ Skip leading space delimiters. Parse name delimited by a space.
1454 \ Create a definition for name with the execution semantics defined below.
1455
1456 \ name Execution:   --
1457 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
1458 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
1459 : DEFER
1460 CREATE
1461 HI2LO
1462 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
1463 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
1464 MOV @RSP+,IP
1465 MOV @IP+,PC
1466 ENDCODE
1467 [THEN]
1468
1469 [UNDEFINED] DEFER! [IF]
1470 \ https://forth-standard.org/standard/core/DEFERStore
1471 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
1472 CODE DEFER!             \ xt2 xt1 --
1473 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
1474 MOV @PSP+,TOS           \ --
1475 MOV @IP+,PC
1476 ENDCODE
1477 [THEN]
1478
1479 [UNDEFINED] IS [IF]
1480 \ https://forth-standard.org/standard/core/IS
1481 \ IS <name>        xt --
1482 \ used as is :
1483 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
1484 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
1485 \ or in a definition : ... ['] U. IS DISPLAY ...
1486 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
1487 \
1488 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
1489 : IS
1490 STATE @
1491 IF  POSTPONE ['] POSTPONE DEFER! 
1492 ELSE ' DEFER! 
1493 THEN
1494 ; IMMEDIATE
1495 [THEN]
1496
1497 [UNDEFINED] >BODY [IF]
1498 \ https://forth-standard.org/standard/core/toBODY
1499 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
1500 CODE >BODY
1501 ADD #4,TOS
1502 MOV @IP+,PC
1503 ENDCODE
1504 [THEN]
1505
1506 \ CODE 20uS           \ n --      8MHz version
1507 \ BEGIN               \ 4 + 16 ~ loop
1508 \     MOV #39,rDOCON   \ 39
1509 \     BEGIN           \ 4 ~ loop
1510 \         NOP
1511 \         SUB #1,rDOCON
1512 \     0=  UNTIL
1513 \     SUB #1,TOS      \ 1
1514 \ 0= UNTIL
1515 \ MOV #XDOCON,rDOCON  \ 2
1516 \ MOV @PSP+,TOS
1517 \ MOV @RSP+,IP        \
1518 \ ENDCODE
1519
1520 CODE 20_US                      \ n --      n * 20 us
1521 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
1522     BEGIN
1523         BIT #1,&LCD_TIM_CTL     \ 3
1524     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
1525     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
1526     SUB #1,TOS                  \ 1
1527 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
1528 MOV @PSP+,TOS                   \ 2
1529 MOV @IP+,PC                     \ 4
1530 ENDCODE
1531
1532 CODE TOP_LCD                    \ LCD Sample
1533 \                               \ if write : %xxxx_WWWW --
1534 \                               \ if read  : -- %0000_RRRR
1535     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
1536     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
1537 0= IF                           \ write LCD bits pattern
1538     AND.B #LCD_DB,TOS           \ 
1539     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
1540     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
1541     MOV @PSP+,TOS               \
1542     MOV @IP+,PC
1543 THEN                            \ read LCD bits pattern
1544     SUB #2,PSP
1545     MOV TOS,0(PSP)
1546     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
1547     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
1548     AND.B #LCD_DB,TOS           \
1549     MOV @IP+,PC
1550 ENDCODE
1551
1552 CODE LCD_WRC                    \ char --         Write Char
1553     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
1554 BW1 SUB #2,PSP                  \
1555     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
1556     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
1557     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
1558     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
1559 COLON                           \ high level word starts here 
1560     TOP_LCD 2 20_US             \ write high nibble first
1561     TOP_LCD 2 20_US 
1562 ;
1563
1564 CODE LCD_WRF                    \ func --         Write Fonction
1565     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
1566     GOTO BW1
1567 ENDCODE
1568
1569 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
1570 : LCD_HOME $02 LCD_WRF 100 20_us ;
1571
1572 \ [UNDEFINED] OR [IF]
1573
1574 \ \ https://forth-standard.org/standard/core/OR
1575 \ \ C OR     x1 x2 -- x3           logical OR
1576 \ CODE OR
1577 \ BIS @PSP+,TOS
1578 \ MOV @IP+,PC
1579 \ ENDCODE
1580
1581 \ [THEN]
1582
1583 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
1584 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
1585 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
1586 \ : LCD_FN_SET        $20 OR LCD_WrF ;
1587 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
1588 \ : LCD_GOTO          $80 OR LCD_WrF ;
1589
1590
1591 \ CODE LCD_RDS                    \ -- status       Read Status
1592 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
1593 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
1594 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
1595 \ COLON                           \ starts a FORTH word
1596 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
1597 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
1598 \ HI2LO                           \ switch from FORTH to assembler
1599 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
1600 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
1601 \     MOV @RSP+,IP                \ restore IP saved by COLON
1602 \     MOV @IP+,PC                 \
1603 \ ENDCODE
1604
1605 \ CODE LCD_RDC                    \ -- char         Read Char
1606 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
1607 \     GOTO BW1
1608 \ ENDCODE
1609
1610
1611 \ ******************************\
1612 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
1613 \ ******************************\
1614 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
1615 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
1616 BIT.B #SW2,&SW2_IN              \ test switch S2
1617 0= IF                           \ case of switch S2 pressed
1618     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
1619     U< IF
1620         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
1621     THEN
1622 ELSE
1623     BIT.B #SW1,&SW1_IN          \ test switch S1 input
1624     0= IF                       \ case of Switch S1 pressed
1625         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
1626         U>= IF                  \
1627            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
1628         THEN                    \
1629     THEN                        \
1630 THEN                            \
1631 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
1632 RET                             \ 5
1633 ENDASM
1634
1635 \ ******************************\
1636 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
1637 \ ******************************\
1638 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
1639 \ ******************************\
1640 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
1641 \                               \       SMclock = 8|16|24 MHz
1642 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
1643 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
1644 \                               \       SR(9)=new Toggle bit memory (ADD on)
1645 \ ******************************\
1646 \ RC5_FirstStartBitHalfCycle:   \
1647 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
1648 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
1649 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
1650 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
1651 \ [THEN]
1652 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
1653     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
1654 [THEN]
1655 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
1656     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
1657 [THEN]
1658 MOV #1778,X                     \ RC5_Period * 1us
1659 MOV #14,W                       \ count of loop
1660 BEGIN                           \
1661 \ ******************************\
1662 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
1663 \ ******************************\                   |
1664 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
1665 \ RC5_Compute_3/4_Period:       \                   |
1666     RRUM    #1,X                \ X=1/2 cycle       |
1667     MOV     X,Y                 \                   ^
1668     RRUM    #1,Y                \ Y=1/4
1669     ADD     X,Y                 \ Y=3/4 cycle
1670     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
1671     U>= UNTIL                   \ 2
1672 \ ******************************\
1673 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
1674 \ ******************************\
1675     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
1676     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
1677     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
1678     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
1679     SUB     #1,W                \ decrement count loop
1680 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
1681 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
1682 0<> WHILE                       \ ----> out of loop ----+
1683     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
1684     BEGIN                       \                       |
1685         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
1686         CMP Y,X                 \ 1                     |   cycle time out of bound ?
1687         U>= IF                  \ 2                 ^   |   yes:
1688         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
1689         GOTO BW1                \                   |   |      quit on truncated RC5 message
1690         THEN                    \                   |   |
1691         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
1692     0<> UNTIL                   \ 2                 |   |
1693 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
1694 \ ******************************\                       |
1695 \ RC5_SampleEndOf:              \ <---------------------+
1696 \ ******************************\
1697 BIC #$30,&RC5_TIM_CTL           \   stop timer
1698 \ ******************************\
1699 \ RC5_ComputeNewRC5word         \
1700 \ ******************************\
1701 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
1702 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
1703 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
1704 \ ******************************\
1705 \ RC5_ComputeC6bit              \
1706 \ ******************************\
1707 BIT     #BIT14,T                \ test /C6 bit in T
1708 0= IF   BIS #BIT6,X             \ set C6 bit in X
1709 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
1710 \ ******************************\
1711 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
1712 \ ******************************\
1713 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
1714 \ ******************************\
1715 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
1716 XOR     @RSP,T                  \ (new XOR old) Toggle bits
1717 BIT     #UF10,T                 \ repeated RC5_command ?
1718 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
1719 XOR #UF10,0(RSP)                \ 5 toggle bit memory
1720 \ ******************************\
1721 \ Display IR_RC5 code           \
1722 \ ******************************\
1723 SUB #8,PSP                      \ TOS -- x x x x TOS
1724 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
1725 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
1726 MOV #$10,&BASEADR               \                                               set hexadecimal base
1727 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
1728 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
1729 LO2HI                           \                                               switch from assembler to FORTH
1730     LCD_CLEAR                   \                                               set LCD cursor at home
1731     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
1732     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
1733     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
1734     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
1735 HI2LO                           \     --                                        switch from FORTH to assembler
1736 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
1737 MOV @PSP+,TOS                   \     -- TOS
1738 RET
1739 ENDASM
1740
1741 \ ******************************\
1742 ASM BACKGROUND                  \
1743 \ ******************************\
1744 BEGIN
1745 \     ...                         \ insert here your background task
1746 \     ...                         \
1747 \     ...                         \
1748     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
1749     BIS &LPM_MODE,SR            \
1750 \ ******************************\
1751 \ here start all interrupts     \
1752 \ ******************************\
1753 \ here return all interrupts    \
1754 \ ******************************\
1755 AGAIN                           \
1756 ENDASM                          \
1757 \ ******************************\
1758
1759 \ ------------------------------\
1760 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
1761 \ ------------------------------\
1762 \     ...                         \ init specific I/O sys as you want
1763 \     ...                         \ before executing default WARM
1764     MOV #WARM,X                 \ ['] WARM 
1765     ADD #4,X                    \ >BODY
1766     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
1767 ENDASM
1768 \ ------------------------------\
1769
1770 \ ------------------------------\
1771 CODE STOP                       \ stops multitasking, must to be used before downloading app
1772 \ ------------------------------\
1773 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
1774     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
1775     MOV X,-2(X)                 \ restore the default background: SLEEP
1776     MOV #WARM,X
1777     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
1778     BIC.B #RC5,&IR_IE           \ clear RC5_Int
1779     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
1780     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
1781     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
1782     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
1783     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
1784 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
1785 ECHO                            \
1786 ." RC5toLCD is removed,"
1787 ."  type START to restart"
1788  WARM                           \ performs reset to reset all interrupt vectors.    
1789 ;
1790 \ ------------------------------\
1791
1792 \ ------------------------------\
1793 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
1794 \ ------------------------------\
1795 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
1796 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
1797 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
1798 \                           --       \ID input divider \ 10 = /4
1799 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
1800 \                                 -  \TBCLR TimerB Clear
1801 \                                  - \TBIE
1802 \                                   -\TBIFG
1803 \ -------------------------------\
1804 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
1805 \                  --                 \CM Capture Mode
1806 \                    --               \CCIS
1807 \                       -             \SCS
1808 \                        --           \CLLD
1809 \                          -          \CAP
1810 \                            ---      \OUTMOD \ 011 = set/reset
1811 \                               -     \CCIE
1812 \                                 -   \CCI
1813 \                                  -  \OUT
1814 \                                   - \COV
1815 \                                    -\CCIFG
1816 \ -------------------------------\
1817 \ LCD_TIM_CCRx                   \
1818 \ -------------------------------\
1819 \ LCD_TIM_EX0                    \ 
1820 \ ------------------------------\
1821 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
1822 \ ------------------------------\
1823 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
1824 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
1825 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
1826     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
1827 [THEN]
1828 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
1829     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
1830 [THEN]
1831     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
1832 \ ------------------------------\
1833 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
1834 \ ------------------------------\
1835 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
1836     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
1837 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
1838 \ ------------------------------\
1839     BIS.B #LCDVo,&LCDVo_DIR     \
1840     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
1841 \ ------------------------------\
1842     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
1843     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
1844 \ ------------------------------\
1845     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
1846     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
1847 \ ******************************\
1848 \ init RC5_Int                  \
1849 \ ******************************\
1850     BIS.B #RC5,&IR_IE           \ enable RC5_Int
1851     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
1852     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
1853 \ ******************************\
1854 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
1855 \ ******************************\
1856 \              %01 0001 0100    \ TAxCTL
1857 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
1858 \                  --           \ ID        divided by 1
1859 \                    --         \ MC        MODE = up to TAxCCRn
1860 \                        -      \ TACLR     clear timer count
1861 \                         -     \ TAIE
1862 \                          -    \ TAIFG
1863 \ ------------------------------\
1864 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
1865 \ ------------------------------\
1866 \                        000    \ TAxEX0
1867 \                        ---    \ TAIDEX    pre divisor
1868 \ ------------------------------\
1869 \          %0000 0000 0000 0101 \ TAxCCR0
1870     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
1871 \ ------------------------------\
1872 \          %0000 0000 0001 0000 \ TAxCCTL0
1873 \                   -           \ CAP capture/compare mode = compare
1874 \                        -      \ CCIEn
1875 \                             - \ CCIFGn
1876     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
1877 \ ------------------------------\
1878     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
1879 \ ------------------------------\
1880 \ define LPM mode for ACCEPT    \
1881 \ ------------------------------\
1882 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
1883 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1884 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1885 \ ------------------------------\
1886 \ activate I/O                  \
1887 \ ------------------------------\
1888 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
1889 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
1890 \ ------------------------------\
1891 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
1892 \ ------------------------------\
1893 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
1894 \ CMP #2,Y                        \ Power_ON event
1895 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
1896 CMP #4,Y                        \
1897 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
1898 \ CMP #6,Y                        \
1899 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
1900 \ CMP #$0A,Y                      \
1901 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
1902 \ CMP #$16,Y                      \
1903 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
1904 \ ------------------------------\
1905 COLON                           \
1906 \ ------------------------------\
1907 \ Init LCD 2x20                 \
1908 \ ------------------------------\
1909     #1000 20_US                 \ 1- wait 20 ms
1910     %011 TOP_LCD                \ 2- send DB5=DB4=1
1911     #205 20_US                  \ 3- wait 4,1 ms
1912     %011 TOP_LCD                \ 4- send again DB5=DB4=1
1913     #5 20_US                    \ 5- wait 0,1 ms
1914     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
1915     #2 20_US                    \    wait 40 us = LCD cycle
1916     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
1917     #2 20_US                    \    wait 40 us = LCD cycle
1918     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
1919     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
1920     LCD_CLEAR                   \ 10- "LCD_Clear"
1921     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
1922     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
1923     LCD_CLEAR                   \ 10- "LCD_Clear"
1924     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
1925     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
1926     CR ." I love you"           \ display message on LCD
1927     ['] CR >BODY IS CR          \ CR executes its default value
1928     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
1929     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
1930     PWR_STATE ABORT             \ init DP and continues with ABORT
1931 ;                               \
1932 \ ------------------------------\
1933
1934 \ ------------------------------\
1935 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
1936 \ ------------------------------\
1937 MOV #SLEEP,X                    \ replace default background process SLEEP
1938 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
1939 MOV #WARM,X                     \ replace default WARM
1940 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
1941 MOV X,PC                        \ then execute new WARM
1942 ENDCODE 
1943 \ ------------------------------\
1944
1945 ECHO
1946             ; downloading RC5toLCD.4th is done
1947 RST_HERE    ; this app is protected against <reset>
1948
1949
1950 RST_STATE
1951
1952 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
1953
1954 [UNDEFINED] MARKER [IF]
1955 \  https://forth-standard.org/standard/core/MARKER
1956 \  MARKER
1957 \ ( "<spaces>name" -- )
1958 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
1959 \ with the execution semantics defined below.
1960
1961 \ name Execution: ( -- )
1962 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
1963 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
1964 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
1965 \ not necessarily provided. No other contextual information such as numeric base is affected
1966 \
1967 : MARKER
1968 CREATE
1969 HI2LO
1970 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
1971 SUB #2,Y            \ 1 Y = LFA
1972 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
1973 ADD #4,&DP          \ 3 add 2 cells
1974 LO2HI
1975 DOES>
1976 HI2LO
1977 MOV @RSP+,IP        \ -- PFA
1978 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
1979 MOV @TOS,&INIDP     \       set DP value for RST_STATE
1980 MOV @PSP+,TOS       \ --
1981 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
1982 ENDCODE
1983 [THEN]
1984
1985 MARKER {RC5TOLCD}
1986
1987 [UNDEFINED] @ [IF]
1988 \ https://forth-standard.org/standard/core/Fetch
1989 \ @     c-addr -- char   fetch char from memory
1990 CODE @
1991 MOV @TOS,TOS
1992 MOV @IP+,PC
1993 ENDCODE
1994 [THEN]
1995
1996 [UNDEFINED] CONSTANT [IF]
1997 \ https://forth-standard.org/standard/core/CONSTANT
1998 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
1999 : CONSTANT 
2000 CREATE
2001 HI2LO
2002 MOV TOS,-2(W)           \   PFA = n
2003 MOV @PSP+,TOS
2004 MOV @RSP+,IP
2005 MOV @IP+,PC
2006 ENDCODE
2007 [THEN]
2008
2009 [UNDEFINED] STATE [IF]
2010 \ https://forth-standard.org/standard/core/STATE
2011 \ STATE   -- a-addr       holds compiler state
2012 STATEADR CONSTANT STATE
2013 [THEN]
2014
2015 [UNDEFINED] = [IF]
2016 \ https://forth-standard.org/standard/core/Equal
2017 \ =      x1 x2 -- flag         test x1=x2
2018 CODE =
2019 SUB @PSP+,TOS   \ 2
2020 0<> IF          \ 2
2021     AND #0,TOS  \ 1
2022     MOV @IP+,PC \ 4
2023 THEN
2024 XOR #-1,TOS     \ 1 flag Z = 1
2025 MOV @IP+,PC     \ 4
2026 ENDCODE
2027 [THEN]
2028
2029 [UNDEFINED] IF [IF]
2030 \ https://forth-standard.org/standard/core/IF
2031 \ IF       -- IFadr    initialize conditional forward branch
2032 CODE IF       \ immediate
2033 SUB #2,PSP              \
2034 MOV TOS,0(PSP)          \
2035 MOV &DP,TOS             \ -- HERE
2036 ADD #4,&DP            \           compile one word, reserve one word
2037 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
2038 ADD #2,TOS              \ -- HERE+2=IFadr
2039 MOV @IP+,PC
2040 ENDCODE IMMEDIATE
2041 [THEN]
2042
2043 [UNDEFINED] THEN [IF]
2044 \ https://forth-standard.org/standard/core/THEN
2045 \ THEN     IFadr --                resolve forward branch
2046 CODE THEN               \ immediate
2047 MOV &DP,0(TOS)          \ -- IFadr
2048 MOV @PSP+,TOS           \ --
2049 MOV @IP+,PC
2050 ENDCODE IMMEDIATE
2051 [THEN]
2052
2053 [UNDEFINED] ELSE [IF]
2054 \ https://forth-standard.org/standard/core/ELSE
2055 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
2056 CODE ELSE     \ immediate
2057 ADD #4,&DP              \ make room to compile two words
2058 MOV &DP,W               \ W=HERE+4
2059 MOV #BRAN,-4(W)
2060 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
2061 SUB #2,W                \ HERE+2
2062 MOV W,TOS               \ -- ELSEadr
2063 MOV @IP+,PC
2064 ENDCODE IMMEDIATE
2065 [THEN]
2066
2067 [UNDEFINED] DEFER [IF]
2068 \ https://forth-standard.org/standard/core/DEFER
2069 \ DEFER "<spaces>name"   --
2070 \ Skip leading space delimiters. Parse name delimited by a space.
2071 \ Create a definition for name with the execution semantics defined below.
2072
2073 \ name Execution:   --
2074 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
2075 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
2076 : DEFER
2077 CREATE
2078 HI2LO
2079 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
2080 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
2081 MOV @RSP+,IP
2082 MOV @IP+,PC
2083 ENDCODE
2084 [THEN]
2085
2086 [UNDEFINED] DEFER! [IF]
2087 \ https://forth-standard.org/standard/core/DEFERStore
2088 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
2089 CODE DEFER!             \ xt2 xt1 --
2090 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
2091 MOV @PSP+,TOS           \ --
2092 MOV @IP+,PC
2093 ENDCODE
2094 [THEN]
2095
2096 [UNDEFINED] IS [IF]
2097 \ https://forth-standard.org/standard/core/IS
2098 \ IS <name>        xt --
2099 \ used as is :
2100 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
2101 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
2102 \ or in a definition : ... ['] U. IS DISPLAY ...
2103 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
2104 \
2105 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
2106 : IS
2107 STATE @
2108 IF  POSTPONE ['] POSTPONE DEFER! 
2109 ELSE ' DEFER! 
2110 THEN
2111 ; IMMEDIATE
2112 [THEN]
2113
2114 [UNDEFINED] >BODY [IF]
2115 \ https://forth-standard.org/standard/core/toBODY
2116 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
2117 CODE >BODY
2118 ADD #4,TOS
2119 MOV @IP+,PC
2120 ENDCODE
2121 [THEN]
2122
2123 \ CODE 20uS           \ n --      8MHz version
2124 \ BEGIN               \ 4 + 16 ~ loop
2125 \     MOV #39,rDOCON   \ 39
2126 \     BEGIN           \ 4 ~ loop
2127 \         NOP
2128 \         SUB #1,rDOCON
2129 \     0=  UNTIL
2130 \     SUB #1,TOS      \ 1
2131 \ 0= UNTIL
2132 \ MOV #XDOCON,rDOCON  \ 2
2133 \ MOV @PSP+,TOS
2134 \ MOV @RSP+,IP        \
2135 \ ENDCODE
2136
2137 CODE 20_US                      \ n --      n * 20 us
2138 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
2139     BEGIN
2140         BIT #1,&LCD_TIM_CTL     \ 3
2141     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
2142     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
2143     SUB #1,TOS                  \ 1
2144 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
2145 MOV @PSP+,TOS                   \ 2
2146 MOV @IP+,PC                     \ 4
2147 ENDCODE
2148
2149 CODE TOP_LCD                    \ LCD Sample
2150 \                               \ if write : %xxxx_WWWW --
2151 \                               \ if read  : -- %0000_RRRR
2152     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
2153     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
2154 0= IF                           \ write LCD bits pattern
2155     AND.B #LCD_DB,TOS           \ 
2156     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
2157     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
2158     MOV @PSP+,TOS               \
2159     MOV @IP+,PC
2160 THEN                            \ read LCD bits pattern
2161     SUB #2,PSP
2162     MOV TOS,0(PSP)
2163     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
2164     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
2165     AND.B #LCD_DB,TOS           \
2166     MOV @IP+,PC
2167 ENDCODE
2168
2169 CODE LCD_WRC                    \ char --         Write Char
2170     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
2171 BW1 SUB #2,PSP                  \
2172     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
2173     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
2174     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
2175     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
2176 COLON                           \ high level word starts here 
2177     TOP_LCD 2 20_US             \ write high nibble first
2178     TOP_LCD 2 20_US 
2179 ;
2180
2181 CODE LCD_WRF                    \ func --         Write Fonction
2182     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
2183     GOTO BW1
2184 ENDCODE
2185
2186 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
2187 : LCD_HOME $02 LCD_WRF 100 20_us ;
2188
2189 \ [UNDEFINED] OR [IF]
2190
2191 \ \ https://forth-standard.org/standard/core/OR
2192 \ \ C OR     x1 x2 -- x3           logical OR
2193 \ CODE OR
2194 \ BIS @PSP+,TOS
2195 \ MOV @IP+,PC
2196 \ ENDCODE
2197
2198 \ [THEN]
2199
2200 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
2201 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
2202 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
2203 \ : LCD_FN_SET        $20 OR LCD_WrF ;
2204 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
2205 \ : LCD_GOTO          $80 OR LCD_WrF ;
2206
2207
2208 \ CODE LCD_RDS                    \ -- status       Read Status
2209 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
2210 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
2211 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
2212 \ COLON                           \ starts a FORTH word
2213 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
2214 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
2215 \ HI2LO                           \ switch from FORTH to assembler
2216 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
2217 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
2218 \     MOV @RSP+,IP                \ restore IP saved by COLON
2219 \     MOV @IP+,PC                 \
2220 \ ENDCODE
2221
2222 \ CODE LCD_RDC                    \ -- char         Read Char
2223 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
2224 \     GOTO BW1
2225 \ ENDCODE
2226
2227
2228 \ ******************************\
2229 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
2230 \ ******************************\
2231 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
2232 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
2233 BIT.B #SW2,&SW2_IN              \ test switch S2
2234 0= IF                           \ case of switch S2 pressed
2235     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
2236     U< IF
2237         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
2238     THEN
2239 ELSE
2240     BIT.B #SW1,&SW1_IN          \ test switch S1 input
2241     0= IF                       \ case of Switch S1 pressed
2242         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
2243         U>= IF                  \
2244            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
2245         THEN                    \
2246     THEN                        \
2247 THEN                            \
2248 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
2249 RET                             \ 5
2250 ENDASM
2251
2252 \ ******************************\
2253 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
2254 \ ******************************\
2255 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
2256 \ ******************************\
2257 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
2258 \                               \       SMclock = 8|16|24 MHz
2259 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
2260 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
2261 \                               \       SR(9)=new Toggle bit memory (ADD on)
2262 \ ******************************\
2263 \ RC5_FirstStartBitHalfCycle:   \
2264 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
2265 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
2266 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
2267 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
2268 \ [THEN]
2269 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
2270     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
2271 [THEN]
2272 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
2273     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
2274 [THEN]
2275 MOV #1778,X                     \ RC5_Period * 1us
2276 MOV #14,W                       \ count of loop
2277 BEGIN                           \
2278 \ ******************************\
2279 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
2280 \ ******************************\                   |
2281 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
2282 \ RC5_Compute_3/4_Period:       \                   |
2283     RRUM    #1,X                \ X=1/2 cycle       |
2284     MOV     X,Y                 \                   ^
2285     RRUM    #1,Y                \ Y=1/4
2286     ADD     X,Y                 \ Y=3/4 cycle
2287     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
2288     U>= UNTIL                   \ 2
2289 \ ******************************\
2290 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
2291 \ ******************************\
2292     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
2293     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
2294     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
2295     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
2296     SUB     #1,W                \ decrement count loop
2297 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
2298 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
2299 0<> WHILE                       \ ----> out of loop ----+
2300     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
2301     BEGIN                       \                       |
2302         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
2303         CMP Y,X                 \ 1                     |   cycle time out of bound ?
2304         U>= IF                  \ 2                 ^   |   yes:
2305         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
2306         GOTO BW1                \                   |   |      quit on truncated RC5 message
2307         THEN                    \                   |   |
2308         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
2309     0<> UNTIL                   \ 2                 |   |
2310 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
2311 \ ******************************\                       |
2312 \ RC5_SampleEndOf:              \ <---------------------+
2313 \ ******************************\
2314 BIC #$30,&RC5_TIM_CTL           \   stop timer
2315 \ ******************************\
2316 \ RC5_ComputeNewRC5word         \
2317 \ ******************************\
2318 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
2319 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
2320 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
2321 \ ******************************\
2322 \ RC5_ComputeC6bit              \
2323 \ ******************************\
2324 BIT     #BIT14,T                \ test /C6 bit in T
2325 0= IF   BIS #BIT6,X             \ set C6 bit in X
2326 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
2327 \ ******************************\
2328 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
2329 \ ******************************\
2330 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
2331 \ ******************************\
2332 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
2333 XOR     @RSP,T                  \ (new XOR old) Toggle bits
2334 BIT     #UF10,T                 \ repeated RC5_command ?
2335 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
2336 XOR #UF10,0(RSP)                \ 5 toggle bit memory
2337 \ ******************************\
2338 \ Display IR_RC5 code           \
2339 \ ******************************\
2340 SUB #8,PSP                      \ TOS -- x x x x TOS
2341 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
2342 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
2343 MOV #$10,&BASEADR               \                                               set hexadecimal base
2344 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
2345 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
2346 LO2HI                           \                                               switch from assembler to FORTH
2347     LCD_CLEAR                   \                                               set LCD cursor at home
2348     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
2349     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
2350     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
2351     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
2352 HI2LO                           \     --                                        switch from FORTH to assembler
2353 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
2354 MOV @PSP+,TOS                   \     -- TOS
2355 RET
2356 ENDASM
2357
2358 \ ******************************\
2359 ASM BACKGROUND                  \
2360 \ ******************************\
2361 BEGIN
2362 \     ...                         \ insert here your background task
2363 \     ...                         \
2364 \     ...                         \
2365     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
2366     BIS &LPM_MODE,SR            \
2367 \ ******************************\
2368 \ here start all interrupts     \
2369 \ ******************************\
2370 \ here return all interrupts    \
2371 \ ******************************\
2372 AGAIN                           \
2373 ENDASM                          \
2374 \ ******************************\
2375
2376 \ ------------------------------\
2377 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
2378 \ ------------------------------\
2379 \     ...                         \ init specific I/O sys as you want
2380 \     ...                         \ before executing default WARM
2381     MOV #WARM,X                 \ ['] WARM 
2382     ADD #4,X                    \ >BODY
2383     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
2384 ENDASM
2385 \ ------------------------------\
2386
2387 \ ------------------------------\
2388 CODE STOP                       \ stops multitasking, must to be used before downloading app
2389 \ ------------------------------\
2390 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
2391     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
2392     MOV X,-2(X)                 \ restore the default background: SLEEP
2393     MOV #WARM,X
2394     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
2395     BIC.B #RC5,&IR_IE           \ clear RC5_Int
2396     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
2397     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
2398     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
2399     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
2400     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
2401 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
2402 ECHO                            \
2403 ." RC5toLCD is removed,"
2404 ."  type START to restart"
2405  WARM                           \ performs reset to reset all interrupt vectors.    
2406 ;
2407 \ ------------------------------\
2408
2409 \ ------------------------------\
2410 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
2411 \ ------------------------------\
2412 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
2413 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
2414 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
2415 \                           --       \ID input divider \ 10 = /4
2416 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
2417 \                                 -  \TBCLR TimerB Clear
2418 \                                  - \TBIE
2419 \                                   -\TBIFG
2420 \ -------------------------------\
2421 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
2422 \                  --                 \CM Capture Mode
2423 \                    --               \CCIS
2424 \                       -             \SCS
2425 \                        --           \CLLD
2426 \                          -          \CAP
2427 \                            ---      \OUTMOD \ 011 = set/reset
2428 \                               -     \CCIE
2429 \                                 -   \CCI
2430 \                                  -  \OUT
2431 \                                   - \COV
2432 \                                    -\CCIFG
2433 \ -------------------------------\
2434 \ LCD_TIM_CCRx                   \
2435 \ -------------------------------\
2436 \ LCD_TIM_EX0                    \ 
2437 \ ------------------------------\
2438 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
2439 \ ------------------------------\
2440 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
2441 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
2442 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
2443     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
2444 [THEN]
2445 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
2446     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
2447 [THEN]
2448     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
2449 \ ------------------------------\
2450 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
2451 \ ------------------------------\
2452 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
2453     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
2454 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
2455 \ ------------------------------\
2456     BIS.B #LCDVo,&LCDVo_DIR     \
2457     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
2458 \ ------------------------------\
2459     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
2460     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
2461 \ ------------------------------\
2462     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
2463     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
2464 \ ******************************\
2465 \ init RC5_Int                  \
2466 \ ******************************\
2467     BIS.B #RC5,&IR_IE           \ enable RC5_Int
2468     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
2469     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
2470 \ ******************************\
2471 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
2472 \ ******************************\
2473 \              %01 0001 0100    \ TAxCTL
2474 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
2475 \                  --           \ ID        divided by 1
2476 \                    --         \ MC        MODE = up to TAxCCRn
2477 \                        -      \ TACLR     clear timer count
2478 \                         -     \ TAIE
2479 \                          -    \ TAIFG
2480 \ ------------------------------\
2481 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
2482 \ ------------------------------\
2483 \                        000    \ TAxEX0
2484 \                        ---    \ TAIDEX    pre divisor
2485 \ ------------------------------\
2486 \          %0000 0000 0000 0101 \ TAxCCR0
2487     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
2488 \ ------------------------------\
2489 \          %0000 0000 0001 0000 \ TAxCCTL0
2490 \                   -           \ CAP capture/compare mode = compare
2491 \                        -      \ CCIEn
2492 \                             - \ CCIFGn
2493     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
2494 \ ------------------------------\
2495     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
2496 \ ------------------------------\
2497 \ define LPM mode for ACCEPT    \
2498 \ ------------------------------\
2499 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
2500 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
2501 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
2502 \ ------------------------------\
2503 \ activate I/O                  \
2504 \ ------------------------------\
2505 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
2506 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
2507 \ ------------------------------\
2508 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
2509 \ ------------------------------\
2510 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
2511 \ CMP #2,Y                        \ Power_ON event
2512 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
2513 CMP #4,Y                        \
2514 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
2515 \ CMP #6,Y                        \
2516 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
2517 \ CMP #$0A,Y                      \
2518 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
2519 \ CMP #$16,Y                      \
2520 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
2521 \ ------------------------------\
2522 COLON                           \
2523 \ ------------------------------\
2524 \ Init LCD 2x20                 \
2525 \ ------------------------------\
2526     #1000 20_US                 \ 1- wait 20 ms
2527     %011 TOP_LCD                \ 2- send DB5=DB4=1
2528     #205 20_US                  \ 3- wait 4,1 ms
2529     %011 TOP_LCD                \ 4- send again DB5=DB4=1
2530     #5 20_US                    \ 5- wait 0,1 ms
2531     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
2532     #2 20_US                    \    wait 40 us = LCD cycle
2533     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
2534     #2 20_US                    \    wait 40 us = LCD cycle
2535     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
2536     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
2537     LCD_CLEAR                   \ 10- "LCD_Clear"
2538     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
2539     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
2540     LCD_CLEAR                   \ 10- "LCD_Clear"
2541     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
2542     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
2543     CR ." I love you"           \ display message on LCD
2544     ['] CR >BODY IS CR          \ CR executes its default value
2545     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
2546     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
2547     PWR_STATE ABORT             \ init DP and continues with ABORT
2548 ;                               \
2549 \ ------------------------------\
2550
2551 \ ------------------------------\
2552 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
2553 \ ------------------------------\
2554 MOV #SLEEP,X                    \ replace default background process SLEEP
2555 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
2556 MOV #WARM,X                     \ replace default WARM
2557 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
2558 MOV X,PC                        \ then execute new WARM
2559 ENDCODE 
2560 \ ------------------------------\
2561
2562 ECHO
2563             ; downloading RC5toLCD.4th is done
2564 RST_HERE    ; this app is protected against <reset>
2565
2566
2567 RST_STATE
2568
2569 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
2570
2571 [UNDEFINED] MARKER [IF]
2572 \  https://forth-standard.org/standard/core/MARKER
2573 \  MARKER
2574 \ ( "<spaces>name" -- )
2575 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
2576 \ with the execution semantics defined below.
2577
2578 \ name Execution: ( -- )
2579 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
2580 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
2581 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
2582 \ not necessarily provided. No other contextual information such as numeric base is affected
2583 \
2584 : MARKER
2585 CREATE
2586 HI2LO
2587 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
2588 SUB #2,Y            \ 1 Y = LFA
2589 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
2590 ADD #4,&DP          \ 3 add 2 cells
2591 LO2HI
2592 DOES>
2593 HI2LO
2594 MOV @RSP+,IP        \ -- PFA
2595 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
2596 MOV @TOS,&INIDP     \       set DP value for RST_STATE
2597 MOV @PSP+,TOS       \ --
2598 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
2599 ENDCODE
2600 [THEN]
2601
2602 MARKER {RC5TOLCD}
2603
2604 [UNDEFINED] @ [IF]
2605 \ https://forth-standard.org/standard/core/Fetch
2606 \ @     c-addr -- char   fetch char from memory
2607 CODE @
2608 MOV @TOS,TOS
2609 MOV @IP+,PC
2610 ENDCODE
2611 [THEN]
2612
2613 [UNDEFINED] CONSTANT [IF]
2614 \ https://forth-standard.org/standard/core/CONSTANT
2615 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
2616 : CONSTANT 
2617 CREATE
2618 HI2LO
2619 MOV TOS,-2(W)           \   PFA = n
2620 MOV @PSP+,TOS
2621 MOV @RSP+,IP
2622 MOV @IP+,PC
2623 ENDCODE
2624 [THEN]
2625
2626 [UNDEFINED] STATE [IF]
2627 \ https://forth-standard.org/standard/core/STATE
2628 \ STATE   -- a-addr       holds compiler state
2629 STATEADR CONSTANT STATE
2630 [THEN]
2631
2632 [UNDEFINED] = [IF]
2633 \ https://forth-standard.org/standard/core/Equal
2634 \ =      x1 x2 -- flag         test x1=x2
2635 CODE =
2636 SUB @PSP+,TOS   \ 2
2637 0<> IF          \ 2
2638     AND #0,TOS  \ 1
2639     MOV @IP+,PC \ 4
2640 THEN
2641 XOR #-1,TOS     \ 1 flag Z = 1
2642 MOV @IP+,PC     \ 4
2643 ENDCODE
2644 [THEN]
2645
2646 [UNDEFINED] IF [IF]
2647 \ https://forth-standard.org/standard/core/IF
2648 \ IF       -- IFadr    initialize conditional forward branch
2649 CODE IF       \ immediate
2650 SUB #2,PSP              \
2651 MOV TOS,0(PSP)          \
2652 MOV &DP,TOS             \ -- HERE
2653 ADD #4,&DP            \           compile one word, reserve one word
2654 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
2655 ADD #2,TOS              \ -- HERE+2=IFadr
2656 MOV @IP+,PC
2657 ENDCODE IMMEDIATE
2658 [THEN]
2659
2660 [UNDEFINED] THEN [IF]
2661 \ https://forth-standard.org/standard/core/THEN
2662 \ THEN     IFadr --                resolve forward branch
2663 CODE THEN               \ immediate
2664 MOV &DP,0(TOS)          \ -- IFadr
2665 MOV @PSP+,TOS           \ --
2666 MOV @IP+,PC
2667 ENDCODE IMMEDIATE
2668 [THEN]
2669
2670 [UNDEFINED] ELSE [IF]
2671 \ https://forth-standard.org/standard/core/ELSE
2672 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
2673 CODE ELSE     \ immediate
2674 ADD #4,&DP              \ make room to compile two words
2675 MOV &DP,W               \ W=HERE+4
2676 MOV #BRAN,-4(W)
2677 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
2678 SUB #2,W                \ HERE+2
2679 MOV W,TOS               \ -- ELSEadr
2680 MOV @IP+,PC
2681 ENDCODE IMMEDIATE
2682 [THEN]
2683
2684 [UNDEFINED] DEFER [IF]
2685 \ https://forth-standard.org/standard/core/DEFER
2686 \ DEFER "<spaces>name"   --
2687 \ Skip leading space delimiters. Parse name delimited by a space.
2688 \ Create a definition for name with the execution semantics defined below.
2689
2690 \ name Execution:   --
2691 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
2692 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
2693 : DEFER
2694 CREATE
2695 HI2LO
2696 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
2697 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
2698 MOV @RSP+,IP
2699 MOV @IP+,PC
2700 ENDCODE
2701 [THEN]
2702
2703 [UNDEFINED] DEFER! [IF]
2704 \ https://forth-standard.org/standard/core/DEFERStore
2705 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
2706 CODE DEFER!             \ xt2 xt1 --
2707 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
2708 MOV @PSP+,TOS           \ --
2709 MOV @IP+,PC
2710 ENDCODE
2711 [THEN]
2712
2713 [UNDEFINED] IS [IF]
2714 \ https://forth-standard.org/standard/core/IS
2715 \ IS <name>        xt --
2716 \ used as is :
2717 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
2718 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
2719 \ or in a definition : ... ['] U. IS DISPLAY ...
2720 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
2721 \
2722 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
2723 : IS
2724 STATE @
2725 IF  POSTPONE ['] POSTPONE DEFER! 
2726 ELSE ' DEFER! 
2727 THEN
2728 ; IMMEDIATE
2729 [THEN]
2730
2731 [UNDEFINED] >BODY [IF]
2732 \ https://forth-standard.org/standard/core/toBODY
2733 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
2734 CODE >BODY
2735 ADD #4,TOS
2736 MOV @IP+,PC
2737 ENDCODE
2738 [THEN]
2739
2740 \ CODE 20uS           \ n --      8MHz version
2741 \ BEGIN               \ 4 + 16 ~ loop
2742 \     MOV #39,rDOCON   \ 39
2743 \     BEGIN           \ 4 ~ loop
2744 \         NOP
2745 \         SUB #1,rDOCON
2746 \     0=  UNTIL
2747 \     SUB #1,TOS      \ 1
2748 \ 0= UNTIL
2749 \ MOV #XDOCON,rDOCON  \ 2
2750 \ MOV @PSP+,TOS
2751 \ MOV @RSP+,IP        \
2752 \ ENDCODE
2753
2754 CODE 20_US                      \ n --      n * 20 us
2755 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
2756     BEGIN
2757         BIT #1,&LCD_TIM_CTL     \ 3
2758     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
2759     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
2760     SUB #1,TOS                  \ 1
2761 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
2762 MOV @PSP+,TOS                   \ 2
2763 MOV @IP+,PC                     \ 4
2764 ENDCODE
2765
2766 CODE TOP_LCD                    \ LCD Sample
2767 \                               \ if write : %xxxx_WWWW --
2768 \                               \ if read  : -- %0000_RRRR
2769     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
2770     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
2771 0= IF                           \ write LCD bits pattern
2772     AND.B #LCD_DB,TOS           \ 
2773     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
2774     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
2775     MOV @PSP+,TOS               \
2776     MOV @IP+,PC
2777 THEN                            \ read LCD bits pattern
2778     SUB #2,PSP
2779     MOV TOS,0(PSP)
2780     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
2781     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
2782     AND.B #LCD_DB,TOS           \
2783     MOV @IP+,PC
2784 ENDCODE
2785
2786 CODE LCD_WRC                    \ char --         Write Char
2787     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
2788 BW1 SUB #2,PSP                  \
2789     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
2790     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
2791     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
2792     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
2793 COLON                           \ high level word starts here 
2794     TOP_LCD 2 20_US             \ write high nibble first
2795     TOP_LCD 2 20_US 
2796 ;
2797
2798 CODE LCD_WRF                    \ func --         Write Fonction
2799     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
2800     GOTO BW1
2801 ENDCODE
2802
2803 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
2804 : LCD_HOME $02 LCD_WRF 100 20_us ;
2805
2806 \ [UNDEFINED] OR [IF]
2807
2808 \ \ https://forth-standard.org/standard/core/OR
2809 \ \ C OR     x1 x2 -- x3           logical OR
2810 \ CODE OR
2811 \ BIS @PSP+,TOS
2812 \ MOV @IP+,PC
2813 \ ENDCODE
2814
2815 \ [THEN]
2816
2817 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
2818 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
2819 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
2820 \ : LCD_FN_SET        $20 OR LCD_WrF ;
2821 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
2822 \ : LCD_GOTO          $80 OR LCD_WrF ;
2823
2824
2825 \ CODE LCD_RDS                    \ -- status       Read Status
2826 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
2827 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
2828 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
2829 \ COLON                           \ starts a FORTH word
2830 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
2831 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
2832 \ HI2LO                           \ switch from FORTH to assembler
2833 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
2834 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
2835 \     MOV @RSP+,IP                \ restore IP saved by COLON
2836 \     MOV @IP+,PC                 \
2837 \ ENDCODE
2838
2839 \ CODE LCD_RDC                    \ -- char         Read Char
2840 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
2841 \     GOTO BW1
2842 \ ENDCODE
2843
2844
2845 \ ******************************\
2846 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
2847 \ ******************************\
2848 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
2849 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
2850 BIT.B #SW2,&SW2_IN              \ test switch S2
2851 0= IF                           \ case of switch S2 pressed
2852     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
2853     U< IF
2854         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
2855     THEN
2856 ELSE
2857     BIT.B #SW1,&SW1_IN          \ test switch S1 input
2858     0= IF                       \ case of Switch S1 pressed
2859         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
2860         U>= IF                  \
2861            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
2862         THEN                    \
2863     THEN                        \
2864 THEN                            \
2865 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
2866 RET                             \ 5
2867 ENDASM
2868
2869 \ ******************************\
2870 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
2871 \ ******************************\
2872 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
2873 \ ******************************\
2874 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
2875 \                               \       SMclock = 8|16|24 MHz
2876 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
2877 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
2878 \                               \       SR(9)=new Toggle bit memory (ADD on)
2879 \ ******************************\
2880 \ RC5_FirstStartBitHalfCycle:   \
2881 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
2882 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
2883 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
2884 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
2885 \ [THEN]
2886 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
2887     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
2888 [THEN]
2889 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
2890     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
2891 [THEN]
2892 MOV #1778,X                     \ RC5_Period * 1us
2893 MOV #14,W                       \ count of loop
2894 BEGIN                           \
2895 \ ******************************\
2896 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
2897 \ ******************************\                   |
2898 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
2899 \ RC5_Compute_3/4_Period:       \                   |
2900     RRUM    #1,X                \ X=1/2 cycle       |
2901     MOV     X,Y                 \                   ^
2902     RRUM    #1,Y                \ Y=1/4
2903     ADD     X,Y                 \ Y=3/4 cycle
2904     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
2905     U>= UNTIL                   \ 2
2906 \ ******************************\
2907 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
2908 \ ******************************\
2909     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
2910     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
2911     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
2912     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
2913     SUB     #1,W                \ decrement count loop
2914 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
2915 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
2916 0<> WHILE                       \ ----> out of loop ----+
2917     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
2918     BEGIN                       \                       |
2919         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
2920         CMP Y,X                 \ 1                     |   cycle time out of bound ?
2921         U>= IF                  \ 2                 ^   |   yes:
2922         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
2923         GOTO BW1                \                   |   |      quit on truncated RC5 message
2924         THEN                    \                   |   |
2925         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
2926     0<> UNTIL                   \ 2                 |   |
2927 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
2928 \ ******************************\                       |
2929 \ RC5_SampleEndOf:              \ <---------------------+
2930 \ ******************************\
2931 BIC #$30,&RC5_TIM_CTL           \   stop timer
2932 \ ******************************\
2933 \ RC5_ComputeNewRC5word         \
2934 \ ******************************\
2935 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
2936 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
2937 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
2938 \ ******************************\
2939 \ RC5_ComputeC6bit              \
2940 \ ******************************\
2941 BIT     #BIT14,T                \ test /C6 bit in T
2942 0= IF   BIS #BIT6,X             \ set C6 bit in X
2943 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
2944 \ ******************************\
2945 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
2946 \ ******************************\
2947 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
2948 \ ******************************\
2949 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
2950 XOR     @RSP,T                  \ (new XOR old) Toggle bits
2951 BIT     #UF10,T                 \ repeated RC5_command ?
2952 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
2953 XOR #UF10,0(RSP)                \ 5 toggle bit memory
2954 \ ******************************\
2955 \ Display IR_RC5 code           \
2956 \ ******************************\
2957 SUB #8,PSP                      \ TOS -- x x x x TOS
2958 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
2959 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
2960 MOV #$10,&BASEADR               \                                               set hexadecimal base
2961 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
2962 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
2963 LO2HI                           \                                               switch from assembler to FORTH
2964     LCD_CLEAR                   \                                               set LCD cursor at home
2965     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
2966     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
2967     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
2968     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
2969 HI2LO                           \     --                                        switch from FORTH to assembler
2970 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
2971 MOV @PSP+,TOS                   \     -- TOS
2972 RET
2973 ENDASM
2974
2975 \ ******************************\
2976 ASM BACKGROUND                  \
2977 \ ******************************\
2978 BEGIN
2979 \     ...                         \ insert here your background task
2980 \     ...                         \
2981 \     ...                         \
2982     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
2983     BIS &LPM_MODE,SR            \
2984 \ ******************************\
2985 \ here start all interrupts     \
2986 \ ******************************\
2987 \ here return all interrupts    \
2988 \ ******************************\
2989 AGAIN                           \
2990 ENDASM                          \
2991 \ ******************************\
2992
2993 \ ------------------------------\
2994 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
2995 \ ------------------------------\
2996 \     ...                         \ init specific I/O sys as you want
2997 \     ...                         \ before executing default WARM
2998     MOV #WARM,X                 \ ['] WARM 
2999     ADD #4,X                    \ >BODY
3000     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
3001 ENDASM
3002 \ ------------------------------\
3003
3004 \ ------------------------------\
3005 CODE STOP                       \ stops multitasking, must to be used before downloading app
3006 \ ------------------------------\
3007 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
3008     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
3009     MOV X,-2(X)                 \ restore the default background: SLEEP
3010     MOV #WARM,X
3011     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
3012     BIC.B #RC5,&IR_IE           \ clear RC5_Int
3013     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
3014     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
3015     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
3016     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
3017     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
3018 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
3019 ECHO                            \
3020 ." RC5toLCD is removed,"
3021 ."  type START to restart"
3022  WARM                           \ performs reset to reset all interrupt vectors.    
3023 ;
3024 \ ------------------------------\
3025
3026 \ ------------------------------\
3027 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
3028 \ ------------------------------\
3029 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
3030 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
3031 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
3032 \                           --       \ID input divider \ 10 = /4
3033 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
3034 \                                 -  \TBCLR TimerB Clear
3035 \                                  - \TBIE
3036 \                                   -\TBIFG
3037 \ -------------------------------\
3038 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
3039 \                  --                 \CM Capture Mode
3040 \                    --               \CCIS
3041 \                       -             \SCS
3042 \                        --           \CLLD
3043 \                          -          \CAP
3044 \                            ---      \OUTMOD \ 011 = set/reset
3045 \                               -     \CCIE
3046 \                                 -   \CCI
3047 \                                  -  \OUT
3048 \                                   - \COV
3049 \                                    -\CCIFG
3050 \ -------------------------------\
3051 \ LCD_TIM_CCRx                   \
3052 \ -------------------------------\
3053 \ LCD_TIM_EX0                    \ 
3054 \ ------------------------------\
3055 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
3056 \ ------------------------------\
3057 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
3058 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
3059 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
3060     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
3061 [THEN]
3062 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
3063     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
3064 [THEN]
3065     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
3066 \ ------------------------------\
3067 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
3068 \ ------------------------------\
3069 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
3070     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
3071 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
3072 \ ------------------------------\
3073     BIS.B #LCDVo,&LCDVo_DIR     \
3074     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
3075 \ ------------------------------\
3076     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
3077     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
3078 \ ------------------------------\
3079     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
3080     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
3081 \ ******************************\
3082 \ init RC5_Int                  \
3083 \ ******************************\
3084     BIS.B #RC5,&IR_IE           \ enable RC5_Int
3085     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
3086     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
3087 \ ******************************\
3088 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
3089 \ ******************************\
3090 \              %01 0001 0100    \ TAxCTL
3091 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
3092 \                  --           \ ID        divided by 1
3093 \                    --         \ MC        MODE = up to TAxCCRn
3094 \                        -      \ TACLR     clear timer count
3095 \                         -     \ TAIE
3096 \                          -    \ TAIFG
3097 \ ------------------------------\
3098 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
3099 \ ------------------------------\
3100 \                        000    \ TAxEX0
3101 \                        ---    \ TAIDEX    pre divisor
3102 \ ------------------------------\
3103 \          %0000 0000 0000 0101 \ TAxCCR0
3104     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
3105 \ ------------------------------\
3106 \          %0000 0000 0001 0000 \ TAxCCTL0
3107 \                   -           \ CAP capture/compare mode = compare
3108 \                        -      \ CCIEn
3109 \                             - \ CCIFGn
3110     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
3111 \ ------------------------------\
3112     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
3113 \ ------------------------------\
3114 \ define LPM mode for ACCEPT    \
3115 \ ------------------------------\
3116 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
3117 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
3118 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
3119 \ ------------------------------\
3120 \ activate I/O                  \
3121 \ ------------------------------\
3122 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
3123 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
3124 \ ------------------------------\
3125 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
3126 \ ------------------------------\
3127 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
3128 \ CMP #2,Y                        \ Power_ON event
3129 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
3130 CMP #4,Y                        \
3131 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
3132 \ CMP #6,Y                        \
3133 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
3134 \ CMP #$0A,Y                      \
3135 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
3136 \ CMP #$16,Y                      \
3137 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
3138 \ ------------------------------\
3139 COLON                           \
3140 \ ------------------------------\
3141 \ Init LCD 2x20                 \
3142 \ ------------------------------\
3143     #1000 20_US                 \ 1- wait 20 ms
3144     %011 TOP_LCD                \ 2- send DB5=DB4=1
3145     #205 20_US                  \ 3- wait 4,1 ms
3146     %011 TOP_LCD                \ 4- send again DB5=DB4=1
3147     #5 20_US                    \ 5- wait 0,1 ms
3148     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
3149     #2 20_US                    \    wait 40 us = LCD cycle
3150     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
3151     #2 20_US                    \    wait 40 us = LCD cycle
3152     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
3153     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
3154     LCD_CLEAR                   \ 10- "LCD_Clear"
3155     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
3156     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
3157     LCD_CLEAR                   \ 10- "LCD_Clear"
3158     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
3159     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
3160     CR ." I love you"           \ display message on LCD
3161     ['] CR >BODY IS CR          \ CR executes its default value
3162     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
3163     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
3164     PWR_STATE ABORT             \ init DP and continues with ABORT
3165 ;                               \
3166 \ ------------------------------\
3167
3168 \ ------------------------------\
3169 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
3170 \ ------------------------------\
3171 MOV #SLEEP,X                    \ replace default background process SLEEP
3172 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
3173 MOV #WARM,X                     \ replace default WARM
3174 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
3175 MOV X,PC                        \ then execute new WARM
3176 ENDCODE 
3177 \ ------------------------------\
3178
3179 ECHO
3180             ; downloading RC5toLCD.4th is done
3181 RST_HERE    ; this app is protected against <reset>
3182
3183
3184 RST_STATE
3185
3186 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
3187
3188 [UNDEFINED] MARKER [IF]
3189 \  https://forth-standard.org/standard/core/MARKER
3190 \  MARKER
3191 \ ( "<spaces>name" -- )
3192 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
3193 \ with the execution semantics defined below.
3194
3195 \ name Execution: ( -- )
3196 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
3197 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
3198 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
3199 \ not necessarily provided. No other contextual information such as numeric base is affected
3200 \
3201 : MARKER
3202 CREATE
3203 HI2LO
3204 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
3205 SUB #2,Y            \ 1 Y = LFA
3206 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
3207 ADD #4,&DP          \ 3 add 2 cells
3208 LO2HI
3209 DOES>
3210 HI2LO
3211 MOV @RSP+,IP        \ -- PFA
3212 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
3213 MOV @TOS,&INIDP     \       set DP value for RST_STATE
3214 MOV @PSP+,TOS       \ --
3215 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
3216 ENDCODE
3217 [THEN]
3218
3219 MARKER {RC5TOLCD}
3220
3221 [UNDEFINED] @ [IF]
3222 \ https://forth-standard.org/standard/core/Fetch
3223 \ @     c-addr -- char   fetch char from memory
3224 CODE @
3225 MOV @TOS,TOS
3226 MOV @IP+,PC
3227 ENDCODE
3228 [THEN]
3229
3230 [UNDEFINED] CONSTANT [IF]
3231 \ https://forth-standard.org/standard/core/CONSTANT
3232 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
3233 : CONSTANT 
3234 CREATE
3235 HI2LO
3236 MOV TOS,-2(W)           \   PFA = n
3237 MOV @PSP+,TOS
3238 MOV @RSP+,IP
3239 MOV @IP+,PC
3240 ENDCODE
3241 [THEN]
3242
3243 [UNDEFINED] STATE [IF]
3244 \ https://forth-standard.org/standard/core/STATE
3245 \ STATE   -- a-addr       holds compiler state
3246 STATEADR CONSTANT STATE
3247 [THEN]
3248
3249 [UNDEFINED] = [IF]
3250 \ https://forth-standard.org/standard/core/Equal
3251 \ =      x1 x2 -- flag         test x1=x2
3252 CODE =
3253 SUB @PSP+,TOS   \ 2
3254 0<> IF          \ 2
3255     AND #0,TOS  \ 1
3256     MOV @IP+,PC \ 4
3257 THEN
3258 XOR #-1,TOS     \ 1 flag Z = 1
3259 MOV @IP+,PC     \ 4
3260 ENDCODE
3261 [THEN]
3262
3263 [UNDEFINED] IF [IF]
3264 \ https://forth-standard.org/standard/core/IF
3265 \ IF       -- IFadr    initialize conditional forward branch
3266 CODE IF       \ immediate
3267 SUB #2,PSP              \
3268 MOV TOS,0(PSP)          \
3269 MOV &DP,TOS             \ -- HERE
3270 ADD #4,&DP            \           compile one word, reserve one word
3271 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
3272 ADD #2,TOS              \ -- HERE+2=IFadr
3273 MOV @IP+,PC
3274 ENDCODE IMMEDIATE
3275 [THEN]
3276
3277 [UNDEFINED] THEN [IF]
3278 \ https://forth-standard.org/standard/core/THEN
3279 \ THEN     IFadr --                resolve forward branch
3280 CODE THEN               \ immediate
3281 MOV &DP,0(TOS)          \ -- IFadr
3282 MOV @PSP+,TOS           \ --
3283 MOV @IP+,PC
3284 ENDCODE IMMEDIATE
3285 [THEN]
3286
3287 [UNDEFINED] ELSE [IF]
3288 \ https://forth-standard.org/standard/core/ELSE
3289 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
3290 CODE ELSE     \ immediate
3291 ADD #4,&DP              \ make room to compile two words
3292 MOV &DP,W               \ W=HERE+4
3293 MOV #BRAN,-4(W)
3294 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
3295 SUB #2,W                \ HERE+2
3296 MOV W,TOS               \ -- ELSEadr
3297 MOV @IP+,PC
3298 ENDCODE IMMEDIATE
3299 [THEN]
3300
3301 [UNDEFINED] DEFER [IF]
3302 \ https://forth-standard.org/standard/core/DEFER
3303 \ DEFER "<spaces>name"   --
3304 \ Skip leading space delimiters. Parse name delimited by a space.
3305 \ Create a definition for name with the execution semantics defined below.
3306
3307 \ name Execution:   --
3308 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
3309 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
3310 : DEFER
3311 CREATE
3312 HI2LO
3313 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
3314 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
3315 MOV @RSP+,IP
3316 MOV @IP+,PC
3317 ENDCODE
3318 [THEN]
3319
3320 [UNDEFINED] DEFER! [IF]
3321 \ https://forth-standard.org/standard/core/DEFERStore
3322 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
3323 CODE DEFER!             \ xt2 xt1 --
3324 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
3325 MOV @PSP+,TOS           \ --
3326 MOV @IP+,PC
3327 ENDCODE
3328 [THEN]
3329
3330 [UNDEFINED] IS [IF]
3331 \ https://forth-standard.org/standard/core/IS
3332 \ IS <name>        xt --
3333 \ used as is :
3334 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
3335 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
3336 \ or in a definition : ... ['] U. IS DISPLAY ...
3337 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
3338 \
3339 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
3340 : IS
3341 STATE @
3342 IF  POSTPONE ['] POSTPONE DEFER! 
3343 ELSE ' DEFER! 
3344 THEN
3345 ; IMMEDIATE
3346 [THEN]
3347
3348 [UNDEFINED] >BODY [IF]
3349 \ https://forth-standard.org/standard/core/toBODY
3350 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
3351 CODE >BODY
3352 ADD #4,TOS
3353 MOV @IP+,PC
3354 ENDCODE
3355 [THEN]
3356
3357 \ CODE 20uS           \ n --      8MHz version
3358 \ BEGIN               \ 4 + 16 ~ loop
3359 \     MOV #39,rDOCON   \ 39
3360 \     BEGIN           \ 4 ~ loop
3361 \         NOP
3362 \         SUB #1,rDOCON
3363 \     0=  UNTIL
3364 \     SUB #1,TOS      \ 1
3365 \ 0= UNTIL
3366 \ MOV #XDOCON,rDOCON  \ 2
3367 \ MOV @PSP+,TOS
3368 \ MOV @RSP+,IP        \
3369 \ ENDCODE
3370
3371 CODE 20_US                      \ n --      n * 20 us
3372 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
3373     BEGIN
3374         BIT #1,&LCD_TIM_CTL     \ 3
3375     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
3376     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
3377     SUB #1,TOS                  \ 1
3378 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
3379 MOV @PSP+,TOS                   \ 2
3380 MOV @IP+,PC                     \ 4
3381 ENDCODE
3382
3383 CODE TOP_LCD                    \ LCD Sample
3384 \                               \ if write : %xxxx_WWWW --
3385 \                               \ if read  : -- %0000_RRRR
3386     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
3387     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
3388 0= IF                           \ write LCD bits pattern
3389     AND.B #LCD_DB,TOS           \ 
3390     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
3391     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
3392     MOV @PSP+,TOS               \
3393     MOV @IP+,PC
3394 THEN                            \ read LCD bits pattern
3395     SUB #2,PSP
3396     MOV TOS,0(PSP)
3397     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
3398     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
3399     AND.B #LCD_DB,TOS           \
3400     MOV @IP+,PC
3401 ENDCODE
3402
3403 CODE LCD_WRC                    \ char --         Write Char
3404     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
3405 BW1 SUB #2,PSP                  \
3406     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
3407     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
3408     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
3409     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
3410 COLON                           \ high level word starts here 
3411     TOP_LCD 2 20_US             \ write high nibble first
3412     TOP_LCD 2 20_US 
3413 ;
3414
3415 CODE LCD_WRF                    \ func --         Write Fonction
3416     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
3417     GOTO BW1
3418 ENDCODE
3419
3420 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
3421 : LCD_HOME $02 LCD_WRF 100 20_us ;
3422
3423 \ [UNDEFINED] OR [IF]
3424
3425 \ \ https://forth-standard.org/standard/core/OR
3426 \ \ C OR     x1 x2 -- x3           logical OR
3427 \ CODE OR
3428 \ BIS @PSP+,TOS
3429 \ MOV @IP+,PC
3430 \ ENDCODE
3431
3432 \ [THEN]
3433
3434 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
3435 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
3436 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
3437 \ : LCD_FN_SET        $20 OR LCD_WrF ;
3438 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
3439 \ : LCD_GOTO          $80 OR LCD_WrF ;
3440
3441
3442 \ CODE LCD_RDS                    \ -- status       Read Status
3443 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
3444 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
3445 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
3446 \ COLON                           \ starts a FORTH word
3447 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
3448 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
3449 \ HI2LO                           \ switch from FORTH to assembler
3450 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
3451 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
3452 \     MOV @RSP+,IP                \ restore IP saved by COLON
3453 \     MOV @IP+,PC                 \
3454 \ ENDCODE
3455
3456 \ CODE LCD_RDC                    \ -- char         Read Char
3457 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
3458 \     GOTO BW1
3459 \ ENDCODE
3460
3461
3462 \ ******************************\
3463 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
3464 \ ******************************\
3465 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
3466 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
3467 BIT.B #SW2,&SW2_IN              \ test switch S2
3468 0= IF                           \ case of switch S2 pressed
3469     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
3470     U< IF
3471         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
3472     THEN
3473 ELSE
3474     BIT.B #SW1,&SW1_IN          \ test switch S1 input
3475     0= IF                       \ case of Switch S1 pressed
3476         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
3477         U>= IF                  \
3478            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
3479         THEN                    \
3480     THEN                        \
3481 THEN                            \
3482 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
3483 RET                             \ 5
3484 ENDASM
3485
3486 \ ******************************\
3487 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
3488 \ ******************************\
3489 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
3490 \ ******************************\
3491 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
3492 \                               \       SMclock = 8|16|24 MHz
3493 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
3494 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
3495 \                               \       SR(9)=new Toggle bit memory (ADD on)
3496 \ ******************************\
3497 \ RC5_FirstStartBitHalfCycle:   \
3498 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
3499 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
3500 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
3501 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
3502 \ [THEN]
3503 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
3504     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
3505 [THEN]
3506 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
3507     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
3508 [THEN]
3509 MOV #1778,X                     \ RC5_Period * 1us
3510 MOV #14,W                       \ count of loop
3511 BEGIN                           \
3512 \ ******************************\
3513 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
3514 \ ******************************\                   |
3515 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
3516 \ RC5_Compute_3/4_Period:       \                   |
3517     RRUM    #1,X                \ X=1/2 cycle       |
3518     MOV     X,Y                 \                   ^
3519     RRUM    #1,Y                \ Y=1/4
3520     ADD     X,Y                 \ Y=3/4 cycle
3521     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
3522     U>= UNTIL                   \ 2
3523 \ ******************************\
3524 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
3525 \ ******************************\
3526     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
3527     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
3528     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
3529     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
3530     SUB     #1,W                \ decrement count loop
3531 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
3532 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
3533 0<> WHILE                       \ ----> out of loop ----+
3534     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
3535     BEGIN                       \                       |
3536         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
3537         CMP Y,X                 \ 1                     |   cycle time out of bound ?
3538         U>= IF                  \ 2                 ^   |   yes:
3539         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
3540         GOTO BW1                \                   |   |      quit on truncated RC5 message
3541         THEN                    \                   |   |
3542         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
3543     0<> UNTIL                   \ 2                 |   |
3544 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
3545 \ ******************************\                       |
3546 \ RC5_SampleEndOf:              \ <---------------------+
3547 \ ******************************\
3548 BIC #$30,&RC5_TIM_CTL           \   stop timer
3549 \ ******************************\
3550 \ RC5_ComputeNewRC5word         \
3551 \ ******************************\
3552 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
3553 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
3554 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
3555 \ ******************************\
3556 \ RC5_ComputeC6bit              \
3557 \ ******************************\
3558 BIT     #BIT14,T                \ test /C6 bit in T
3559 0= IF   BIS #BIT6,X             \ set C6 bit in X
3560 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
3561 \ ******************************\
3562 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
3563 \ ******************************\
3564 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
3565 \ ******************************\
3566 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
3567 XOR     @RSP,T                  \ (new XOR old) Toggle bits
3568 BIT     #UF10,T                 \ repeated RC5_command ?
3569 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
3570 XOR #UF10,0(RSP)                \ 5 toggle bit memory
3571 \ ******************************\
3572 \ Display IR_RC5 code           \
3573 \ ******************************\
3574 SUB #8,PSP                      \ TOS -- x x x x TOS
3575 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
3576 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
3577 MOV #$10,&BASEADR               \                                               set hexadecimal base
3578 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
3579 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
3580 LO2HI                           \                                               switch from assembler to FORTH
3581     LCD_CLEAR                   \                                               set LCD cursor at home
3582     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
3583     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
3584     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
3585     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
3586 HI2LO                           \     --                                        switch from FORTH to assembler
3587 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
3588 MOV @PSP+,TOS                   \     -- TOS
3589 RET
3590 ENDASM
3591
3592 \ ******************************\
3593 ASM BACKGROUND                  \
3594 \ ******************************\
3595 BEGIN
3596 \     ...                         \ insert here your background task
3597 \     ...                         \
3598 \     ...                         \
3599     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
3600     BIS &LPM_MODE,SR            \
3601 \ ******************************\
3602 \ here start all interrupts     \
3603 \ ******************************\
3604 \ here return all interrupts    \
3605 \ ******************************\
3606 AGAIN                           \
3607 ENDASM                          \
3608 \ ******************************\
3609
3610 \ ------------------------------\
3611 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
3612 \ ------------------------------\
3613 \     ...                         \ init specific I/O sys as you want
3614 \     ...                         \ before executing default WARM
3615     MOV #WARM,X                 \ ['] WARM 
3616     ADD #4,X                    \ >BODY
3617     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
3618 ENDASM
3619 \ ------------------------------\
3620
3621 \ ------------------------------\
3622 CODE STOP                       \ stops multitasking, must to be used before downloading app
3623 \ ------------------------------\
3624 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
3625     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
3626     MOV X,-2(X)                 \ restore the default background: SLEEP
3627     MOV #WARM,X
3628     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
3629     BIC.B #RC5,&IR_IE           \ clear RC5_Int
3630     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
3631     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
3632     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
3633     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
3634     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
3635 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
3636 ECHO                            \
3637 ." RC5toLCD is removed,"
3638 ."  type START to restart"
3639  WARM                           \ performs reset to reset all interrupt vectors.    
3640 ;
3641 \ ------------------------------\
3642
3643 \ ------------------------------\
3644 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
3645 \ ------------------------------\
3646 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
3647 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
3648 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
3649 \                           --       \ID input divider \ 10 = /4
3650 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
3651 \                                 -  \TBCLR TimerB Clear
3652 \                                  - \TBIE
3653 \                                   -\TBIFG
3654 \ -------------------------------\
3655 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
3656 \                  --                 \CM Capture Mode
3657 \                    --               \CCIS
3658 \                       -             \SCS
3659 \                        --           \CLLD
3660 \                          -          \CAP
3661 \                            ---      \OUTMOD \ 011 = set/reset
3662 \                               -     \CCIE
3663 \                                 -   \CCI
3664 \                                  -  \OUT
3665 \                                   - \COV
3666 \                                    -\CCIFG
3667 \ -------------------------------\
3668 \ LCD_TIM_CCRx                   \
3669 \ -------------------------------\
3670 \ LCD_TIM_EX0                    \ 
3671 \ ------------------------------\
3672 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
3673 \ ------------------------------\
3674 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
3675 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
3676 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
3677     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
3678 [THEN]
3679 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
3680     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
3681 [THEN]
3682     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
3683 \ ------------------------------\
3684 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
3685 \ ------------------------------\
3686 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
3687     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
3688 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
3689 \ ------------------------------\
3690     BIS.B #LCDVo,&LCDVo_DIR     \
3691     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
3692 \ ------------------------------\
3693     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
3694     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
3695 \ ------------------------------\
3696     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
3697     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
3698 \ ******************************\
3699 \ init RC5_Int                  \
3700 \ ******************************\
3701     BIS.B #RC5,&IR_IE           \ enable RC5_Int
3702     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
3703     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
3704 \ ******************************\
3705 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
3706 \ ******************************\
3707 \              %01 0001 0100    \ TAxCTL
3708 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
3709 \                  --           \ ID        divided by 1
3710 \                    --         \ MC        MODE = up to TAxCCRn
3711 \                        -      \ TACLR     clear timer count
3712 \                         -     \ TAIE
3713 \                          -    \ TAIFG
3714 \ ------------------------------\
3715 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
3716 \ ------------------------------\
3717 \                        000    \ TAxEX0
3718 \                        ---    \ TAIDEX    pre divisor
3719 \ ------------------------------\
3720 \          %0000 0000 0000 0101 \ TAxCCR0
3721     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
3722 \ ------------------------------\
3723 \          %0000 0000 0001 0000 \ TAxCCTL0
3724 \                   -           \ CAP capture/compare mode = compare
3725 \                        -      \ CCIEn
3726 \                             - \ CCIFGn
3727     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
3728 \ ------------------------------\
3729     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
3730 \ ------------------------------\
3731 \ define LPM mode for ACCEPT    \
3732 \ ------------------------------\
3733 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
3734 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
3735 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
3736 \ ------------------------------\
3737 \ activate I/O                  \
3738 \ ------------------------------\
3739 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
3740 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
3741 \ ------------------------------\
3742 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
3743 \ ------------------------------\
3744 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
3745 \ CMP #2,Y                        \ Power_ON event
3746 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
3747 CMP #4,Y                        \
3748 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
3749 \ CMP #6,Y                        \
3750 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
3751 \ CMP #$0A,Y                      \
3752 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
3753 \ CMP #$16,Y                      \
3754 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
3755 \ ------------------------------\
3756 COLON                           \
3757 \ ------------------------------\
3758 \ Init LCD 2x20                 \
3759 \ ------------------------------\
3760     #1000 20_US                 \ 1- wait 20 ms
3761     %011 TOP_LCD                \ 2- send DB5=DB4=1
3762     #205 20_US                  \ 3- wait 4,1 ms
3763     %011 TOP_LCD                \ 4- send again DB5=DB4=1
3764     #5 20_US                    \ 5- wait 0,1 ms
3765     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
3766     #2 20_US                    \    wait 40 us = LCD cycle
3767     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
3768     #2 20_US                    \    wait 40 us = LCD cycle
3769     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
3770     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
3771     LCD_CLEAR                   \ 10- "LCD_Clear"
3772     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
3773     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
3774     LCD_CLEAR                   \ 10- "LCD_Clear"
3775     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
3776     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
3777     CR ." I love you"           \ display message on LCD
3778     ['] CR >BODY IS CR          \ CR executes its default value
3779     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
3780     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
3781     PWR_STATE ABORT             \ init DP and continues with ABORT
3782 ;                               \
3783 \ ------------------------------\
3784
3785 \ ------------------------------\
3786 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
3787 \ ------------------------------\
3788 MOV #SLEEP,X                    \ replace default background process SLEEP
3789 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
3790 MOV #WARM,X                     \ replace default WARM
3791 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
3792 MOV X,PC                        \ then execute new WARM
3793 ENDCODE 
3794 \ ------------------------------\
3795
3796 ECHO
3797             ; downloading RC5toLCD.4th is done
3798 RST_HERE    ; this app is protected against <reset>
3799
3800
3801 RST_STATE
3802
3803 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
3804
3805 [UNDEFINED] MARKER [IF]
3806 \  https://forth-standard.org/standard/core/MARKER
3807 \  MARKER
3808 \ ( "<spaces>name" -- )
3809 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
3810 \ with the execution semantics defined below.
3811
3812 \ name Execution: ( -- )
3813 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
3814 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
3815 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
3816 \ not necessarily provided. No other contextual information such as numeric base is affected
3817 \
3818 : MARKER
3819 CREATE
3820 HI2LO
3821 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
3822 SUB #2,Y            \ 1 Y = LFA
3823 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
3824 ADD #4,&DP          \ 3 add 2 cells
3825 LO2HI
3826 DOES>
3827 HI2LO
3828 MOV @RSP+,IP        \ -- PFA
3829 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
3830 MOV @TOS,&INIDP     \       set DP value for RST_STATE
3831 MOV @PSP+,TOS       \ --
3832 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
3833 ENDCODE
3834 [THEN]
3835
3836 MARKER {RC5TOLCD}
3837
3838 [UNDEFINED] @ [IF]
3839 \ https://forth-standard.org/standard/core/Fetch
3840 \ @     c-addr -- char   fetch char from memory
3841 CODE @
3842 MOV @TOS,TOS
3843 MOV @IP+,PC
3844 ENDCODE
3845 [THEN]
3846
3847 [UNDEFINED] CONSTANT [IF]
3848 \ https://forth-standard.org/standard/core/CONSTANT
3849 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
3850 : CONSTANT 
3851 CREATE
3852 HI2LO
3853 MOV TOS,-2(W)           \   PFA = n
3854 MOV @PSP+,TOS
3855 MOV @RSP+,IP
3856 MOV @IP+,PC
3857 ENDCODE
3858 [THEN]
3859
3860 [UNDEFINED] STATE [IF]
3861 \ https://forth-standard.org/standard/core/STATE
3862 \ STATE   -- a-addr       holds compiler state
3863 STATEADR CONSTANT STATE
3864 [THEN]
3865
3866 [UNDEFINED] = [IF]
3867 \ https://forth-standard.org/standard/core/Equal
3868 \ =      x1 x2 -- flag         test x1=x2
3869 CODE =
3870 SUB @PSP+,TOS   \ 2
3871 0<> IF          \ 2
3872     AND #0,TOS  \ 1
3873     MOV @IP+,PC \ 4
3874 THEN
3875 XOR #-1,TOS     \ 1 flag Z = 1
3876 MOV @IP+,PC     \ 4
3877 ENDCODE
3878 [THEN]
3879
3880 [UNDEFINED] IF [IF]
3881 \ https://forth-standard.org/standard/core/IF
3882 \ IF       -- IFadr    initialize conditional forward branch
3883 CODE IF       \ immediate
3884 SUB #2,PSP              \
3885 MOV TOS,0(PSP)          \
3886 MOV &DP,TOS             \ -- HERE
3887 ADD #4,&DP            \           compile one word, reserve one word
3888 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
3889 ADD #2,TOS              \ -- HERE+2=IFadr
3890 MOV @IP+,PC
3891 ENDCODE IMMEDIATE
3892 [THEN]
3893
3894 [UNDEFINED] THEN [IF]
3895 \ https://forth-standard.org/standard/core/THEN
3896 \ THEN     IFadr --                resolve forward branch
3897 CODE THEN               \ immediate
3898 MOV &DP,0(TOS)          \ -- IFadr
3899 MOV @PSP+,TOS           \ --
3900 MOV @IP+,PC
3901 ENDCODE IMMEDIATE
3902 [THEN]
3903
3904 [UNDEFINED] ELSE [IF]
3905 \ https://forth-standard.org/standard/core/ELSE
3906 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
3907 CODE ELSE     \ immediate
3908 ADD #4,&DP              \ make room to compile two words
3909 MOV &DP,W               \ W=HERE+4
3910 MOV #BRAN,-4(W)
3911 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
3912 SUB #2,W                \ HERE+2
3913 MOV W,TOS               \ -- ELSEadr
3914 MOV @IP+,PC
3915 ENDCODE IMMEDIATE
3916 [THEN]
3917
3918 [UNDEFINED] DEFER [IF]
3919 \ https://forth-standard.org/standard/core/DEFER
3920 \ DEFER "<spaces>name"   --
3921 \ Skip leading space delimiters. Parse name delimited by a space.
3922 \ Create a definition for name with the execution semantics defined below.
3923
3924 \ name Execution:   --
3925 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
3926 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
3927 : DEFER
3928 CREATE
3929 HI2LO
3930 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
3931 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
3932 MOV @RSP+,IP
3933 MOV @IP+,PC
3934 ENDCODE
3935 [THEN]
3936
3937 [UNDEFINED] DEFER! [IF]
3938 \ https://forth-standard.org/standard/core/DEFERStore
3939 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
3940 CODE DEFER!             \ xt2 xt1 --
3941 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
3942 MOV @PSP+,TOS           \ --
3943 MOV @IP+,PC
3944 ENDCODE
3945 [THEN]
3946
3947 [UNDEFINED] IS [IF]
3948 \ https://forth-standard.org/standard/core/IS
3949 \ IS <name>        xt --
3950 \ used as is :
3951 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
3952 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
3953 \ or in a definition : ... ['] U. IS DISPLAY ...
3954 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
3955 \
3956 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
3957 : IS
3958 STATE @
3959 IF  POSTPONE ['] POSTPONE DEFER! 
3960 ELSE ' DEFER! 
3961 THEN
3962 ; IMMEDIATE
3963 [THEN]
3964
3965 [UNDEFINED] >BODY [IF]
3966 \ https://forth-standard.org/standard/core/toBODY
3967 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
3968 CODE >BODY
3969 ADD #4,TOS
3970 MOV @IP+,PC
3971 ENDCODE
3972 [THEN]
3973
3974 \ CODE 20uS           \ n --      8MHz version
3975 \ BEGIN               \ 4 + 16 ~ loop
3976 \     MOV #39,rDOCON   \ 39
3977 \     BEGIN           \ 4 ~ loop
3978 \         NOP
3979 \         SUB #1,rDOCON
3980 \     0=  UNTIL
3981 \     SUB #1,TOS      \ 1
3982 \ 0= UNTIL
3983 \ MOV #XDOCON,rDOCON  \ 2
3984 \ MOV @PSP+,TOS
3985 \ MOV @RSP+,IP        \
3986 \ ENDCODE
3987
3988 CODE 20_US                      \ n --      n * 20 us
3989 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
3990     BEGIN
3991         BIT #1,&LCD_TIM_CTL     \ 3
3992     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
3993     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
3994     SUB #1,TOS                  \ 1
3995 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
3996 MOV @PSP+,TOS                   \ 2
3997 MOV @IP+,PC                     \ 4
3998 ENDCODE
3999
4000 CODE TOP_LCD                    \ LCD Sample
4001 \                               \ if write : %xxxx_WWWW --
4002 \                               \ if read  : -- %0000_RRRR
4003     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
4004     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
4005 0= IF                           \ write LCD bits pattern
4006     AND.B #LCD_DB,TOS           \ 
4007     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
4008     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
4009     MOV @PSP+,TOS               \
4010     MOV @IP+,PC
4011 THEN                            \ read LCD bits pattern
4012     SUB #2,PSP
4013     MOV TOS,0(PSP)
4014     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
4015     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
4016     AND.B #LCD_DB,TOS           \
4017     MOV @IP+,PC
4018 ENDCODE
4019
4020 CODE LCD_WRC                    \ char --         Write Char
4021     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
4022 BW1 SUB #2,PSP                  \
4023     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
4024     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
4025     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
4026     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
4027 COLON                           \ high level word starts here 
4028     TOP_LCD 2 20_US             \ write high nibble first
4029     TOP_LCD 2 20_US 
4030 ;
4031
4032 CODE LCD_WRF                    \ func --         Write Fonction
4033     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
4034     GOTO BW1
4035 ENDCODE
4036
4037 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
4038 : LCD_HOME $02 LCD_WRF 100 20_us ;
4039
4040 \ [UNDEFINED] OR [IF]
4041
4042 \ \ https://forth-standard.org/standard/core/OR
4043 \ \ C OR     x1 x2 -- x3           logical OR
4044 \ CODE OR
4045 \ BIS @PSP+,TOS
4046 \ MOV @IP+,PC
4047 \ ENDCODE
4048
4049 \ [THEN]
4050
4051 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
4052 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
4053 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
4054 \ : LCD_FN_SET        $20 OR LCD_WrF ;
4055 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
4056 \ : LCD_GOTO          $80 OR LCD_WrF ;
4057
4058
4059 \ CODE LCD_RDS                    \ -- status       Read Status
4060 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
4061 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
4062 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
4063 \ COLON                           \ starts a FORTH word
4064 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
4065 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
4066 \ HI2LO                           \ switch from FORTH to assembler
4067 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
4068 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
4069 \     MOV @RSP+,IP                \ restore IP saved by COLON
4070 \     MOV @IP+,PC                 \
4071 \ ENDCODE
4072
4073 \ CODE LCD_RDC                    \ -- char         Read Char
4074 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
4075 \     GOTO BW1
4076 \ ENDCODE
4077
4078
4079 \ ******************************\
4080 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
4081 \ ******************************\
4082 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
4083 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
4084 BIT.B #SW2,&SW2_IN              \ test switch S2
4085 0= IF                           \ case of switch S2 pressed
4086     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
4087     U< IF
4088         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
4089     THEN
4090 ELSE
4091     BIT.B #SW1,&SW1_IN          \ test switch S1 input
4092     0= IF                       \ case of Switch S1 pressed
4093         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
4094         U>= IF                  \
4095            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
4096         THEN                    \
4097     THEN                        \
4098 THEN                            \
4099 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
4100 RET                             \ 5
4101 ENDASM
4102
4103 \ ******************************\
4104 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
4105 \ ******************************\
4106 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
4107 \ ******************************\
4108 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
4109 \                               \       SMclock = 8|16|24 MHz
4110 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
4111 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
4112 \                               \       SR(9)=new Toggle bit memory (ADD on)
4113 \ ******************************\
4114 \ RC5_FirstStartBitHalfCycle:   \
4115 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
4116 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
4117 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
4118 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
4119 \ [THEN]
4120 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
4121     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
4122 [THEN]
4123 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
4124     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
4125 [THEN]
4126 MOV #1778,X                     \ RC5_Period * 1us
4127 MOV #14,W                       \ count of loop
4128 BEGIN                           \
4129 \ ******************************\
4130 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
4131 \ ******************************\                   |
4132 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
4133 \ RC5_Compute_3/4_Period:       \                   |
4134     RRUM    #1,X                \ X=1/2 cycle       |
4135     MOV     X,Y                 \                   ^
4136     RRUM    #1,Y                \ Y=1/4
4137     ADD     X,Y                 \ Y=3/4 cycle
4138     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
4139     U>= UNTIL                   \ 2
4140 \ ******************************\
4141 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
4142 \ ******************************\
4143     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
4144     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
4145     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
4146     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
4147     SUB     #1,W                \ decrement count loop
4148 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
4149 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
4150 0<> WHILE                       \ ----> out of loop ----+
4151     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
4152     BEGIN                       \                       |
4153         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
4154         CMP Y,X                 \ 1                     |   cycle time out of bound ?
4155         U>= IF                  \ 2                 ^   |   yes:
4156         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
4157         GOTO BW1                \                   |   |      quit on truncated RC5 message
4158         THEN                    \                   |   |
4159         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
4160     0<> UNTIL                   \ 2                 |   |
4161 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
4162 \ ******************************\                       |
4163 \ RC5_SampleEndOf:              \ <---------------------+
4164 \ ******************************\
4165 BIC #$30,&RC5_TIM_CTL           \   stop timer
4166 \ ******************************\
4167 \ RC5_ComputeNewRC5word         \
4168 \ ******************************\
4169 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
4170 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
4171 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
4172 \ ******************************\
4173 \ RC5_ComputeC6bit              \
4174 \ ******************************\
4175 BIT     #BIT14,T                \ test /C6 bit in T
4176 0= IF   BIS #BIT6,X             \ set C6 bit in X
4177 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
4178 \ ******************************\
4179 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
4180 \ ******************************\
4181 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
4182 \ ******************************\
4183 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
4184 XOR     @RSP,T                  \ (new XOR old) Toggle bits
4185 BIT     #UF10,T                 \ repeated RC5_command ?
4186 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
4187 XOR #UF10,0(RSP)                \ 5 toggle bit memory
4188 \ ******************************\
4189 \ Display IR_RC5 code           \
4190 \ ******************************\
4191 SUB #8,PSP                      \ TOS -- x x x x TOS
4192 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
4193 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
4194 MOV #$10,&BASEADR               \                                               set hexadecimal base
4195 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
4196 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
4197 LO2HI                           \                                               switch from assembler to FORTH
4198     LCD_CLEAR                   \                                               set LCD cursor at home
4199     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
4200     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
4201     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
4202     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
4203 HI2LO                           \     --                                        switch from FORTH to assembler
4204 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
4205 MOV @PSP+,TOS                   \     -- TOS
4206 RET
4207 ENDASM
4208
4209 \ ******************************\
4210 ASM BACKGROUND                  \
4211 \ ******************************\
4212 BEGIN
4213 \     ...                         \ insert here your background task
4214 \     ...                         \
4215 \     ...                         \
4216     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
4217     BIS &LPM_MODE,SR            \
4218 \ ******************************\
4219 \ here start all interrupts     \
4220 \ ******************************\
4221 \ here return all interrupts    \
4222 \ ******************************\
4223 AGAIN                           \
4224 ENDASM                          \
4225 \ ******************************\
4226
4227 \ ------------------------------\
4228 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
4229 \ ------------------------------\
4230 \     ...                         \ init specific I/O sys as you want
4231 \     ...                         \ before executing default WARM
4232     MOV #WARM,X                 \ ['] WARM 
4233     ADD #4,X                    \ >BODY
4234     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
4235 ENDASM
4236 \ ------------------------------\
4237
4238 \ ------------------------------\
4239 CODE STOP                       \ stops multitasking, must to be used before downloading app
4240 \ ------------------------------\
4241 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
4242     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
4243     MOV X,-2(X)                 \ restore the default background: SLEEP
4244     MOV #WARM,X
4245     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
4246     BIC.B #RC5,&IR_IE           \ clear RC5_Int
4247     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
4248     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
4249     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
4250     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
4251     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
4252 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
4253 ECHO                            \
4254 ." RC5toLCD is removed,"
4255 ."  type START to restart"
4256  WARM                           \ performs reset to reset all interrupt vectors.    
4257 ;
4258 \ ------------------------------\
4259
4260 \ ------------------------------\
4261 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
4262 \ ------------------------------\
4263 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
4264 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
4265 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
4266 \                           --       \ID input divider \ 10 = /4
4267 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
4268 \                                 -  \TBCLR TimerB Clear
4269 \                                  - \TBIE
4270 \                                   -\TBIFG
4271 \ -------------------------------\
4272 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
4273 \                  --                 \CM Capture Mode
4274 \                    --               \CCIS
4275 \                       -             \SCS
4276 \                        --           \CLLD
4277 \                          -          \CAP
4278 \                            ---      \OUTMOD \ 011 = set/reset
4279 \                               -     \CCIE
4280 \                                 -   \CCI
4281 \                                  -  \OUT
4282 \                                   - \COV
4283 \                                    -\CCIFG
4284 \ -------------------------------\
4285 \ LCD_TIM_CCRx                   \
4286 \ -------------------------------\
4287 \ LCD_TIM_EX0                    \ 
4288 \ ------------------------------\
4289 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
4290 \ ------------------------------\
4291 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
4292 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
4293 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
4294     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
4295 [THEN]
4296 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
4297     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
4298 [THEN]
4299     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
4300 \ ------------------------------\
4301 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
4302 \ ------------------------------\
4303 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
4304     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
4305 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
4306 \ ------------------------------\
4307     BIS.B #LCDVo,&LCDVo_DIR     \
4308     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
4309 \ ------------------------------\
4310     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
4311     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
4312 \ ------------------------------\
4313     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
4314     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
4315 \ ******************************\
4316 \ init RC5_Int                  \
4317 \ ******************************\
4318     BIS.B #RC5,&IR_IE           \ enable RC5_Int
4319     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
4320     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
4321 \ ******************************\
4322 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
4323 \ ******************************\
4324 \              %01 0001 0100    \ TAxCTL
4325 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
4326 \                  --           \ ID        divided by 1
4327 \                    --         \ MC        MODE = up to TAxCCRn
4328 \                        -      \ TACLR     clear timer count
4329 \                         -     \ TAIE
4330 \                          -    \ TAIFG
4331 \ ------------------------------\
4332 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
4333 \ ------------------------------\
4334 \                        000    \ TAxEX0
4335 \                        ---    \ TAIDEX    pre divisor
4336 \ ------------------------------\
4337 \          %0000 0000 0000 0101 \ TAxCCR0
4338     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
4339 \ ------------------------------\
4340 \          %0000 0000 0001 0000 \ TAxCCTL0
4341 \                   -           \ CAP capture/compare mode = compare
4342 \                        -      \ CCIEn
4343 \                             - \ CCIFGn
4344     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
4345 \ ------------------------------\
4346     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
4347 \ ------------------------------\
4348 \ define LPM mode for ACCEPT    \
4349 \ ------------------------------\
4350 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
4351 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
4352 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
4353 \ ------------------------------\
4354 \ activate I/O                  \
4355 \ ------------------------------\
4356 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
4357 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
4358 \ ------------------------------\
4359 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
4360 \ ------------------------------\
4361 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
4362 \ CMP #2,Y                        \ Power_ON event
4363 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
4364 CMP #4,Y                        \
4365 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
4366 \ CMP #6,Y                        \
4367 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
4368 \ CMP #$0A,Y                      \
4369 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
4370 \ CMP #$16,Y                      \
4371 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
4372 \ ------------------------------\
4373 COLON                           \
4374 \ ------------------------------\
4375 \ Init LCD 2x20                 \
4376 \ ------------------------------\
4377     #1000 20_US                 \ 1- wait 20 ms
4378     %011 TOP_LCD                \ 2- send DB5=DB4=1
4379     #205 20_US                  \ 3- wait 4,1 ms
4380     %011 TOP_LCD                \ 4- send again DB5=DB4=1
4381     #5 20_US                    \ 5- wait 0,1 ms
4382     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
4383     #2 20_US                    \    wait 40 us = LCD cycle
4384     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
4385     #2 20_US                    \    wait 40 us = LCD cycle
4386     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
4387     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
4388     LCD_CLEAR                   \ 10- "LCD_Clear"
4389     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
4390     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
4391     LCD_CLEAR                   \ 10- "LCD_Clear"
4392     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
4393     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
4394     CR ." I love you"           \ display message on LCD
4395     ['] CR >BODY IS CR          \ CR executes its default value
4396     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
4397     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
4398     PWR_STATE ABORT             \ init DP and continues with ABORT
4399 ;                               \
4400 \ ------------------------------\
4401
4402 \ ------------------------------\
4403 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
4404 \ ------------------------------\
4405 MOV #SLEEP,X                    \ replace default background process SLEEP
4406 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
4407 MOV #WARM,X                     \ replace default WARM
4408 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
4409 MOV X,PC                        \ then execute new WARM
4410 ENDCODE 
4411 \ ------------------------------\
4412
4413 ECHO
4414             ; downloading RC5toLCD.4th is done
4415 RST_HERE    ; this app is protected against <reset>
4416
4417
4418 RST_STATE
4419
4420 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
4421
4422 [UNDEFINED] MARKER [IF]
4423 \  https://forth-standard.org/standard/core/MARKER
4424 \  MARKER
4425 \ ( "<spaces>name" -- )
4426 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
4427 \ with the execution semantics defined below.
4428
4429 \ name Execution: ( -- )
4430 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
4431 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
4432 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
4433 \ not necessarily provided. No other contextual information such as numeric base is affected
4434 \
4435 : MARKER
4436 CREATE
4437 HI2LO
4438 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
4439 SUB #2,Y            \ 1 Y = LFA
4440 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
4441 ADD #4,&DP          \ 3 add 2 cells
4442 LO2HI
4443 DOES>
4444 HI2LO
4445 MOV @RSP+,IP        \ -- PFA
4446 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
4447 MOV @TOS,&INIDP     \       set DP value for RST_STATE
4448 MOV @PSP+,TOS       \ --
4449 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
4450 ENDCODE
4451 [THEN]
4452
4453 MARKER {RC5TOLCD}
4454
4455 [UNDEFINED] @ [IF]
4456 \ https://forth-standard.org/standard/core/Fetch
4457 \ @     c-addr -- char   fetch char from memory
4458 CODE @
4459 MOV @TOS,TOS
4460 MOV @IP+,PC
4461 ENDCODE
4462 [THEN]
4463
4464 [UNDEFINED] CONSTANT [IF]
4465 \ https://forth-standard.org/standard/core/CONSTANT
4466 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
4467 : CONSTANT 
4468 CREATE
4469 HI2LO
4470 MOV TOS,-2(W)           \   PFA = n
4471 MOV @PSP+,TOS
4472 MOV @RSP+,IP
4473 MOV @IP+,PC
4474 ENDCODE
4475 [THEN]
4476
4477 [UNDEFINED] STATE [IF]
4478 \ https://forth-standard.org/standard/core/STATE
4479 \ STATE   -- a-addr       holds compiler state
4480 STATEADR CONSTANT STATE
4481 [THEN]
4482
4483 [UNDEFINED] = [IF]
4484 \ https://forth-standard.org/standard/core/Equal
4485 \ =      x1 x2 -- flag         test x1=x2
4486 CODE =
4487 SUB @PSP+,TOS   \ 2
4488 0<> IF          \ 2
4489     AND #0,TOS  \ 1
4490     MOV @IP+,PC \ 4
4491 THEN
4492 XOR #-1,TOS     \ 1 flag Z = 1
4493 MOV @IP+,PC     \ 4
4494 ENDCODE
4495 [THEN]
4496
4497 [UNDEFINED] IF [IF]
4498 \ https://forth-standard.org/standard/core/IF
4499 \ IF       -- IFadr    initialize conditional forward branch
4500 CODE IF       \ immediate
4501 SUB #2,PSP              \
4502 MOV TOS,0(PSP)          \
4503 MOV &DP,TOS             \ -- HERE
4504 ADD #4,&DP            \           compile one word, reserve one word
4505 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
4506 ADD #2,TOS              \ -- HERE+2=IFadr
4507 MOV @IP+,PC
4508 ENDCODE IMMEDIATE
4509 [THEN]
4510
4511 [UNDEFINED] THEN [IF]
4512 \ https://forth-standard.org/standard/core/THEN
4513 \ THEN     IFadr --                resolve forward branch
4514 CODE THEN               \ immediate
4515 MOV &DP,0(TOS)          \ -- IFadr
4516 MOV @PSP+,TOS           \ --
4517 MOV @IP+,PC
4518 ENDCODE IMMEDIATE
4519 [THEN]
4520
4521 [UNDEFINED] ELSE [IF]
4522 \ https://forth-standard.org/standard/core/ELSE
4523 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
4524 CODE ELSE     \ immediate
4525 ADD #4,&DP              \ make room to compile two words
4526 MOV &DP,W               \ W=HERE+4
4527 MOV #BRAN,-4(W)
4528 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
4529 SUB #2,W                \ HERE+2
4530 MOV W,TOS               \ -- ELSEadr
4531 MOV @IP+,PC
4532 ENDCODE IMMEDIATE
4533 [THEN]
4534
4535 [UNDEFINED] DEFER [IF]
4536 \ https://forth-standard.org/standard/core/DEFER
4537 \ DEFER "<spaces>name"   --
4538 \ Skip leading space delimiters. Parse name delimited by a space.
4539 \ Create a definition for name with the execution semantics defined below.
4540
4541 \ name Execution:   --
4542 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
4543 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
4544 : DEFER
4545 CREATE
4546 HI2LO
4547 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
4548 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
4549 MOV @RSP+,IP
4550 MOV @IP+,PC
4551 ENDCODE
4552 [THEN]
4553
4554 [UNDEFINED] DEFER! [IF]
4555 \ https://forth-standard.org/standard/core/DEFERStore
4556 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
4557 CODE DEFER!             \ xt2 xt1 --
4558 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
4559 MOV @PSP+,TOS           \ --
4560 MOV @IP+,PC
4561 ENDCODE
4562 [THEN]
4563
4564 [UNDEFINED] IS [IF]
4565 \ https://forth-standard.org/standard/core/IS
4566 \ IS <name>        xt --
4567 \ used as is :
4568 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
4569 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
4570 \ or in a definition : ... ['] U. IS DISPLAY ...
4571 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
4572 \
4573 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
4574 : IS
4575 STATE @
4576 IF  POSTPONE ['] POSTPONE DEFER! 
4577 ELSE ' DEFER! 
4578 THEN
4579 ; IMMEDIATE
4580 [THEN]
4581
4582 [UNDEFINED] >BODY [IF]
4583 \ https://forth-standard.org/standard/core/toBODY
4584 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
4585 CODE >BODY
4586 ADD #4,TOS
4587 MOV @IP+,PC
4588 ENDCODE
4589 [THEN]
4590
4591 \ CODE 20uS           \ n --      8MHz version
4592 \ BEGIN               \ 4 + 16 ~ loop
4593 \     MOV #39,rDOCON   \ 39
4594 \     BEGIN           \ 4 ~ loop
4595 \         NOP
4596 \         SUB #1,rDOCON
4597 \     0=  UNTIL
4598 \     SUB #1,TOS      \ 1
4599 \ 0= UNTIL
4600 \ MOV #XDOCON,rDOCON  \ 2
4601 \ MOV @PSP+,TOS
4602 \ MOV @RSP+,IP        \
4603 \ ENDCODE
4604
4605 CODE 20_US                      \ n --      n * 20 us
4606 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
4607     BEGIN
4608         BIT #1,&LCD_TIM_CTL     \ 3
4609     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
4610     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
4611     SUB #1,TOS                  \ 1
4612 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
4613 MOV @PSP+,TOS                   \ 2
4614 MOV @IP+,PC                     \ 4
4615 ENDCODE
4616
4617 CODE TOP_LCD                    \ LCD Sample
4618 \                               \ if write : %xxxx_WWWW --
4619 \                               \ if read  : -- %0000_RRRR
4620     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
4621     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
4622 0= IF                           \ write LCD bits pattern
4623     AND.B #LCD_DB,TOS           \ 
4624     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
4625     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
4626     MOV @PSP+,TOS               \
4627     MOV @IP+,PC
4628 THEN                            \ read LCD bits pattern
4629     SUB #2,PSP
4630     MOV TOS,0(PSP)
4631     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
4632     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
4633     AND.B #LCD_DB,TOS           \
4634     MOV @IP+,PC
4635 ENDCODE
4636
4637 CODE LCD_WRC                    \ char --         Write Char
4638     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
4639 BW1 SUB #2,PSP                  \
4640     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
4641     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
4642     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
4643     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
4644 COLON                           \ high level word starts here 
4645     TOP_LCD 2 20_US             \ write high nibble first
4646     TOP_LCD 2 20_US 
4647 ;
4648
4649 CODE LCD_WRF                    \ func --         Write Fonction
4650     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
4651     GOTO BW1
4652 ENDCODE
4653
4654 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
4655 : LCD_HOME $02 LCD_WRF 100 20_us ;
4656
4657 \ [UNDEFINED] OR [IF]
4658
4659 \ \ https://forth-standard.org/standard/core/OR
4660 \ \ C OR     x1 x2 -- x3           logical OR
4661 \ CODE OR
4662 \ BIS @PSP+,TOS
4663 \ MOV @IP+,PC
4664 \ ENDCODE
4665
4666 \ [THEN]
4667
4668 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
4669 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
4670 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
4671 \ : LCD_FN_SET        $20 OR LCD_WrF ;
4672 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
4673 \ : LCD_GOTO          $80 OR LCD_WrF ;
4674
4675
4676 \ CODE LCD_RDS                    \ -- status       Read Status
4677 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
4678 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
4679 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
4680 \ COLON                           \ starts a FORTH word
4681 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
4682 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
4683 \ HI2LO                           \ switch from FORTH to assembler
4684 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
4685 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
4686 \     MOV @RSP+,IP                \ restore IP saved by COLON
4687 \     MOV @IP+,PC                 \
4688 \ ENDCODE
4689
4690 \ CODE LCD_RDC                    \ -- char         Read Char
4691 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
4692 \     GOTO BW1
4693 \ ENDCODE
4694
4695
4696 \ ******************************\
4697 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
4698 \ ******************************\
4699 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
4700 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
4701 BIT.B #SW2,&SW2_IN              \ test switch S2
4702 0= IF                           \ case of switch S2 pressed
4703     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
4704     U< IF
4705         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
4706     THEN
4707 ELSE
4708     BIT.B #SW1,&SW1_IN          \ test switch S1 input
4709     0= IF                       \ case of Switch S1 pressed
4710         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
4711         U>= IF                  \
4712            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
4713         THEN                    \
4714     THEN                        \
4715 THEN                            \
4716 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
4717 RET                             \ 5
4718 ENDASM
4719
4720 \ ******************************\
4721 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
4722 \ ******************************\
4723 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
4724 \ ******************************\
4725 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
4726 \                               \       SMclock = 8|16|24 MHz
4727 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
4728 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
4729 \                               \       SR(9)=new Toggle bit memory (ADD on)
4730 \ ******************************\
4731 \ RC5_FirstStartBitHalfCycle:   \
4732 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
4733 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
4734 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
4735 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
4736 \ [THEN]
4737 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
4738     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
4739 [THEN]
4740 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
4741     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
4742 [THEN]
4743 MOV #1778,X                     \ RC5_Period * 1us
4744 MOV #14,W                       \ count of loop
4745 BEGIN                           \
4746 \ ******************************\
4747 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
4748 \ ******************************\                   |
4749 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
4750 \ RC5_Compute_3/4_Period:       \                   |
4751     RRUM    #1,X                \ X=1/2 cycle       |
4752     MOV     X,Y                 \                   ^
4753     RRUM    #1,Y                \ Y=1/4
4754     ADD     X,Y                 \ Y=3/4 cycle
4755     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
4756     U>= UNTIL                   \ 2
4757 \ ******************************\
4758 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
4759 \ ******************************\
4760     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
4761     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
4762     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
4763     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
4764     SUB     #1,W                \ decrement count loop
4765 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
4766 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
4767 0<> WHILE                       \ ----> out of loop ----+
4768     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
4769     BEGIN                       \                       |
4770         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
4771         CMP Y,X                 \ 1                     |   cycle time out of bound ?
4772         U>= IF                  \ 2                 ^   |   yes:
4773         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
4774         GOTO BW1                \                   |   |      quit on truncated RC5 message
4775         THEN                    \                   |   |
4776         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
4777     0<> UNTIL                   \ 2                 |   |
4778 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
4779 \ ******************************\                       |
4780 \ RC5_SampleEndOf:              \ <---------------------+
4781 \ ******************************\
4782 BIC #$30,&RC5_TIM_CTL           \   stop timer
4783 \ ******************************\
4784 \ RC5_ComputeNewRC5word         \
4785 \ ******************************\
4786 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
4787 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
4788 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
4789 \ ******************************\
4790 \ RC5_ComputeC6bit              \
4791 \ ******************************\
4792 BIT     #BIT14,T                \ test /C6 bit in T
4793 0= IF   BIS #BIT6,X             \ set C6 bit in X
4794 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
4795 \ ******************************\
4796 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
4797 \ ******************************\
4798 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
4799 \ ******************************\
4800 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
4801 XOR     @RSP,T                  \ (new XOR old) Toggle bits
4802 BIT     #UF10,T                 \ repeated RC5_command ?
4803 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
4804 XOR #UF10,0(RSP)                \ 5 toggle bit memory
4805 \ ******************************\
4806 \ Display IR_RC5 code           \
4807 \ ******************************\
4808 SUB #8,PSP                      \ TOS -- x x x x TOS
4809 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
4810 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
4811 MOV #$10,&BASEADR               \                                               set hexadecimal base
4812 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
4813 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
4814 LO2HI                           \                                               switch from assembler to FORTH
4815     LCD_CLEAR                   \                                               set LCD cursor at home
4816     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
4817     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
4818     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
4819     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
4820 HI2LO                           \     --                                        switch from FORTH to assembler
4821 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
4822 MOV @PSP+,TOS                   \     -- TOS
4823 RET
4824 ENDASM
4825
4826 \ ******************************\
4827 ASM BACKGROUND                  \
4828 \ ******************************\
4829 BEGIN
4830 \     ...                         \ insert here your background task
4831 \     ...                         \
4832 \     ...                         \
4833     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
4834     BIS &LPM_MODE,SR            \
4835 \ ******************************\
4836 \ here start all interrupts     \
4837 \ ******************************\
4838 \ here return all interrupts    \
4839 \ ******************************\
4840 AGAIN                           \
4841 ENDASM                          \
4842 \ ******************************\
4843
4844 \ ------------------------------\
4845 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
4846 \ ------------------------------\
4847 \     ...                         \ init specific I/O sys as you want
4848 \     ...                         \ before executing default WARM
4849     MOV #WARM,X                 \ ['] WARM 
4850     ADD #4,X                    \ >BODY
4851     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
4852 ENDASM
4853 \ ------------------------------\
4854
4855 \ ------------------------------\
4856 CODE STOP                       \ stops multitasking, must to be used before downloading app
4857 \ ------------------------------\
4858 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
4859     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
4860     MOV X,-2(X)                 \ restore the default background: SLEEP
4861     MOV #WARM,X
4862     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
4863     BIC.B #RC5,&IR_IE           \ clear RC5_Int
4864     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
4865     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
4866     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
4867     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
4868     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
4869 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
4870 ECHO                            \
4871 ." RC5toLCD is removed,"
4872 ."  type START to restart"
4873  WARM                           \ performs reset to reset all interrupt vectors.    
4874 ;
4875 \ ------------------------------\
4876
4877 \ ------------------------------\
4878 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
4879 \ ------------------------------\
4880 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
4881 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
4882 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
4883 \                           --       \ID input divider \ 10 = /4
4884 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
4885 \                                 -  \TBCLR TimerB Clear
4886 \                                  - \TBIE
4887 \                                   -\TBIFG
4888 \ -------------------------------\
4889 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
4890 \                  --                 \CM Capture Mode
4891 \                    --               \CCIS
4892 \                       -             \SCS
4893 \                        --           \CLLD
4894 \                          -          \CAP
4895 \                            ---      \OUTMOD \ 011 = set/reset
4896 \                               -     \CCIE
4897 \                                 -   \CCI
4898 \                                  -  \OUT
4899 \                                   - \COV
4900 \                                    -\CCIFG
4901 \ -------------------------------\
4902 \ LCD_TIM_CCRx                   \
4903 \ -------------------------------\
4904 \ LCD_TIM_EX0                    \ 
4905 \ ------------------------------\
4906 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
4907 \ ------------------------------\
4908 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
4909 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
4910 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
4911     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
4912 [THEN]
4913 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
4914     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
4915 [THEN]
4916     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
4917 \ ------------------------------\
4918 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
4919 \ ------------------------------\
4920 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
4921     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
4922 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
4923 \ ------------------------------\
4924     BIS.B #LCDVo,&LCDVo_DIR     \
4925     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
4926 \ ------------------------------\
4927     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
4928     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
4929 \ ------------------------------\
4930     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
4931     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
4932 \ ******************************\
4933 \ init RC5_Int                  \
4934 \ ******************************\
4935     BIS.B #RC5,&IR_IE           \ enable RC5_Int
4936     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
4937     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
4938 \ ******************************\
4939 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
4940 \ ******************************\
4941 \              %01 0001 0100    \ TAxCTL
4942 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
4943 \                  --           \ ID        divided by 1
4944 \                    --         \ MC        MODE = up to TAxCCRn
4945 \                        -      \ TACLR     clear timer count
4946 \                         -     \ TAIE
4947 \                          -    \ TAIFG
4948 \ ------------------------------\
4949 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
4950 \ ------------------------------\
4951 \                        000    \ TAxEX0
4952 \                        ---    \ TAIDEX    pre divisor
4953 \ ------------------------------\
4954 \          %0000 0000 0000 0101 \ TAxCCR0
4955     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
4956 \ ------------------------------\
4957 \          %0000 0000 0001 0000 \ TAxCCTL0
4958 \                   -           \ CAP capture/compare mode = compare
4959 \                        -      \ CCIEn
4960 \                             - \ CCIFGn
4961     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
4962 \ ------------------------------\
4963     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
4964 \ ------------------------------\
4965 \ define LPM mode for ACCEPT    \
4966 \ ------------------------------\
4967 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
4968 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
4969 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
4970 \ ------------------------------\
4971 \ activate I/O                  \
4972 \ ------------------------------\
4973 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
4974 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
4975 \ ------------------------------\
4976 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
4977 \ ------------------------------\
4978 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
4979 \ CMP #2,Y                        \ Power_ON event
4980 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
4981 CMP #4,Y                        \
4982 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
4983 \ CMP #6,Y                        \
4984 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
4985 \ CMP #$0A,Y                      \
4986 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
4987 \ CMP #$16,Y                      \
4988 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
4989 \ ------------------------------\
4990 COLON                           \
4991 \ ------------------------------\
4992 \ Init LCD 2x20                 \
4993 \ ------------------------------\
4994     #1000 20_US                 \ 1- wait 20 ms
4995     %011 TOP_LCD                \ 2- send DB5=DB4=1
4996     #205 20_US                  \ 3- wait 4,1 ms
4997     %011 TOP_LCD                \ 4- send again DB5=DB4=1
4998     #5 20_US                    \ 5- wait 0,1 ms
4999     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
5000     #2 20_US                    \    wait 40 us = LCD cycle
5001     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
5002     #2 20_US                    \    wait 40 us = LCD cycle
5003     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
5004     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
5005     LCD_CLEAR                   \ 10- "LCD_Clear"
5006     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
5007     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
5008     LCD_CLEAR                   \ 10- "LCD_Clear"
5009     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
5010     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
5011     CR ." I love you"           \ display message on LCD
5012     ['] CR >BODY IS CR          \ CR executes its default value
5013     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
5014     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
5015     PWR_STATE ABORT             \ init DP and continues with ABORT
5016 ;                               \
5017 \ ------------------------------\
5018
5019 \ ------------------------------\
5020 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
5021 \ ------------------------------\
5022 MOV #SLEEP,X                    \ replace default background process SLEEP
5023 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
5024 MOV #WARM,X                     \ replace default WARM
5025 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
5026 MOV X,PC                        \ then execute new WARM
5027 ENDCODE 
5028 \ ------------------------------\
5029
5030 ECHO
5031             ; downloading RC5toLCD.4th is done
5032 RST_HERE    ; this app is protected against <reset>
5033
5034
5035 RST_STATE
5036
5037 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
5038
5039 [UNDEFINED] MARKER [IF]
5040 \  https://forth-standard.org/standard/core/MARKER
5041 \  MARKER
5042 \ ( "<spaces>name" -- )
5043 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
5044 \ with the execution semantics defined below.
5045
5046 \ name Execution: ( -- )
5047 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
5048 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
5049 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
5050 \ not necessarily provided. No other contextual information such as numeric base is affected
5051 \
5052 : MARKER
5053 CREATE
5054 HI2LO
5055 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
5056 SUB #2,Y            \ 1 Y = LFA
5057 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
5058 ADD #4,&DP          \ 3 add 2 cells
5059 LO2HI
5060 DOES>
5061 HI2LO
5062 MOV @RSP+,IP        \ -- PFA
5063 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
5064 MOV @TOS,&INIDP     \       set DP value for RST_STATE
5065 MOV @PSP+,TOS       \ --
5066 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
5067 ENDCODE
5068 [THEN]
5069
5070 MARKER {RC5TOLCD}
5071
5072 [UNDEFINED] @ [IF]
5073 \ https://forth-standard.org/standard/core/Fetch
5074 \ @     c-addr -- char   fetch char from memory
5075 CODE @
5076 MOV @TOS,TOS
5077 MOV @IP+,PC
5078 ENDCODE
5079 [THEN]
5080
5081 [UNDEFINED] CONSTANT [IF]
5082 \ https://forth-standard.org/standard/core/CONSTANT
5083 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
5084 : CONSTANT 
5085 CREATE
5086 HI2LO
5087 MOV TOS,-2(W)           \   PFA = n
5088 MOV @PSP+,TOS
5089 MOV @RSP+,IP
5090 MOV @IP+,PC
5091 ENDCODE
5092 [THEN]
5093
5094 [UNDEFINED] STATE [IF]
5095 \ https://forth-standard.org/standard/core/STATE
5096 \ STATE   -- a-addr       holds compiler state
5097 STATEADR CONSTANT STATE
5098 [THEN]
5099
5100 [UNDEFINED] = [IF]
5101 \ https://forth-standard.org/standard/core/Equal
5102 \ =      x1 x2 -- flag         test x1=x2
5103 CODE =
5104 SUB @PSP+,TOS   \ 2
5105 0<> IF          \ 2
5106     AND #0,TOS  \ 1
5107     MOV @IP+,PC \ 4
5108 THEN
5109 XOR #-1,TOS     \ 1 flag Z = 1
5110 MOV @IP+,PC     \ 4
5111 ENDCODE
5112 [THEN]
5113
5114 [UNDEFINED] IF [IF]
5115 \ https://forth-standard.org/standard/core/IF
5116 \ IF       -- IFadr    initialize conditional forward branch
5117 CODE IF       \ immediate
5118 SUB #2,PSP              \
5119 MOV TOS,0(PSP)          \
5120 MOV &DP,TOS             \ -- HERE
5121 ADD #4,&DP            \           compile one word, reserve one word
5122 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
5123 ADD #2,TOS              \ -- HERE+2=IFadr
5124 MOV @IP+,PC
5125 ENDCODE IMMEDIATE
5126 [THEN]
5127
5128 [UNDEFINED] THEN [IF]
5129 \ https://forth-standard.org/standard/core/THEN
5130 \ THEN     IFadr --                resolve forward branch
5131 CODE THEN               \ immediate
5132 MOV &DP,0(TOS)          \ -- IFadr
5133 MOV @PSP+,TOS           \ --
5134 MOV @IP+,PC
5135 ENDCODE IMMEDIATE
5136 [THEN]
5137
5138 [UNDEFINED] ELSE [IF]
5139 \ https://forth-standard.org/standard/core/ELSE
5140 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
5141 CODE ELSE     \ immediate
5142 ADD #4,&DP              \ make room to compile two words
5143 MOV &DP,W               \ W=HERE+4
5144 MOV #BRAN,-4(W)
5145 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
5146 SUB #2,W                \ HERE+2
5147 MOV W,TOS               \ -- ELSEadr
5148 MOV @IP+,PC
5149 ENDCODE IMMEDIATE
5150 [THEN]
5151
5152 [UNDEFINED] DEFER [IF]
5153 \ https://forth-standard.org/standard/core/DEFER
5154 \ DEFER "<spaces>name"   --
5155 \ Skip leading space delimiters. Parse name delimited by a space.
5156 \ Create a definition for name with the execution semantics defined below.
5157
5158 \ name Execution:   --
5159 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
5160 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
5161 : DEFER
5162 CREATE
5163 HI2LO
5164 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
5165 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
5166 MOV @RSP+,IP
5167 MOV @IP+,PC
5168 ENDCODE
5169 [THEN]
5170
5171 [UNDEFINED] DEFER! [IF]
5172 \ https://forth-standard.org/standard/core/DEFERStore
5173 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
5174 CODE DEFER!             \ xt2 xt1 --
5175 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
5176 MOV @PSP+,TOS           \ --
5177 MOV @IP+,PC
5178 ENDCODE
5179 [THEN]
5180
5181 [UNDEFINED] IS [IF]
5182 \ https://forth-standard.org/standard/core/IS
5183 \ IS <name>        xt --
5184 \ used as is :
5185 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
5186 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
5187 \ or in a definition : ... ['] U. IS DISPLAY ...
5188 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
5189 \
5190 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
5191 : IS
5192 STATE @
5193 IF  POSTPONE ['] POSTPONE DEFER! 
5194 ELSE ' DEFER! 
5195 THEN
5196 ; IMMEDIATE
5197 [THEN]
5198
5199 [UNDEFINED] >BODY [IF]
5200 \ https://forth-standard.org/standard/core/toBODY
5201 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
5202 CODE >BODY
5203 ADD #4,TOS
5204 MOV @IP+,PC
5205 ENDCODE
5206 [THEN]
5207
5208 \ CODE 20uS           \ n --      8MHz version
5209 \ BEGIN               \ 4 + 16 ~ loop
5210 \     MOV #39,rDOCON   \ 39
5211 \     BEGIN           \ 4 ~ loop
5212 \         NOP
5213 \         SUB #1,rDOCON
5214 \     0=  UNTIL
5215 \     SUB #1,TOS      \ 1
5216 \ 0= UNTIL
5217 \ MOV #XDOCON,rDOCON  \ 2
5218 \ MOV @PSP+,TOS
5219 \ MOV @RSP+,IP        \
5220 \ ENDCODE
5221
5222 CODE 20_US                      \ n --      n * 20 us
5223 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
5224     BEGIN
5225         BIT #1,&LCD_TIM_CTL     \ 3
5226     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
5227     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
5228     SUB #1,TOS                  \ 1
5229 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
5230 MOV @PSP+,TOS                   \ 2
5231 MOV @IP+,PC                     \ 4
5232 ENDCODE
5233
5234 CODE TOP_LCD                    \ LCD Sample
5235 \                               \ if write : %xxxx_WWWW --
5236 \                               \ if read  : -- %0000_RRRR
5237     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
5238     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
5239 0= IF                           \ write LCD bits pattern
5240     AND.B #LCD_DB,TOS           \ 
5241     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
5242     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
5243     MOV @PSP+,TOS               \
5244     MOV @IP+,PC
5245 THEN                            \ read LCD bits pattern
5246     SUB #2,PSP
5247     MOV TOS,0(PSP)
5248     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
5249     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
5250     AND.B #LCD_DB,TOS           \
5251     MOV @IP+,PC
5252 ENDCODE
5253
5254 CODE LCD_WRC                    \ char --         Write Char
5255     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
5256 BW1 SUB #2,PSP                  \
5257     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
5258     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
5259     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
5260     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
5261 COLON                           \ high level word starts here 
5262     TOP_LCD 2 20_US             \ write high nibble first
5263     TOP_LCD 2 20_US 
5264 ;
5265
5266 CODE LCD_WRF                    \ func --         Write Fonction
5267     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
5268     GOTO BW1
5269 ENDCODE
5270
5271 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
5272 : LCD_HOME $02 LCD_WRF 100 20_us ;
5273
5274 \ [UNDEFINED] OR [IF]
5275
5276 \ \ https://forth-standard.org/standard/core/OR
5277 \ \ C OR     x1 x2 -- x3           logical OR
5278 \ CODE OR
5279 \ BIS @PSP+,TOS
5280 \ MOV @IP+,PC
5281 \ ENDCODE
5282
5283 \ [THEN]
5284
5285 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
5286 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
5287 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
5288 \ : LCD_FN_SET        $20 OR LCD_WrF ;
5289 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
5290 \ : LCD_GOTO          $80 OR LCD_WrF ;
5291
5292
5293 \ CODE LCD_RDS                    \ -- status       Read Status
5294 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
5295 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
5296 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
5297 \ COLON                           \ starts a FORTH word
5298 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
5299 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
5300 \ HI2LO                           \ switch from FORTH to assembler
5301 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
5302 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
5303 \     MOV @RSP+,IP                \ restore IP saved by COLON
5304 \     MOV @IP+,PC                 \
5305 \ ENDCODE
5306
5307 \ CODE LCD_RDC                    \ -- char         Read Char
5308 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
5309 \     GOTO BW1
5310 \ ENDCODE
5311
5312
5313 \ ******************************\
5314 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
5315 \ ******************************\
5316 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
5317 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
5318 BIT.B #SW2,&SW2_IN              \ test switch S2
5319 0= IF                           \ case of switch S2 pressed
5320     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
5321     U< IF
5322         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
5323     THEN
5324 ELSE
5325     BIT.B #SW1,&SW1_IN          \ test switch S1 input
5326     0= IF                       \ case of Switch S1 pressed
5327         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
5328         U>= IF                  \
5329            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
5330         THEN                    \
5331     THEN                        \
5332 THEN                            \
5333 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
5334 RET                             \ 5
5335 ENDASM
5336
5337 \ ******************************\
5338 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
5339 \ ******************************\
5340 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
5341 \ ******************************\
5342 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
5343 \                               \       SMclock = 8|16|24 MHz
5344 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
5345 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
5346 \                               \       SR(9)=new Toggle bit memory (ADD on)
5347 \ ******************************\
5348 \ RC5_FirstStartBitHalfCycle:   \
5349 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
5350 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
5351 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
5352 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
5353 \ [THEN]
5354 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
5355     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
5356 [THEN]
5357 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
5358     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
5359 [THEN]
5360 MOV #1778,X                     \ RC5_Period * 1us
5361 MOV #14,W                       \ count of loop
5362 BEGIN                           \
5363 \ ******************************\
5364 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
5365 \ ******************************\                   |
5366 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
5367 \ RC5_Compute_3/4_Period:       \                   |
5368     RRUM    #1,X                \ X=1/2 cycle       |
5369     MOV     X,Y                 \                   ^
5370     RRUM    #1,Y                \ Y=1/4
5371     ADD     X,Y                 \ Y=3/4 cycle
5372     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
5373     U>= UNTIL                   \ 2
5374 \ ******************************\
5375 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
5376 \ ******************************\
5377     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
5378     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
5379     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
5380     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
5381     SUB     #1,W                \ decrement count loop
5382 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
5383 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
5384 0<> WHILE                       \ ----> out of loop ----+
5385     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
5386     BEGIN                       \                       |
5387         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
5388         CMP Y,X                 \ 1                     |   cycle time out of bound ?
5389         U>= IF                  \ 2                 ^   |   yes:
5390         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
5391         GOTO BW1                \                   |   |      quit on truncated RC5 message
5392         THEN                    \                   |   |
5393         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
5394     0<> UNTIL                   \ 2                 |   |
5395 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
5396 \ ******************************\                       |
5397 \ RC5_SampleEndOf:              \ <---------------------+
5398 \ ******************************\
5399 BIC #$30,&RC5_TIM_CTL           \   stop timer
5400 \ ******************************\
5401 \ RC5_ComputeNewRC5word         \
5402 \ ******************************\
5403 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
5404 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
5405 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
5406 \ ******************************\
5407 \ RC5_ComputeC6bit              \
5408 \ ******************************\
5409 BIT     #BIT14,T                \ test /C6 bit in T
5410 0= IF   BIS #BIT6,X             \ set C6 bit in X
5411 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
5412 \ ******************************\
5413 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
5414 \ ******************************\
5415 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
5416 \ ******************************\
5417 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
5418 XOR     @RSP,T                  \ (new XOR old) Toggle bits
5419 BIT     #UF10,T                 \ repeated RC5_command ?
5420 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
5421 XOR #UF10,0(RSP)                \ 5 toggle bit memory
5422 \ ******************************\
5423 \ Display IR_RC5 code           \
5424 \ ******************************\
5425 SUB #8,PSP                      \ TOS -- x x x x TOS
5426 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
5427 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
5428 MOV #$10,&BASEADR               \                                               set hexadecimal base
5429 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
5430 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
5431 LO2HI                           \                                               switch from assembler to FORTH
5432     LCD_CLEAR                   \                                               set LCD cursor at home
5433     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
5434     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
5435     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
5436     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
5437 HI2LO                           \     --                                        switch from FORTH to assembler
5438 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
5439 MOV @PSP+,TOS                   \     -- TOS
5440 RET
5441 ENDASM
5442
5443 \ ******************************\
5444 ASM BACKGROUND                  \
5445 \ ******************************\
5446 BEGIN
5447 \     ...                         \ insert here your background task
5448 \     ...                         \
5449 \     ...                         \
5450     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
5451     BIS &LPM_MODE,SR            \
5452 \ ******************************\
5453 \ here start all interrupts     \
5454 \ ******************************\
5455 \ here return all interrupts    \
5456 \ ******************************\
5457 AGAIN                           \
5458 ENDASM                          \
5459 \ ******************************\
5460
5461 \ ------------------------------\
5462 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
5463 \ ------------------------------\
5464 \     ...                         \ init specific I/O sys as you want
5465 \     ...                         \ before executing default WARM
5466     MOV #WARM,X                 \ ['] WARM 
5467     ADD #4,X                    \ >BODY
5468     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
5469 ENDASM
5470 \ ------------------------------\
5471
5472 \ ------------------------------\
5473 CODE STOP                       \ stops multitasking, must to be used before downloading app
5474 \ ------------------------------\
5475 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
5476     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
5477     MOV X,-2(X)                 \ restore the default background: SLEEP
5478     MOV #WARM,X
5479     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
5480     BIC.B #RC5,&IR_IE           \ clear RC5_Int
5481     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
5482     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
5483     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
5484     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
5485     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
5486 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
5487 ECHO                            \
5488 ." RC5toLCD is removed,"
5489 ."  type START to restart"
5490  WARM                           \ performs reset to reset all interrupt vectors.    
5491 ;
5492 \ ------------------------------\
5493
5494 \ ------------------------------\
5495 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
5496 \ ------------------------------\
5497 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
5498 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
5499 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
5500 \                           --       \ID input divider \ 10 = /4
5501 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
5502 \                                 -  \TBCLR TimerB Clear
5503 \                                  - \TBIE
5504 \                                   -\TBIFG
5505 \ -------------------------------\
5506 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
5507 \                  --                 \CM Capture Mode
5508 \                    --               \CCIS
5509 \                       -             \SCS
5510 \                        --           \CLLD
5511 \                          -          \CAP
5512 \                            ---      \OUTMOD \ 011 = set/reset
5513 \                               -     \CCIE
5514 \                                 -   \CCI
5515 \                                  -  \OUT
5516 \                                   - \COV
5517 \                                    -\CCIFG
5518 \ -------------------------------\
5519 \ LCD_TIM_CCRx                   \
5520 \ -------------------------------\
5521 \ LCD_TIM_EX0                    \ 
5522 \ ------------------------------\
5523 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
5524 \ ------------------------------\
5525 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
5526 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
5527 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
5528     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
5529 [THEN]
5530 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
5531     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
5532 [THEN]
5533     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
5534 \ ------------------------------\
5535 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
5536 \ ------------------------------\
5537 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
5538     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
5539 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
5540 \ ------------------------------\
5541     BIS.B #LCDVo,&LCDVo_DIR     \
5542     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
5543 \ ------------------------------\
5544     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
5545     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
5546 \ ------------------------------\
5547     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
5548     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
5549 \ ******************************\
5550 \ init RC5_Int                  \
5551 \ ******************************\
5552     BIS.B #RC5,&IR_IE           \ enable RC5_Int
5553     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
5554     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
5555 \ ******************************\
5556 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
5557 \ ******************************\
5558 \              %01 0001 0100    \ TAxCTL
5559 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
5560 \                  --           \ ID        divided by 1
5561 \                    --         \ MC        MODE = up to TAxCCRn
5562 \                        -      \ TACLR     clear timer count
5563 \                         -     \ TAIE
5564 \                          -    \ TAIFG
5565 \ ------------------------------\
5566 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
5567 \ ------------------------------\
5568 \                        000    \ TAxEX0
5569 \                        ---    \ TAIDEX    pre divisor
5570 \ ------------------------------\
5571 \          %0000 0000 0000 0101 \ TAxCCR0
5572     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
5573 \ ------------------------------\
5574 \          %0000 0000 0001 0000 \ TAxCCTL0
5575 \                   -           \ CAP capture/compare mode = compare
5576 \                        -      \ CCIEn
5577 \                             - \ CCIFGn
5578     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
5579 \ ------------------------------\
5580     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
5581 \ ------------------------------\
5582 \ define LPM mode for ACCEPT    \
5583 \ ------------------------------\
5584 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
5585 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
5586 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
5587 \ ------------------------------\
5588 \ activate I/O                  \
5589 \ ------------------------------\
5590 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
5591 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
5592 \ ------------------------------\
5593 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
5594 \ ------------------------------\
5595 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
5596 \ CMP #2,Y                        \ Power_ON event
5597 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
5598 CMP #4,Y                        \
5599 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
5600 \ CMP #6,Y                        \
5601 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
5602 \ CMP #$0A,Y                      \
5603 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
5604 \ CMP #$16,Y                      \
5605 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
5606 \ ------------------------------\
5607 COLON                           \
5608 \ ------------------------------\
5609 \ Init LCD 2x20                 \
5610 \ ------------------------------\
5611     #1000 20_US                 \ 1- wait 20 ms
5612     %011 TOP_LCD                \ 2- send DB5=DB4=1
5613     #205 20_US                  \ 3- wait 4,1 ms
5614     %011 TOP_LCD                \ 4- send again DB5=DB4=1
5615     #5 20_US                    \ 5- wait 0,1 ms
5616     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
5617     #2 20_US                    \    wait 40 us = LCD cycle
5618     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
5619     #2 20_US                    \    wait 40 us = LCD cycle
5620     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
5621     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
5622     LCD_CLEAR                   \ 10- "LCD_Clear"
5623     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
5624     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
5625     LCD_CLEAR                   \ 10- "LCD_Clear"
5626     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
5627     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
5628     CR ." I love you"           \ display message on LCD
5629     ['] CR >BODY IS CR          \ CR executes its default value
5630     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
5631     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
5632     PWR_STATE ABORT             \ init DP and continues with ABORT
5633 ;                               \
5634 \ ------------------------------\
5635
5636 \ ------------------------------\
5637 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
5638 \ ------------------------------\
5639 MOV #SLEEP,X                    \ replace default background process SLEEP
5640 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
5641 MOV #WARM,X                     \ replace default WARM
5642 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
5643 MOV X,PC                        \ then execute new WARM
5644 ENDCODE 
5645 \ ------------------------------\
5646
5647 ECHO
5648             ; downloading RC5toLCD.4th is done
5649 RST_HERE    ; this app is protected against <reset>
5650
5651
5652 RST_STATE
5653
5654 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
5655
5656 [UNDEFINED] MARKER [IF]
5657 \  https://forth-standard.org/standard/core/MARKER
5658 \  MARKER
5659 \ ( "<spaces>name" -- )
5660 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
5661 \ with the execution semantics defined below.
5662
5663 \ name Execution: ( -- )
5664 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
5665 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
5666 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
5667 \ not necessarily provided. No other contextual information such as numeric base is affected
5668 \
5669 : MARKER
5670 CREATE
5671 HI2LO
5672 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
5673 SUB #2,Y            \ 1 Y = LFA
5674 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
5675 ADD #4,&DP          \ 3 add 2 cells
5676 LO2HI
5677 DOES>
5678 HI2LO
5679 MOV @RSP+,IP        \ -- PFA
5680 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
5681 MOV @TOS,&INIDP     \       set DP value for RST_STATE
5682 MOV @PSP+,TOS       \ --
5683 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
5684 ENDCODE
5685 [THEN]
5686
5687 MARKER {RC5TOLCD}
5688
5689 [UNDEFINED] @ [IF]
5690 \ https://forth-standard.org/standard/core/Fetch
5691 \ @     c-addr -- char   fetch char from memory
5692 CODE @
5693 MOV @TOS,TOS
5694 MOV @IP+,PC
5695 ENDCODE
5696 [THEN]
5697
5698 [UNDEFINED] CONSTANT [IF]
5699 \ https://forth-standard.org/standard/core/CONSTANT
5700 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
5701 : CONSTANT 
5702 CREATE
5703 HI2LO
5704 MOV TOS,-2(W)           \   PFA = n
5705 MOV @PSP+,TOS
5706 MOV @RSP+,IP
5707 MOV @IP+,PC
5708 ENDCODE
5709 [THEN]
5710
5711 [UNDEFINED] STATE [IF]
5712 \ https://forth-standard.org/standard/core/STATE
5713 \ STATE   -- a-addr       holds compiler state
5714 STATEADR CONSTANT STATE
5715 [THEN]
5716
5717 [UNDEFINED] = [IF]
5718 \ https://forth-standard.org/standard/core/Equal
5719 \ =      x1 x2 -- flag         test x1=x2
5720 CODE =
5721 SUB @PSP+,TOS   \ 2
5722 0<> IF          \ 2
5723     AND #0,TOS  \ 1
5724     MOV @IP+,PC \ 4
5725 THEN
5726 XOR #-1,TOS     \ 1 flag Z = 1
5727 MOV @IP+,PC     \ 4
5728 ENDCODE
5729 [THEN]
5730
5731 [UNDEFINED] IF [IF]
5732 \ https://forth-standard.org/standard/core/IF
5733 \ IF       -- IFadr    initialize conditional forward branch
5734 CODE IF       \ immediate
5735 SUB #2,PSP              \
5736 MOV TOS,0(PSP)          \
5737 MOV &DP,TOS             \ -- HERE
5738 ADD #4,&DP            \           compile one word, reserve one word
5739 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
5740 ADD #2,TOS              \ -- HERE+2=IFadr
5741 MOV @IP+,PC
5742 ENDCODE IMMEDIATE
5743 [THEN]
5744
5745 [UNDEFINED] THEN [IF]
5746 \ https://forth-standard.org/standard/core/THEN
5747 \ THEN     IFadr --                resolve forward branch
5748 CODE THEN               \ immediate
5749 MOV &DP,0(TOS)          \ -- IFadr
5750 MOV @PSP+,TOS           \ --
5751 MOV @IP+,PC
5752 ENDCODE IMMEDIATE
5753 [THEN]
5754
5755 [UNDEFINED] ELSE [IF]
5756 \ https://forth-standard.org/standard/core/ELSE
5757 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
5758 CODE ELSE     \ immediate
5759 ADD #4,&DP              \ make room to compile two words
5760 MOV &DP,W               \ W=HERE+4
5761 MOV #BRAN,-4(W)
5762 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
5763 SUB #2,W                \ HERE+2
5764 MOV W,TOS               \ -- ELSEadr
5765 MOV @IP+,PC
5766 ENDCODE IMMEDIATE
5767 [THEN]
5768
5769 [UNDEFINED] DEFER [IF]
5770 \ https://forth-standard.org/standard/core/DEFER
5771 \ DEFER "<spaces>name"   --
5772 \ Skip leading space delimiters. Parse name delimited by a space.
5773 \ Create a definition for name with the execution semantics defined below.
5774
5775 \ name Execution:   --
5776 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
5777 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
5778 : DEFER
5779 CREATE
5780 HI2LO
5781 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
5782 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
5783 MOV @RSP+,IP
5784 MOV @IP+,PC
5785 ENDCODE
5786 [THEN]
5787
5788 [UNDEFINED] DEFER! [IF]
5789 \ https://forth-standard.org/standard/core/DEFERStore
5790 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
5791 CODE DEFER!             \ xt2 xt1 --
5792 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
5793 MOV @PSP+,TOS           \ --
5794 MOV @IP+,PC
5795 ENDCODE
5796 [THEN]
5797
5798 [UNDEFINED] IS [IF]
5799 \ https://forth-standard.org/standard/core/IS
5800 \ IS <name>        xt --
5801 \ used as is :
5802 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
5803 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
5804 \ or in a definition : ... ['] U. IS DISPLAY ...
5805 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
5806 \
5807 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
5808 : IS
5809 STATE @
5810 IF  POSTPONE ['] POSTPONE DEFER! 
5811 ELSE ' DEFER! 
5812 THEN
5813 ; IMMEDIATE
5814 [THEN]
5815
5816 [UNDEFINED] >BODY [IF]
5817 \ https://forth-standard.org/standard/core/toBODY
5818 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
5819 CODE >BODY
5820 ADD #4,TOS
5821 MOV @IP+,PC
5822 ENDCODE
5823 [THEN]
5824
5825 \ CODE 20uS           \ n --      8MHz version
5826 \ BEGIN               \ 4 + 16 ~ loop
5827 \     MOV #39,rDOCON   \ 39
5828 \     BEGIN           \ 4 ~ loop
5829 \         NOP
5830 \         SUB #1,rDOCON
5831 \     0=  UNTIL
5832 \     SUB #1,TOS      \ 1
5833 \ 0= UNTIL
5834 \ MOV #XDOCON,rDOCON  \ 2
5835 \ MOV @PSP+,TOS
5836 \ MOV @RSP+,IP        \
5837 \ ENDCODE
5838
5839 CODE 20_US                      \ n --      n * 20 us
5840 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
5841     BEGIN
5842         BIT #1,&LCD_TIM_CTL     \ 3
5843     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
5844     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
5845     SUB #1,TOS                  \ 1
5846 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
5847 MOV @PSP+,TOS                   \ 2
5848 MOV @IP+,PC                     \ 4
5849 ENDCODE
5850
5851 CODE TOP_LCD                    \ LCD Sample
5852 \                               \ if write : %xxxx_WWWW --
5853 \                               \ if read  : -- %0000_RRRR
5854     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
5855     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
5856 0= IF                           \ write LCD bits pattern
5857     AND.B #LCD_DB,TOS           \ 
5858     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
5859     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
5860     MOV @PSP+,TOS               \
5861     MOV @IP+,PC
5862 THEN                            \ read LCD bits pattern
5863     SUB #2,PSP
5864     MOV TOS,0(PSP)
5865     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
5866     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
5867     AND.B #LCD_DB,TOS           \
5868     MOV @IP+,PC
5869 ENDCODE
5870
5871 CODE LCD_WRC                    \ char --         Write Char
5872     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
5873 BW1 SUB #2,PSP                  \
5874     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
5875     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
5876     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
5877     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
5878 COLON                           \ high level word starts here 
5879     TOP_LCD 2 20_US             \ write high nibble first
5880     TOP_LCD 2 20_US 
5881 ;
5882
5883 CODE LCD_WRF                    \ func --         Write Fonction
5884     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
5885     GOTO BW1
5886 ENDCODE
5887
5888 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
5889 : LCD_HOME $02 LCD_WRF 100 20_us ;
5890
5891 \ [UNDEFINED] OR [IF]
5892
5893 \ \ https://forth-standard.org/standard/core/OR
5894 \ \ C OR     x1 x2 -- x3           logical OR
5895 \ CODE OR
5896 \ BIS @PSP+,TOS
5897 \ MOV @IP+,PC
5898 \ ENDCODE
5899
5900 \ [THEN]
5901
5902 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
5903 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
5904 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
5905 \ : LCD_FN_SET        $20 OR LCD_WrF ;
5906 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
5907 \ : LCD_GOTO          $80 OR LCD_WrF ;
5908
5909
5910 \ CODE LCD_RDS                    \ -- status       Read Status
5911 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
5912 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
5913 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
5914 \ COLON                           \ starts a FORTH word
5915 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
5916 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
5917 \ HI2LO                           \ switch from FORTH to assembler
5918 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
5919 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
5920 \     MOV @RSP+,IP                \ restore IP saved by COLON
5921 \     MOV @IP+,PC                 \
5922 \ ENDCODE
5923
5924 \ CODE LCD_RDC                    \ -- char         Read Char
5925 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
5926 \     GOTO BW1
5927 \ ENDCODE
5928
5929
5930 \ ******************************\
5931 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
5932 \ ******************************\
5933 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
5934 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
5935 BIT.B #SW2,&SW2_IN              \ test switch S2
5936 0= IF                           \ case of switch S2 pressed
5937     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
5938     U< IF
5939         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
5940     THEN
5941 ELSE
5942     BIT.B #SW1,&SW1_IN          \ test switch S1 input
5943     0= IF                       \ case of Switch S1 pressed
5944         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
5945         U>= IF                  \
5946            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
5947         THEN                    \
5948     THEN                        \
5949 THEN                            \
5950 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
5951 RET                             \ 5
5952 ENDASM
5953
5954 \ ******************************\
5955 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
5956 \ ******************************\
5957 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
5958 \ ******************************\
5959 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
5960 \                               \       SMclock = 8|16|24 MHz
5961 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
5962 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
5963 \                               \       SR(9)=new Toggle bit memory (ADD on)
5964 \ ******************************\
5965 \ RC5_FirstStartBitHalfCycle:   \
5966 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
5967 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
5968 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
5969 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
5970 \ [THEN]
5971 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
5972     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
5973 [THEN]
5974 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
5975     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
5976 [THEN]
5977 MOV #1778,X                     \ RC5_Period * 1us
5978 MOV #14,W                       \ count of loop
5979 BEGIN                           \
5980 \ ******************************\
5981 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
5982 \ ******************************\                   |
5983 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
5984 \ RC5_Compute_3/4_Period:       \                   |
5985     RRUM    #1,X                \ X=1/2 cycle       |
5986     MOV     X,Y                 \                   ^
5987     RRUM    #1,Y                \ Y=1/4
5988     ADD     X,Y                 \ Y=3/4 cycle
5989     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
5990     U>= UNTIL                   \ 2
5991 \ ******************************\
5992 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
5993 \ ******************************\
5994     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
5995     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
5996     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
5997     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
5998     SUB     #1,W                \ decrement count loop
5999 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
6000 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
6001 0<> WHILE                       \ ----> out of loop ----+
6002     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
6003     BEGIN                       \                       |
6004         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
6005         CMP Y,X                 \ 1                     |   cycle time out of bound ?
6006         U>= IF                  \ 2                 ^   |   yes:
6007         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
6008         GOTO BW1                \                   |   |      quit on truncated RC5 message
6009         THEN                    \                   |   |
6010         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
6011     0<> UNTIL                   \ 2                 |   |
6012 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
6013 \ ******************************\                       |
6014 \ RC5_SampleEndOf:              \ <---------------------+
6015 \ ******************************\
6016 BIC #$30,&RC5_TIM_CTL           \   stop timer
6017 \ ******************************\
6018 \ RC5_ComputeNewRC5word         \
6019 \ ******************************\
6020 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
6021 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
6022 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
6023 \ ******************************\
6024 \ RC5_ComputeC6bit              \
6025 \ ******************************\
6026 BIT     #BIT14,T                \ test /C6 bit in T
6027 0= IF   BIS #BIT6,X             \ set C6 bit in X
6028 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
6029 \ ******************************\
6030 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
6031 \ ******************************\
6032 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
6033 \ ******************************\
6034 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
6035 XOR     @RSP,T                  \ (new XOR old) Toggle bits
6036 BIT     #UF10,T                 \ repeated RC5_command ?
6037 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
6038 XOR #UF10,0(RSP)                \ 5 toggle bit memory
6039 \ ******************************\
6040 \ Display IR_RC5 code           \
6041 \ ******************************\
6042 SUB #8,PSP                      \ TOS -- x x x x TOS
6043 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
6044 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
6045 MOV #$10,&BASEADR               \                                               set hexadecimal base
6046 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
6047 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
6048 LO2HI                           \                                               switch from assembler to FORTH
6049     LCD_CLEAR                   \                                               set LCD cursor at home
6050     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
6051     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
6052     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
6053     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
6054 HI2LO                           \     --                                        switch from FORTH to assembler
6055 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
6056 MOV @PSP+,TOS                   \     -- TOS
6057 RET
6058 ENDASM
6059
6060 \ ******************************\
6061 ASM BACKGROUND                  \
6062 \ ******************************\
6063 BEGIN
6064 \     ...                         \ insert here your background task
6065 \     ...                         \
6066 \     ...                         \
6067     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
6068     BIS &LPM_MODE,SR            \
6069 \ ******************************\
6070 \ here start all interrupts     \
6071 \ ******************************\
6072 \ here return all interrupts    \
6073 \ ******************************\
6074 AGAIN                           \
6075 ENDASM                          \
6076 \ ******************************\
6077
6078 \ ------------------------------\
6079 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
6080 \ ------------------------------\
6081 \     ...                         \ init specific I/O sys as you want
6082 \     ...                         \ before executing default WARM
6083     MOV #WARM,X                 \ ['] WARM 
6084     ADD #4,X                    \ >BODY
6085     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
6086 ENDASM
6087 \ ------------------------------\
6088
6089 \ ------------------------------\
6090 CODE STOP                       \ stops multitasking, must to be used before downloading app
6091 \ ------------------------------\
6092 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
6093     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
6094     MOV X,-2(X)                 \ restore the default background: SLEEP
6095     MOV #WARM,X
6096     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
6097     BIC.B #RC5,&IR_IE           \ clear RC5_Int
6098     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
6099     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
6100     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
6101     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
6102     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
6103 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
6104 ECHO                            \
6105 ." RC5toLCD is removed,"
6106 ."  type START to restart"
6107  WARM                           \ performs reset to reset all interrupt vectors.    
6108 ;
6109 \ ------------------------------\
6110
6111 \ ------------------------------\
6112 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
6113 \ ------------------------------\
6114 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
6115 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
6116 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
6117 \                           --       \ID input divider \ 10 = /4
6118 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
6119 \                                 -  \TBCLR TimerB Clear
6120 \                                  - \TBIE
6121 \                                   -\TBIFG
6122 \ -------------------------------\
6123 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
6124 \                  --                 \CM Capture Mode
6125 \                    --               \CCIS
6126 \                       -             \SCS
6127 \                        --           \CLLD
6128 \                          -          \CAP
6129 \                            ---      \OUTMOD \ 011 = set/reset
6130 \                               -     \CCIE
6131 \                                 -   \CCI
6132 \                                  -  \OUT
6133 \                                   - \COV
6134 \                                    -\CCIFG
6135 \ -------------------------------\
6136 \ LCD_TIM_CCRx                   \
6137 \ -------------------------------\
6138 \ LCD_TIM_EX0                    \ 
6139 \ ------------------------------\
6140 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
6141 \ ------------------------------\
6142 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
6143 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
6144 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
6145     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
6146 [THEN]
6147 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
6148     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
6149 [THEN]
6150     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
6151 \ ------------------------------\
6152 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
6153 \ ------------------------------\
6154 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
6155     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
6156 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
6157 \ ------------------------------\
6158     BIS.B #LCDVo,&LCDVo_DIR     \
6159     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
6160 \ ------------------------------\
6161     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
6162     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
6163 \ ------------------------------\
6164     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
6165     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
6166 \ ******************************\
6167 \ init RC5_Int                  \
6168 \ ******************************\
6169     BIS.B #RC5,&IR_IE           \ enable RC5_Int
6170     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
6171     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
6172 \ ******************************\
6173 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
6174 \ ******************************\
6175 \              %01 0001 0100    \ TAxCTL
6176 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
6177 \                  --           \ ID        divided by 1
6178 \                    --         \ MC        MODE = up to TAxCCRn
6179 \                        -      \ TACLR     clear timer count
6180 \                         -     \ TAIE
6181 \                          -    \ TAIFG
6182 \ ------------------------------\
6183 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
6184 \ ------------------------------\
6185 \                        000    \ TAxEX0
6186 \                        ---    \ TAIDEX    pre divisor
6187 \ ------------------------------\
6188 \          %0000 0000 0000 0101 \ TAxCCR0
6189     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
6190 \ ------------------------------\
6191 \          %0000 0000 0001 0000 \ TAxCCTL0
6192 \                   -           \ CAP capture/compare mode = compare
6193 \                        -      \ CCIEn
6194 \                             - \ CCIFGn
6195     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
6196 \ ------------------------------\
6197     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
6198 \ ------------------------------\
6199 \ define LPM mode for ACCEPT    \
6200 \ ------------------------------\
6201 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
6202 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
6203 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
6204 \ ------------------------------\
6205 \ activate I/O                  \
6206 \ ------------------------------\
6207 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
6208 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
6209 \ ------------------------------\
6210 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
6211 \ ------------------------------\
6212 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
6213 \ CMP #2,Y                        \ Power_ON event
6214 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
6215 CMP #4,Y                        \
6216 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
6217 \ CMP #6,Y                        \
6218 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
6219 \ CMP #$0A,Y                      \
6220 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
6221 \ CMP #$16,Y                      \
6222 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
6223 \ ------------------------------\
6224 COLON                           \
6225 \ ------------------------------\
6226 \ Init LCD 2x20                 \
6227 \ ------------------------------\
6228     #1000 20_US                 \ 1- wait 20 ms
6229     %011 TOP_LCD                \ 2- send DB5=DB4=1
6230     #205 20_US                  \ 3- wait 4,1 ms
6231     %011 TOP_LCD                \ 4- send again DB5=DB4=1
6232     #5 20_US                    \ 5- wait 0,1 ms
6233     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
6234     #2 20_US                    \    wait 40 us = LCD cycle
6235     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
6236     #2 20_US                    \    wait 40 us = LCD cycle
6237     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
6238     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
6239     LCD_CLEAR                   \ 10- "LCD_Clear"
6240     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
6241     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
6242     LCD_CLEAR                   \ 10- "LCD_Clear"
6243     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
6244     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
6245     CR ." I love you"           \ display message on LCD
6246     ['] CR >BODY IS CR          \ CR executes its default value
6247     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
6248     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
6249     PWR_STATE ABORT             \ init DP and continues with ABORT
6250 ;                               \
6251 \ ------------------------------\
6252
6253 \ ------------------------------\
6254 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
6255 \ ------------------------------\
6256 MOV #SLEEP,X                    \ replace default background process SLEEP
6257 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
6258 MOV #WARM,X                     \ replace default WARM
6259 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
6260 MOV X,PC                        \ then execute new WARM
6261 ENDCODE 
6262 \ ------------------------------\
6263
6264 ECHO
6265             ; downloading RC5toLCD.4th is done
6266 RST_HERE    ; this app is protected against <reset>
6267
6268
6269 RST_STATE
6270
6271 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
6272
6273 [UNDEFINED] MARKER [IF]
6274 \  https://forth-standard.org/standard/core/MARKER
6275 \  MARKER
6276 \ ( "<spaces>name" -- )
6277 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
6278 \ with the execution semantics defined below.
6279
6280 \ name Execution: ( -- )
6281 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
6282 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
6283 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
6284 \ not necessarily provided. No other contextual information such as numeric base is affected
6285 \
6286 : MARKER
6287 CREATE
6288 HI2LO
6289 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
6290 SUB #2,Y            \ 1 Y = LFA
6291 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
6292 ADD #4,&DP          \ 3 add 2 cells
6293 LO2HI
6294 DOES>
6295 HI2LO
6296 MOV @RSP+,IP        \ -- PFA
6297 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
6298 MOV @TOS,&INIDP     \       set DP value for RST_STATE
6299 MOV @PSP+,TOS       \ --
6300 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
6301 ENDCODE
6302 [THEN]
6303
6304 MARKER {RC5TOLCD}
6305
6306 [UNDEFINED] @ [IF]
6307 \ https://forth-standard.org/standard/core/Fetch
6308 \ @     c-addr -- char   fetch char from memory
6309 CODE @
6310 MOV @TOS,TOS
6311 MOV @IP+,PC
6312 ENDCODE
6313 [THEN]
6314
6315 [UNDEFINED] CONSTANT [IF]
6316 \ https://forth-standard.org/standard/core/CONSTANT
6317 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
6318 : CONSTANT 
6319 CREATE
6320 HI2LO
6321 MOV TOS,-2(W)           \   PFA = n
6322 MOV @PSP+,TOS
6323 MOV @RSP+,IP
6324 MOV @IP+,PC
6325 ENDCODE
6326 [THEN]
6327
6328 [UNDEFINED] STATE [IF]
6329 \ https://forth-standard.org/standard/core/STATE
6330 \ STATE   -- a-addr       holds compiler state
6331 STATEADR CONSTANT STATE
6332 [THEN]
6333
6334 [UNDEFINED] = [IF]
6335 \ https://forth-standard.org/standard/core/Equal
6336 \ =      x1 x2 -- flag         test x1=x2
6337 CODE =
6338 SUB @PSP+,TOS   \ 2
6339 0<> IF          \ 2
6340     AND #0,TOS  \ 1
6341     MOV @IP+,PC \ 4
6342 THEN
6343 XOR #-1,TOS     \ 1 flag Z = 1
6344 MOV @IP+,PC     \ 4
6345 ENDCODE
6346 [THEN]
6347
6348 [UNDEFINED] IF [IF]
6349 \ https://forth-standard.org/standard/core/IF
6350 \ IF       -- IFadr    initialize conditional forward branch
6351 CODE IF       \ immediate
6352 SUB #2,PSP              \
6353 MOV TOS,0(PSP)          \
6354 MOV &DP,TOS             \ -- HERE
6355 ADD #4,&DP            \           compile one word, reserve one word
6356 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
6357 ADD #2,TOS              \ -- HERE+2=IFadr
6358 MOV @IP+,PC
6359 ENDCODE IMMEDIATE
6360 [THEN]
6361
6362 [UNDEFINED] THEN [IF]
6363 \ https://forth-standard.org/standard/core/THEN
6364 \ THEN     IFadr --                resolve forward branch
6365 CODE THEN               \ immediate
6366 MOV &DP,0(TOS)          \ -- IFadr
6367 MOV @PSP+,TOS           \ --
6368 MOV @IP+,PC
6369 ENDCODE IMMEDIATE
6370 [THEN]
6371
6372 [UNDEFINED] ELSE [IF]
6373 \ https://forth-standard.org/standard/core/ELSE
6374 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
6375 CODE ELSE     \ immediate
6376 ADD #4,&DP              \ make room to compile two words
6377 MOV &DP,W               \ W=HERE+4
6378 MOV #BRAN,-4(W)
6379 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
6380 SUB #2,W                \ HERE+2
6381 MOV W,TOS               \ -- ELSEadr
6382 MOV @IP+,PC
6383 ENDCODE IMMEDIATE
6384 [THEN]
6385
6386 [UNDEFINED] DEFER [IF]
6387 \ https://forth-standard.org/standard/core/DEFER
6388 \ DEFER "<spaces>name"   --
6389 \ Skip leading space delimiters. Parse name delimited by a space.
6390 \ Create a definition for name with the execution semantics defined below.
6391
6392 \ name Execution:   --
6393 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
6394 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
6395 : DEFER
6396 CREATE
6397 HI2LO
6398 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
6399 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
6400 MOV @RSP+,IP
6401 MOV @IP+,PC
6402 ENDCODE
6403 [THEN]
6404
6405 [UNDEFINED] DEFER! [IF]
6406 \ https://forth-standard.org/standard/core/DEFERStore
6407 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
6408 CODE DEFER!             \ xt2 xt1 --
6409 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
6410 MOV @PSP+,TOS           \ --
6411 MOV @IP+,PC
6412 ENDCODE
6413 [THEN]
6414
6415 [UNDEFINED] IS [IF]
6416 \ https://forth-standard.org/standard/core/IS
6417 \ IS <name>        xt --
6418 \ used as is :
6419 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
6420 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
6421 \ or in a definition : ... ['] U. IS DISPLAY ...
6422 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
6423 \
6424 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
6425 : IS
6426 STATE @
6427 IF  POSTPONE ['] POSTPONE DEFER! 
6428 ELSE ' DEFER! 
6429 THEN
6430 ; IMMEDIATE
6431 [THEN]
6432
6433 [UNDEFINED] >BODY [IF]
6434 \ https://forth-standard.org/standard/core/toBODY
6435 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
6436 CODE >BODY
6437 ADD #4,TOS
6438 MOV @IP+,PC
6439 ENDCODE
6440 [THEN]
6441
6442 \ CODE 20uS           \ n --      8MHz version
6443 \ BEGIN               \ 4 + 16 ~ loop
6444 \     MOV #39,rDOCON   \ 39
6445 \     BEGIN           \ 4 ~ loop
6446 \         NOP
6447 \         SUB #1,rDOCON
6448 \     0=  UNTIL
6449 \     SUB #1,TOS      \ 1
6450 \ 0= UNTIL
6451 \ MOV #XDOCON,rDOCON  \ 2
6452 \ MOV @PSP+,TOS
6453 \ MOV @RSP+,IP        \
6454 \ ENDCODE
6455
6456 CODE 20_US                      \ n --      n * 20 us
6457 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
6458     BEGIN
6459         BIT #1,&LCD_TIM_CTL     \ 3
6460     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
6461     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
6462     SUB #1,TOS                  \ 1
6463 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
6464 MOV @PSP+,TOS                   \ 2
6465 MOV @IP+,PC                     \ 4
6466 ENDCODE
6467
6468 CODE TOP_LCD                    \ LCD Sample
6469 \                               \ if write : %xxxx_WWWW --
6470 \                               \ if read  : -- %0000_RRRR
6471     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
6472     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
6473 0= IF                           \ write LCD bits pattern
6474     AND.B #LCD_DB,TOS           \ 
6475     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
6476     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
6477     MOV @PSP+,TOS               \
6478     MOV @IP+,PC
6479 THEN                            \ read LCD bits pattern
6480     SUB #2,PSP
6481     MOV TOS,0(PSP)
6482     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
6483     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
6484     AND.B #LCD_DB,TOS           \
6485     MOV @IP+,PC
6486 ENDCODE
6487
6488 CODE LCD_WRC                    \ char --         Write Char
6489     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
6490 BW1 SUB #2,PSP                  \
6491     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
6492     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
6493     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
6494     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
6495 COLON                           \ high level word starts here 
6496     TOP_LCD 2 20_US             \ write high nibble first
6497     TOP_LCD 2 20_US 
6498 ;
6499
6500 CODE LCD_WRF                    \ func --         Write Fonction
6501     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
6502     GOTO BW1
6503 ENDCODE
6504
6505 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
6506 : LCD_HOME $02 LCD_WRF 100 20_us ;
6507
6508 \ [UNDEFINED] OR [IF]
6509
6510 \ \ https://forth-standard.org/standard/core/OR
6511 \ \ C OR     x1 x2 -- x3           logical OR
6512 \ CODE OR
6513 \ BIS @PSP+,TOS
6514 \ MOV @IP+,PC
6515 \ ENDCODE
6516
6517 \ [THEN]
6518
6519 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
6520 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
6521 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
6522 \ : LCD_FN_SET        $20 OR LCD_WrF ;
6523 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
6524 \ : LCD_GOTO          $80 OR LCD_WrF ;
6525
6526
6527 \ CODE LCD_RDS                    \ -- status       Read Status
6528 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
6529 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
6530 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
6531 \ COLON                           \ starts a FORTH word
6532 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
6533 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
6534 \ HI2LO                           \ switch from FORTH to assembler
6535 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
6536 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
6537 \     MOV @RSP+,IP                \ restore IP saved by COLON
6538 \     MOV @IP+,PC                 \
6539 \ ENDCODE
6540
6541 \ CODE LCD_RDC                    \ -- char         Read Char
6542 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
6543 \     GOTO BW1
6544 \ ENDCODE
6545
6546
6547 \ ******************************\
6548 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
6549 \ ******************************\
6550 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
6551 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
6552 BIT.B #SW2,&SW2_IN              \ test switch S2
6553 0= IF                           \ case of switch S2 pressed
6554     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
6555     U< IF
6556         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
6557     THEN
6558 ELSE
6559     BIT.B #SW1,&SW1_IN          \ test switch S1 input
6560     0= IF                       \ case of Switch S1 pressed
6561         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
6562         U>= IF                  \
6563            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
6564         THEN                    \
6565     THEN                        \
6566 THEN                            \
6567 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
6568 RET                             \ 5
6569 ENDASM
6570
6571 \ ******************************\
6572 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
6573 \ ******************************\
6574 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
6575 \ ******************************\
6576 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
6577 \                               \       SMclock = 8|16|24 MHz
6578 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
6579 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
6580 \                               \       SR(9)=new Toggle bit memory (ADD on)
6581 \ ******************************\
6582 \ RC5_FirstStartBitHalfCycle:   \
6583 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
6584 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
6585 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
6586 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
6587 \ [THEN]
6588 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
6589     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
6590 [THEN]
6591 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
6592     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
6593 [THEN]
6594 MOV #1778,X                     \ RC5_Period * 1us
6595 MOV #14,W                       \ count of loop
6596 BEGIN                           \
6597 \ ******************************\
6598 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
6599 \ ******************************\                   |
6600 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
6601 \ RC5_Compute_3/4_Period:       \                   |
6602     RRUM    #1,X                \ X=1/2 cycle       |
6603     MOV     X,Y                 \                   ^
6604     RRUM    #1,Y                \ Y=1/4
6605     ADD     X,Y                 \ Y=3/4 cycle
6606     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
6607     U>= UNTIL                   \ 2
6608 \ ******************************\
6609 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
6610 \ ******************************\
6611     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
6612     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
6613     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
6614     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
6615     SUB     #1,W                \ decrement count loop
6616 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
6617 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
6618 0<> WHILE                       \ ----> out of loop ----+
6619     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
6620     BEGIN                       \                       |
6621         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
6622         CMP Y,X                 \ 1                     |   cycle time out of bound ?
6623         U>= IF                  \ 2                 ^   |   yes:
6624         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
6625         GOTO BW1                \                   |   |      quit on truncated RC5 message
6626         THEN                    \                   |   |
6627         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
6628     0<> UNTIL                   \ 2                 |   |
6629 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
6630 \ ******************************\                       |
6631 \ RC5_SampleEndOf:              \ <---------------------+
6632 \ ******************************\
6633 BIC #$30,&RC5_TIM_CTL           \   stop timer
6634 \ ******************************\
6635 \ RC5_ComputeNewRC5word         \
6636 \ ******************************\
6637 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
6638 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
6639 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
6640 \ ******************************\
6641 \ RC5_ComputeC6bit              \
6642 \ ******************************\
6643 BIT     #BIT14,T                \ test /C6 bit in T
6644 0= IF   BIS #BIT6,X             \ set C6 bit in X
6645 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
6646 \ ******************************\
6647 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
6648 \ ******************************\
6649 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
6650 \ ******************************\
6651 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
6652 XOR     @RSP,T                  \ (new XOR old) Toggle bits
6653 BIT     #UF10,T                 \ repeated RC5_command ?
6654 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
6655 XOR #UF10,0(RSP)                \ 5 toggle bit memory
6656 \ ******************************\
6657 \ Display IR_RC5 code           \
6658 \ ******************************\
6659 SUB #8,PSP                      \ TOS -- x x x x TOS
6660 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
6661 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
6662 MOV #$10,&BASEADR               \                                               set hexadecimal base
6663 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
6664 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
6665 LO2HI                           \                                               switch from assembler to FORTH
6666     LCD_CLEAR                   \                                               set LCD cursor at home
6667     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
6668     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
6669     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
6670     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
6671 HI2LO                           \     --                                        switch from FORTH to assembler
6672 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
6673 MOV @PSP+,TOS                   \     -- TOS
6674 RET
6675 ENDASM
6676
6677 \ ******************************\
6678 ASM BACKGROUND                  \
6679 \ ******************************\
6680 BEGIN
6681 \     ...                         \ insert here your background task
6682 \     ...                         \
6683 \     ...                         \
6684     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
6685     BIS &LPM_MODE,SR            \
6686 \ ******************************\
6687 \ here start all interrupts     \
6688 \ ******************************\
6689 \ here return all interrupts    \
6690 \ ******************************\
6691 AGAIN                           \
6692 ENDASM                          \
6693 \ ******************************\
6694
6695 \ ------------------------------\
6696 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
6697 \ ------------------------------\
6698 \     ...                         \ init specific I/O sys as you want
6699 \     ...                         \ before executing default WARM
6700     MOV #WARM,X                 \ ['] WARM 
6701     ADD #4,X                    \ >BODY
6702     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
6703 ENDASM
6704 \ ------------------------------\
6705
6706 \ ------------------------------\
6707 CODE STOP                       \ stops multitasking, must to be used before downloading app
6708 \ ------------------------------\
6709 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
6710     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
6711     MOV X,-2(X)                 \ restore the default background: SLEEP
6712     MOV #WARM,X
6713     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
6714     BIC.B #RC5,&IR_IE           \ clear RC5_Int
6715     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
6716     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
6717     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
6718     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
6719     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
6720 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
6721 ECHO                            \
6722 ." RC5toLCD is removed,"
6723 ."  type START to restart"
6724  WARM                           \ performs reset to reset all interrupt vectors.    
6725 ;
6726 \ ------------------------------\
6727
6728 \ ------------------------------\
6729 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
6730 \ ------------------------------\
6731 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
6732 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
6733 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
6734 \                           --       \ID input divider \ 10 = /4
6735 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
6736 \                                 -  \TBCLR TimerB Clear
6737 \                                  - \TBIE
6738 \                                   -\TBIFG
6739 \ -------------------------------\
6740 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
6741 \                  --                 \CM Capture Mode
6742 \                    --               \CCIS
6743 \                       -             \SCS
6744 \                        --           \CLLD
6745 \                          -          \CAP
6746 \                            ---      \OUTMOD \ 011 = set/reset
6747 \                               -     \CCIE
6748 \                                 -   \CCI
6749 \                                  -  \OUT
6750 \                                   - \COV
6751 \                                    -\CCIFG
6752 \ -------------------------------\
6753 \ LCD_TIM_CCRx                   \
6754 \ -------------------------------\
6755 \ LCD_TIM_EX0                    \ 
6756 \ ------------------------------\
6757 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
6758 \ ------------------------------\
6759 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
6760 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
6761 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
6762     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
6763 [THEN]
6764 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
6765     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
6766 [THEN]
6767     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
6768 \ ------------------------------\
6769 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
6770 \ ------------------------------\
6771 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
6772     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
6773 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
6774 \ ------------------------------\
6775     BIS.B #LCDVo,&LCDVo_DIR     \
6776     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
6777 \ ------------------------------\
6778     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
6779     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
6780 \ ------------------------------\
6781     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
6782     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
6783 \ ******************************\
6784 \ init RC5_Int                  \
6785 \ ******************************\
6786     BIS.B #RC5,&IR_IE           \ enable RC5_Int
6787     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
6788     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
6789 \ ******************************\
6790 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
6791 \ ******************************\
6792 \              %01 0001 0100    \ TAxCTL
6793 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
6794 \                  --           \ ID        divided by 1
6795 \                    --         \ MC        MODE = up to TAxCCRn
6796 \                        -      \ TACLR     clear timer count
6797 \                         -     \ TAIE
6798 \                          -    \ TAIFG
6799 \ ------------------------------\
6800 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
6801 \ ------------------------------\
6802 \                        000    \ TAxEX0
6803 \                        ---    \ TAIDEX    pre divisor
6804 \ ------------------------------\
6805 \          %0000 0000 0000 0101 \ TAxCCR0
6806     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
6807 \ ------------------------------\
6808 \          %0000 0000 0001 0000 \ TAxCCTL0
6809 \                   -           \ CAP capture/compare mode = compare
6810 \                        -      \ CCIEn
6811 \                             - \ CCIFGn
6812     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
6813 \ ------------------------------\
6814     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
6815 \ ------------------------------\
6816 \ define LPM mode for ACCEPT    \
6817 \ ------------------------------\
6818 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
6819 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
6820 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
6821 \ ------------------------------\
6822 \ activate I/O                  \
6823 \ ------------------------------\
6824 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
6825 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
6826 \ ------------------------------\
6827 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
6828 \ ------------------------------\
6829 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
6830 \ CMP #2,Y                        \ Power_ON event
6831 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
6832 CMP #4,Y                        \
6833 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
6834 \ CMP #6,Y                        \
6835 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
6836 \ CMP #$0A,Y                      \
6837 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
6838 \ CMP #$16,Y                      \
6839 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
6840 \ ------------------------------\
6841 COLON                           \
6842 \ ------------------------------\
6843 \ Init LCD 2x20                 \
6844 \ ------------------------------\
6845     #1000 20_US                 \ 1- wait 20 ms
6846     %011 TOP_LCD                \ 2- send DB5=DB4=1
6847     #205 20_US                  \ 3- wait 4,1 ms
6848     %011 TOP_LCD                \ 4- send again DB5=DB4=1
6849     #5 20_US                    \ 5- wait 0,1 ms
6850     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
6851     #2 20_US                    \    wait 40 us = LCD cycle
6852     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
6853     #2 20_US                    \    wait 40 us = LCD cycle
6854     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
6855     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
6856     LCD_CLEAR                   \ 10- "LCD_Clear"
6857     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
6858     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
6859     LCD_CLEAR                   \ 10- "LCD_Clear"
6860     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
6861     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
6862     CR ." I love you"           \ display message on LCD
6863     ['] CR >BODY IS CR          \ CR executes its default value
6864     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
6865     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
6866     PWR_STATE ABORT             \ init DP and continues with ABORT
6867 ;                               \
6868 \ ------------------------------\
6869
6870 \ ------------------------------\
6871 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
6872 \ ------------------------------\
6873 MOV #SLEEP,X                    \ replace default background process SLEEP
6874 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
6875 MOV #WARM,X                     \ replace default WARM
6876 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
6877 MOV X,PC                        \ then execute new WARM
6878 ENDCODE 
6879 \ ------------------------------\
6880
6881 ECHO
6882             ; downloading RC5toLCD.4th is done
6883 RST_HERE    ; this app is protected against <reset>
6884
6885
6886 RST_STATE
6887
6888 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
6889
6890 [UNDEFINED] MARKER [IF]
6891 \  https://forth-standard.org/standard/core/MARKER
6892 \  MARKER
6893 \ ( "<spaces>name" -- )
6894 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
6895 \ with the execution semantics defined below.
6896
6897 \ name Execution: ( -- )
6898 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
6899 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
6900 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
6901 \ not necessarily provided. No other contextual information such as numeric base is affected
6902 \
6903 : MARKER
6904 CREATE
6905 HI2LO
6906 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
6907 SUB #2,Y            \ 1 Y = LFA
6908 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
6909 ADD #4,&DP          \ 3 add 2 cells
6910 LO2HI
6911 DOES>
6912 HI2LO
6913 MOV @RSP+,IP        \ -- PFA
6914 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
6915 MOV @TOS,&INIDP     \       set DP value for RST_STATE
6916 MOV @PSP+,TOS       \ --
6917 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
6918 ENDCODE
6919 [THEN]
6920
6921 MARKER {RC5TOLCD}
6922
6923 [UNDEFINED] @ [IF]
6924 \ https://forth-standard.org/standard/core/Fetch
6925 \ @     c-addr -- char   fetch char from memory
6926 CODE @
6927 MOV @TOS,TOS
6928 MOV @IP+,PC
6929 ENDCODE
6930 [THEN]
6931
6932 [UNDEFINED] CONSTANT [IF]
6933 \ https://forth-standard.org/standard/core/CONSTANT
6934 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
6935 : CONSTANT 
6936 CREATE
6937 HI2LO
6938 MOV TOS,-2(W)           \   PFA = n
6939 MOV @PSP+,TOS
6940 MOV @RSP+,IP
6941 MOV @IP+,PC
6942 ENDCODE
6943 [THEN]
6944
6945 [UNDEFINED] STATE [IF]
6946 \ https://forth-standard.org/standard/core/STATE
6947 \ STATE   -- a-addr       holds compiler state
6948 STATEADR CONSTANT STATE
6949 [THEN]
6950
6951 [UNDEFINED] = [IF]
6952 \ https://forth-standard.org/standard/core/Equal
6953 \ =      x1 x2 -- flag         test x1=x2
6954 CODE =
6955 SUB @PSP+,TOS   \ 2
6956 0<> IF          \ 2
6957     AND #0,TOS  \ 1
6958     MOV @IP+,PC \ 4
6959 THEN
6960 XOR #-1,TOS     \ 1 flag Z = 1
6961 MOV @IP+,PC     \ 4
6962 ENDCODE
6963 [THEN]
6964
6965 [UNDEFINED] IF [IF]
6966 \ https://forth-standard.org/standard/core/IF
6967 \ IF       -- IFadr    initialize conditional forward branch
6968 CODE IF       \ immediate
6969 SUB #2,PSP              \
6970 MOV TOS,0(PSP)          \
6971 MOV &DP,TOS             \ -- HERE
6972 ADD #4,&DP            \           compile one word, reserve one word
6973 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
6974 ADD #2,TOS              \ -- HERE+2=IFadr
6975 MOV @IP+,PC
6976 ENDCODE IMMEDIATE
6977 [THEN]
6978
6979 [UNDEFINED] THEN [IF]
6980 \ https://forth-standard.org/standard/core/THEN
6981 \ THEN     IFadr --                resolve forward branch
6982 CODE THEN               \ immediate
6983 MOV &DP,0(TOS)          \ -- IFadr
6984 MOV @PSP+,TOS           \ --
6985 MOV @IP+,PC
6986 ENDCODE IMMEDIATE
6987 [THEN]
6988
6989 [UNDEFINED] ELSE [IF]
6990 \ https://forth-standard.org/standard/core/ELSE
6991 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
6992 CODE ELSE     \ immediate
6993 ADD #4,&DP              \ make room to compile two words
6994 MOV &DP,W               \ W=HERE+4
6995 MOV #BRAN,-4(W)
6996 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
6997 SUB #2,W                \ HERE+2
6998 MOV W,TOS               \ -- ELSEadr
6999 MOV @IP+,PC
7000 ENDCODE IMMEDIATE
7001 [THEN]
7002
7003 [UNDEFINED] DEFER [IF]
7004 \ https://forth-standard.org/standard/core/DEFER
7005 \ DEFER "<spaces>name"   --
7006 \ Skip leading space delimiters. Parse name delimited by a space.
7007 \ Create a definition for name with the execution semantics defined below.
7008
7009 \ name Execution:   --
7010 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
7011 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
7012 : DEFER
7013 CREATE
7014 HI2LO
7015 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
7016 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
7017 MOV @RSP+,IP
7018 MOV @IP+,PC
7019 ENDCODE
7020 [THEN]
7021
7022 [UNDEFINED] DEFER! [IF]
7023 \ https://forth-standard.org/standard/core/DEFERStore
7024 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
7025 CODE DEFER!             \ xt2 xt1 --
7026 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
7027 MOV @PSP+,TOS           \ --
7028 MOV @IP+,PC
7029 ENDCODE
7030 [THEN]
7031
7032 [UNDEFINED] IS [IF]
7033 \ https://forth-standard.org/standard/core/IS
7034 \ IS <name>        xt --
7035 \ used as is :
7036 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
7037 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
7038 \ or in a definition : ... ['] U. IS DISPLAY ...
7039 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
7040 \
7041 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
7042 : IS
7043 STATE @
7044 IF  POSTPONE ['] POSTPONE DEFER! 
7045 ELSE ' DEFER! 
7046 THEN
7047 ; IMMEDIATE
7048 [THEN]
7049
7050 [UNDEFINED] >BODY [IF]
7051 \ https://forth-standard.org/standard/core/toBODY
7052 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
7053 CODE >BODY
7054 ADD #4,TOS
7055 MOV @IP+,PC
7056 ENDCODE
7057 [THEN]
7058
7059 \ CODE 20uS           \ n --      8MHz version
7060 \ BEGIN               \ 4 + 16 ~ loop
7061 \     MOV #39,rDOCON   \ 39
7062 \     BEGIN           \ 4 ~ loop
7063 \         NOP
7064 \         SUB #1,rDOCON
7065 \     0=  UNTIL
7066 \     SUB #1,TOS      \ 1
7067 \ 0= UNTIL
7068 \ MOV #XDOCON,rDOCON  \ 2
7069 \ MOV @PSP+,TOS
7070 \ MOV @RSP+,IP        \
7071 \ ENDCODE
7072
7073 CODE 20_US                      \ n --      n * 20 us
7074 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
7075     BEGIN
7076         BIT #1,&LCD_TIM_CTL     \ 3
7077     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
7078     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
7079     SUB #1,TOS                  \ 1
7080 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
7081 MOV @PSP+,TOS                   \ 2
7082 MOV @IP+,PC                     \ 4
7083 ENDCODE
7084
7085 CODE TOP_LCD                    \ LCD Sample
7086 \                               \ if write : %xxxx_WWWW --
7087 \                               \ if read  : -- %0000_RRRR
7088     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
7089     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
7090 0= IF                           \ write LCD bits pattern
7091     AND.B #LCD_DB,TOS           \ 
7092     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
7093     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
7094     MOV @PSP+,TOS               \
7095     MOV @IP+,PC
7096 THEN                            \ read LCD bits pattern
7097     SUB #2,PSP
7098     MOV TOS,0(PSP)
7099     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
7100     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
7101     AND.B #LCD_DB,TOS           \
7102     MOV @IP+,PC
7103 ENDCODE
7104
7105 CODE LCD_WRC                    \ char --         Write Char
7106     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
7107 BW1 SUB #2,PSP                  \
7108     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
7109     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
7110     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
7111     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
7112 COLON                           \ high level word starts here 
7113     TOP_LCD 2 20_US             \ write high nibble first
7114     TOP_LCD 2 20_US 
7115 ;
7116
7117 CODE LCD_WRF                    \ func --         Write Fonction
7118     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
7119     GOTO BW1
7120 ENDCODE
7121
7122 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
7123 : LCD_HOME $02 LCD_WRF 100 20_us ;
7124
7125 \ [UNDEFINED] OR [IF]
7126
7127 \ \ https://forth-standard.org/standard/core/OR
7128 \ \ C OR     x1 x2 -- x3           logical OR
7129 \ CODE OR
7130 \ BIS @PSP+,TOS
7131 \ MOV @IP+,PC
7132 \ ENDCODE
7133
7134 \ [THEN]
7135
7136 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
7137 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
7138 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
7139 \ : LCD_FN_SET        $20 OR LCD_WrF ;
7140 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
7141 \ : LCD_GOTO          $80 OR LCD_WrF ;
7142
7143
7144 \ CODE LCD_RDS                    \ -- status       Read Status
7145 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
7146 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
7147 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
7148 \ COLON                           \ starts a FORTH word
7149 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
7150 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
7151 \ HI2LO                           \ switch from FORTH to assembler
7152 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
7153 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
7154 \     MOV @RSP+,IP                \ restore IP saved by COLON
7155 \     MOV @IP+,PC                 \
7156 \ ENDCODE
7157
7158 \ CODE LCD_RDC                    \ -- char         Read Char
7159 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
7160 \     GOTO BW1
7161 \ ENDCODE
7162
7163
7164 \ ******************************\
7165 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
7166 \ ******************************\
7167 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
7168 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
7169 BIT.B #SW2,&SW2_IN              \ test switch S2
7170 0= IF                           \ case of switch S2 pressed
7171     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
7172     U< IF
7173         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
7174     THEN
7175 ELSE
7176     BIT.B #SW1,&SW1_IN          \ test switch S1 input
7177     0= IF                       \ case of Switch S1 pressed
7178         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
7179         U>= IF                  \
7180            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
7181         THEN                    \
7182     THEN                        \
7183 THEN                            \
7184 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
7185 RET                             \ 5
7186 ENDASM
7187
7188 \ ******************************\
7189 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
7190 \ ******************************\
7191 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
7192 \ ******************************\
7193 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
7194 \                               \       SMclock = 8|16|24 MHz
7195 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
7196 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
7197 \                               \       SR(9)=new Toggle bit memory (ADD on)
7198 \ ******************************\
7199 \ RC5_FirstStartBitHalfCycle:   \
7200 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
7201 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
7202 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
7203 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
7204 \ [THEN]
7205 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
7206     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
7207 [THEN]
7208 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
7209     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
7210 [THEN]
7211 MOV #1778,X                     \ RC5_Period * 1us
7212 MOV #14,W                       \ count of loop
7213 BEGIN                           \
7214 \ ******************************\
7215 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
7216 \ ******************************\                   |
7217 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
7218 \ RC5_Compute_3/4_Period:       \                   |
7219     RRUM    #1,X                \ X=1/2 cycle       |
7220     MOV     X,Y                 \                   ^
7221     RRUM    #1,Y                \ Y=1/4
7222     ADD     X,Y                 \ Y=3/4 cycle
7223     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
7224     U>= UNTIL                   \ 2
7225 \ ******************************\
7226 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
7227 \ ******************************\
7228     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
7229     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
7230     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
7231     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
7232     SUB     #1,W                \ decrement count loop
7233 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
7234 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
7235 0<> WHILE                       \ ----> out of loop ----+
7236     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
7237     BEGIN                       \                       |
7238         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
7239         CMP Y,X                 \ 1                     |   cycle time out of bound ?
7240         U>= IF                  \ 2                 ^   |   yes:
7241         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
7242         GOTO BW1                \                   |   |      quit on truncated RC5 message
7243         THEN                    \                   |   |
7244         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
7245     0<> UNTIL                   \ 2                 |   |
7246 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
7247 \ ******************************\                       |
7248 \ RC5_SampleEndOf:              \ <---------------------+
7249 \ ******************************\
7250 BIC #$30,&RC5_TIM_CTL           \   stop timer
7251 \ ******************************\
7252 \ RC5_ComputeNewRC5word         \
7253 \ ******************************\
7254 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
7255 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
7256 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
7257 \ ******************************\
7258 \ RC5_ComputeC6bit              \
7259 \ ******************************\
7260 BIT     #BIT14,T                \ test /C6 bit in T
7261 0= IF   BIS #BIT6,X             \ set C6 bit in X
7262 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
7263 \ ******************************\
7264 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
7265 \ ******************************\
7266 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
7267 \ ******************************\
7268 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
7269 XOR     @RSP,T                  \ (new XOR old) Toggle bits
7270 BIT     #UF10,T                 \ repeated RC5_command ?
7271 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
7272 XOR #UF10,0(RSP)                \ 5 toggle bit memory
7273 \ ******************************\
7274 \ Display IR_RC5 code           \
7275 \ ******************************\
7276 SUB #8,PSP                      \ TOS -- x x x x TOS
7277 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
7278 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
7279 MOV #$10,&BASEADR               \                                               set hexadecimal base
7280 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
7281 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
7282 LO2HI                           \                                               switch from assembler to FORTH
7283     LCD_CLEAR                   \                                               set LCD cursor at home
7284     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
7285     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
7286     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
7287     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
7288 HI2LO                           \     --                                        switch from FORTH to assembler
7289 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
7290 MOV @PSP+,TOS                   \     -- TOS
7291 RET
7292 ENDASM
7293
7294 \ ******************************\
7295 ASM BACKGROUND                  \
7296 \ ******************************\
7297 BEGIN
7298 \     ...                         \ insert here your background task
7299 \     ...                         \
7300 \     ...                         \
7301     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
7302     BIS &LPM_MODE,SR            \
7303 \ ******************************\
7304 \ here start all interrupts     \
7305 \ ******************************\
7306 \ here return all interrupts    \
7307 \ ******************************\
7308 AGAIN                           \
7309 ENDASM                          \
7310 \ ******************************\
7311
7312 \ ------------------------------\
7313 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
7314 \ ------------------------------\
7315 \     ...                         \ init specific I/O sys as you want
7316 \     ...                         \ before executing default WARM
7317     MOV #WARM,X                 \ ['] WARM 
7318     ADD #4,X                    \ >BODY
7319     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
7320 ENDASM
7321 \ ------------------------------\
7322
7323 \ ------------------------------\
7324 CODE STOP                       \ stops multitasking, must to be used before downloading app
7325 \ ------------------------------\
7326 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
7327     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
7328     MOV X,-2(X)                 \ restore the default background: SLEEP
7329     MOV #WARM,X
7330     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
7331     BIC.B #RC5,&IR_IE           \ clear RC5_Int
7332     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
7333     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
7334     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
7335     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
7336     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
7337 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
7338 ECHO                            \
7339 ." RC5toLCD is removed,"
7340 ."  type START to restart"
7341  WARM                           \ performs reset to reset all interrupt vectors.    
7342 ;
7343 \ ------------------------------\
7344
7345 \ ------------------------------\
7346 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
7347 \ ------------------------------\
7348 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
7349 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
7350 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
7351 \                           --       \ID input divider \ 10 = /4
7352 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
7353 \                                 -  \TBCLR TimerB Clear
7354 \                                  - \TBIE
7355 \                                   -\TBIFG
7356 \ -------------------------------\
7357 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
7358 \                  --                 \CM Capture Mode
7359 \                    --               \CCIS
7360 \                       -             \SCS
7361 \                        --           \CLLD
7362 \                          -          \CAP
7363 \                            ---      \OUTMOD \ 011 = set/reset
7364 \                               -     \CCIE
7365 \                                 -   \CCI
7366 \                                  -  \OUT
7367 \                                   - \COV
7368 \                                    -\CCIFG
7369 \ -------------------------------\
7370 \ LCD_TIM_CCRx                   \
7371 \ -------------------------------\
7372 \ LCD_TIM_EX0                    \ 
7373 \ ------------------------------\
7374 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
7375 \ ------------------------------\
7376 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
7377 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
7378 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
7379     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
7380 [THEN]
7381 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
7382     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
7383 [THEN]
7384     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
7385 \ ------------------------------\
7386 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
7387 \ ------------------------------\
7388 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
7389     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
7390 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
7391 \ ------------------------------\
7392     BIS.B #LCDVo,&LCDVo_DIR     \
7393     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
7394 \ ------------------------------\
7395     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
7396     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
7397 \ ------------------------------\
7398     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
7399     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
7400 \ ******************************\
7401 \ init RC5_Int                  \
7402 \ ******************************\
7403     BIS.B #RC5,&IR_IE           \ enable RC5_Int
7404     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
7405     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
7406 \ ******************************\
7407 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
7408 \ ******************************\
7409 \              %01 0001 0100    \ TAxCTL
7410 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
7411 \                  --           \ ID        divided by 1
7412 \                    --         \ MC        MODE = up to TAxCCRn
7413 \                        -      \ TACLR     clear timer count
7414 \                         -     \ TAIE
7415 \                          -    \ TAIFG
7416 \ ------------------------------\
7417 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
7418 \ ------------------------------\
7419 \                        000    \ TAxEX0
7420 \                        ---    \ TAIDEX    pre divisor
7421 \ ------------------------------\
7422 \          %0000 0000 0000 0101 \ TAxCCR0
7423     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
7424 \ ------------------------------\
7425 \          %0000 0000 0001 0000 \ TAxCCTL0
7426 \                   -           \ CAP capture/compare mode = compare
7427 \                        -      \ CCIEn
7428 \                             - \ CCIFGn
7429     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
7430 \ ------------------------------\
7431     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
7432 \ ------------------------------\
7433 \ define LPM mode for ACCEPT    \
7434 \ ------------------------------\
7435 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
7436 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
7437 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
7438 \ ------------------------------\
7439 \ activate I/O                  \
7440 \ ------------------------------\
7441 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
7442 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
7443 \ ------------------------------\
7444 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
7445 \ ------------------------------\
7446 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
7447 \ CMP #2,Y                        \ Power_ON event
7448 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
7449 CMP #4,Y                        \
7450 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
7451 \ CMP #6,Y                        \
7452 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
7453 \ CMP #$0A,Y                      \
7454 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
7455 \ CMP #$16,Y                      \
7456 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
7457 \ ------------------------------\
7458 COLON                           \
7459 \ ------------------------------\
7460 \ Init LCD 2x20                 \
7461 \ ------------------------------\
7462     #1000 20_US                 \ 1- wait 20 ms
7463     %011 TOP_LCD                \ 2- send DB5=DB4=1
7464     #205 20_US                  \ 3- wait 4,1 ms
7465     %011 TOP_LCD                \ 4- send again DB5=DB4=1
7466     #5 20_US                    \ 5- wait 0,1 ms
7467     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
7468     #2 20_US                    \    wait 40 us = LCD cycle
7469     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
7470     #2 20_US                    \    wait 40 us = LCD cycle
7471     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
7472     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
7473     LCD_CLEAR                   \ 10- "LCD_Clear"
7474     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
7475     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
7476     LCD_CLEAR                   \ 10- "LCD_Clear"
7477     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
7478     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
7479     CR ." I love you"           \ display message on LCD
7480     ['] CR >BODY IS CR          \ CR executes its default value
7481     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
7482     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
7483     PWR_STATE ABORT             \ init DP and continues with ABORT
7484 ;                               \
7485 \ ------------------------------\
7486
7487 \ ------------------------------\
7488 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
7489 \ ------------------------------\
7490 MOV #SLEEP,X                    \ replace default background process SLEEP
7491 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
7492 MOV #WARM,X                     \ replace default WARM
7493 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
7494 MOV X,PC                        \ then execute new WARM
7495 ENDCODE 
7496 \ ------------------------------\
7497
7498 ECHO
7499             ; downloading RC5toLCD.4th is done
7500 RST_HERE    ; this app is protected against <reset>
7501
7502
7503 RST_STATE
7504
7505 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
7506
7507 [UNDEFINED] MARKER [IF]
7508 \  https://forth-standard.org/standard/core/MARKER
7509 \  MARKER
7510 \ ( "<spaces>name" -- )
7511 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
7512 \ with the execution semantics defined below.
7513
7514 \ name Execution: ( -- )
7515 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
7516 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
7517 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
7518 \ not necessarily provided. No other contextual information such as numeric base is affected
7519 \
7520 : MARKER
7521 CREATE
7522 HI2LO
7523 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
7524 SUB #2,Y            \ 1 Y = LFA
7525 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
7526 ADD #4,&DP          \ 3 add 2 cells
7527 LO2HI
7528 DOES>
7529 HI2LO
7530 MOV @RSP+,IP        \ -- PFA
7531 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
7532 MOV @TOS,&INIDP     \       set DP value for RST_STATE
7533 MOV @PSP+,TOS       \ --
7534 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
7535 ENDCODE
7536 [THEN]
7537
7538 MARKER {RC5TOLCD}
7539
7540 [UNDEFINED] @ [IF]
7541 \ https://forth-standard.org/standard/core/Fetch
7542 \ @     c-addr -- char   fetch char from memory
7543 CODE @
7544 MOV @TOS,TOS
7545 MOV @IP+,PC
7546 ENDCODE
7547 [THEN]
7548
7549 [UNDEFINED] CONSTANT [IF]
7550 \ https://forth-standard.org/standard/core/CONSTANT
7551 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
7552 : CONSTANT 
7553 CREATE
7554 HI2LO
7555 MOV TOS,-2(W)           \   PFA = n
7556 MOV @PSP+,TOS
7557 MOV @RSP+,IP
7558 MOV @IP+,PC
7559 ENDCODE
7560 [THEN]
7561
7562 [UNDEFINED] STATE [IF]
7563 \ https://forth-standard.org/standard/core/STATE
7564 \ STATE   -- a-addr       holds compiler state
7565 STATEADR CONSTANT STATE
7566 [THEN]
7567
7568 [UNDEFINED] = [IF]
7569 \ https://forth-standard.org/standard/core/Equal
7570 \ =      x1 x2 -- flag         test x1=x2
7571 CODE =
7572 SUB @PSP+,TOS   \ 2
7573 0<> IF          \ 2
7574     AND #0,TOS  \ 1
7575     MOV @IP+,PC \ 4
7576 THEN
7577 XOR #-1,TOS     \ 1 flag Z = 1
7578 MOV @IP+,PC     \ 4
7579 ENDCODE
7580 [THEN]
7581
7582 [UNDEFINED] IF [IF]
7583 \ https://forth-standard.org/standard/core/IF
7584 \ IF       -- IFadr    initialize conditional forward branch
7585 CODE IF       \ immediate
7586 SUB #2,PSP              \
7587 MOV TOS,0(PSP)          \
7588 MOV &DP,TOS             \ -- HERE
7589 ADD #4,&DP            \           compile one word, reserve one word
7590 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
7591 ADD #2,TOS              \ -- HERE+2=IFadr
7592 MOV @IP+,PC
7593 ENDCODE IMMEDIATE
7594 [THEN]
7595
7596 [UNDEFINED] THEN [IF]
7597 \ https://forth-standard.org/standard/core/THEN
7598 \ THEN     IFadr --                resolve forward branch
7599 CODE THEN               \ immediate
7600 MOV &DP,0(TOS)          \ -- IFadr
7601 MOV @PSP+,TOS           \ --
7602 MOV @IP+,PC
7603 ENDCODE IMMEDIATE
7604 [THEN]
7605
7606 [UNDEFINED] ELSE [IF]
7607 \ https://forth-standard.org/standard/core/ELSE
7608 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
7609 CODE ELSE     \ immediate
7610 ADD #4,&DP              \ make room to compile two words
7611 MOV &DP,W               \ W=HERE+4
7612 MOV #BRAN,-4(W)
7613 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
7614 SUB #2,W                \ HERE+2
7615 MOV W,TOS               \ -- ELSEadr
7616 MOV @IP+,PC
7617 ENDCODE IMMEDIATE
7618 [THEN]
7619
7620 [UNDEFINED] DEFER [IF]
7621 \ https://forth-standard.org/standard/core/DEFER
7622 \ DEFER "<spaces>name"   --
7623 \ Skip leading space delimiters. Parse name delimited by a space.
7624 \ Create a definition for name with the execution semantics defined below.
7625
7626 \ name Execution:   --
7627 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
7628 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
7629 : DEFER
7630 CREATE
7631 HI2LO
7632 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
7633 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
7634 MOV @RSP+,IP
7635 MOV @IP+,PC
7636 ENDCODE
7637 [THEN]
7638
7639 [UNDEFINED] DEFER! [IF]
7640 \ https://forth-standard.org/standard/core/DEFERStore
7641 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
7642 CODE DEFER!             \ xt2 xt1 --
7643 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
7644 MOV @PSP+,TOS           \ --
7645 MOV @IP+,PC
7646 ENDCODE
7647 [THEN]
7648
7649 [UNDEFINED] IS [IF]
7650 \ https://forth-standard.org/standard/core/IS
7651 \ IS <name>        xt --
7652 \ used as is :
7653 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
7654 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
7655 \ or in a definition : ... ['] U. IS DISPLAY ...
7656 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
7657 \
7658 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
7659 : IS
7660 STATE @
7661 IF  POSTPONE ['] POSTPONE DEFER! 
7662 ELSE ' DEFER! 
7663 THEN
7664 ; IMMEDIATE
7665 [THEN]
7666
7667 [UNDEFINED] >BODY [IF]
7668 \ https://forth-standard.org/standard/core/toBODY
7669 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
7670 CODE >BODY
7671 ADD #4,TOS
7672 MOV @IP+,PC
7673 ENDCODE
7674 [THEN]
7675
7676 \ CODE 20uS           \ n --      8MHz version
7677 \ BEGIN               \ 4 + 16 ~ loop
7678 \     MOV #39,rDOCON   \ 39
7679 \     BEGIN           \ 4 ~ loop
7680 \         NOP
7681 \         SUB #1,rDOCON
7682 \     0=  UNTIL
7683 \     SUB #1,TOS      \ 1
7684 \ 0= UNTIL
7685 \ MOV #XDOCON,rDOCON  \ 2
7686 \ MOV @PSP+,TOS
7687 \ MOV @RSP+,IP        \
7688 \ ENDCODE
7689
7690 CODE 20_US                      \ n --      n * 20 us
7691 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
7692     BEGIN
7693         BIT #1,&LCD_TIM_CTL     \ 3
7694     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
7695     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
7696     SUB #1,TOS                  \ 1
7697 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
7698 MOV @PSP+,TOS                   \ 2
7699 MOV @IP+,PC                     \ 4
7700 ENDCODE
7701
7702 CODE TOP_LCD                    \ LCD Sample
7703 \                               \ if write : %xxxx_WWWW --
7704 \                               \ if read  : -- %0000_RRRR
7705     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
7706     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
7707 0= IF                           \ write LCD bits pattern
7708     AND.B #LCD_DB,TOS           \ 
7709     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
7710     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
7711     MOV @PSP+,TOS               \
7712     MOV @IP+,PC
7713 THEN                            \ read LCD bits pattern
7714     SUB #2,PSP
7715     MOV TOS,0(PSP)
7716     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
7717     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
7718     AND.B #LCD_DB,TOS           \
7719     MOV @IP+,PC
7720 ENDCODE
7721
7722 CODE LCD_WRC                    \ char --         Write Char
7723     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
7724 BW1 SUB #2,PSP                  \
7725     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
7726     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
7727     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
7728     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
7729 COLON                           \ high level word starts here 
7730     TOP_LCD 2 20_US             \ write high nibble first
7731     TOP_LCD 2 20_US 
7732 ;
7733
7734 CODE LCD_WRF                    \ func --         Write Fonction
7735     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
7736     GOTO BW1
7737 ENDCODE
7738
7739 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
7740 : LCD_HOME $02 LCD_WRF 100 20_us ;
7741
7742 \ [UNDEFINED] OR [IF]
7743
7744 \ \ https://forth-standard.org/standard/core/OR
7745 \ \ C OR     x1 x2 -- x3           logical OR
7746 \ CODE OR
7747 \ BIS @PSP+,TOS
7748 \ MOV @IP+,PC
7749 \ ENDCODE
7750
7751 \ [THEN]
7752
7753 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
7754 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
7755 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
7756 \ : LCD_FN_SET        $20 OR LCD_WrF ;
7757 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
7758 \ : LCD_GOTO          $80 OR LCD_WrF ;
7759
7760
7761 \ CODE LCD_RDS                    \ -- status       Read Status
7762 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
7763 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
7764 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
7765 \ COLON                           \ starts a FORTH word
7766 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
7767 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
7768 \ HI2LO                           \ switch from FORTH to assembler
7769 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
7770 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
7771 \     MOV @RSP+,IP                \ restore IP saved by COLON
7772 \     MOV @IP+,PC                 \
7773 \ ENDCODE
7774
7775 \ CODE LCD_RDC                    \ -- char         Read Char
7776 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
7777 \     GOTO BW1
7778 \ ENDCODE
7779
7780
7781 \ ******************************\
7782 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
7783 \ ******************************\
7784 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
7785 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
7786 BIT.B #SW2,&SW2_IN              \ test switch S2
7787 0= IF                           \ case of switch S2 pressed
7788     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
7789     U< IF
7790         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
7791     THEN
7792 ELSE
7793     BIT.B #SW1,&SW1_IN          \ test switch S1 input
7794     0= IF                       \ case of Switch S1 pressed
7795         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
7796         U>= IF                  \
7797            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
7798         THEN                    \
7799     THEN                        \
7800 THEN                            \
7801 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
7802 RET                             \ 5
7803 ENDASM
7804
7805 \ ******************************\
7806 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
7807 \ ******************************\
7808 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
7809 \ ******************************\
7810 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
7811 \                               \       SMclock = 8|16|24 MHz
7812 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
7813 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
7814 \                               \       SR(9)=new Toggle bit memory (ADD on)
7815 \ ******************************\
7816 \ RC5_FirstStartBitHalfCycle:   \
7817 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
7818 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
7819 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
7820 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
7821 \ [THEN]
7822 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
7823     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
7824 [THEN]
7825 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
7826     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
7827 [THEN]
7828 MOV #1778,X                     \ RC5_Period * 1us
7829 MOV #14,W                       \ count of loop
7830 BEGIN                           \
7831 \ ******************************\
7832 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
7833 \ ******************************\                   |
7834 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
7835 \ RC5_Compute_3/4_Period:       \                   |
7836     RRUM    #1,X                \ X=1/2 cycle       |
7837     MOV     X,Y                 \                   ^
7838     RRUM    #1,Y                \ Y=1/4
7839     ADD     X,Y                 \ Y=3/4 cycle
7840     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
7841     U>= UNTIL                   \ 2
7842 \ ******************************\
7843 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
7844 \ ******************************\
7845     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
7846     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
7847     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
7848     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
7849     SUB     #1,W                \ decrement count loop
7850 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
7851 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
7852 0<> WHILE                       \ ----> out of loop ----+
7853     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
7854     BEGIN                       \                       |
7855         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
7856         CMP Y,X                 \ 1                     |   cycle time out of bound ?
7857         U>= IF                  \ 2                 ^   |   yes:
7858         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
7859         GOTO BW1                \                   |   |      quit on truncated RC5 message
7860         THEN                    \                   |   |
7861         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
7862     0<> UNTIL                   \ 2                 |   |
7863 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
7864 \ ******************************\                       |
7865 \ RC5_SampleEndOf:              \ <---------------------+
7866 \ ******************************\
7867 BIC #$30,&RC5_TIM_CTL           \   stop timer
7868 \ ******************************\
7869 \ RC5_ComputeNewRC5word         \
7870 \ ******************************\
7871 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
7872 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
7873 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
7874 \ ******************************\
7875 \ RC5_ComputeC6bit              \
7876 \ ******************************\
7877 BIT     #BIT14,T                \ test /C6 bit in T
7878 0= IF   BIS #BIT6,X             \ set C6 bit in X
7879 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
7880 \ ******************************\
7881 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
7882 \ ******************************\
7883 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
7884 \ ******************************\
7885 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
7886 XOR     @RSP,T                  \ (new XOR old) Toggle bits
7887 BIT     #UF10,T                 \ repeated RC5_command ?
7888 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
7889 XOR #UF10,0(RSP)                \ 5 toggle bit memory
7890 \ ******************************\
7891 \ Display IR_RC5 code           \
7892 \ ******************************\
7893 SUB #8,PSP                      \ TOS -- x x x x TOS
7894 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
7895 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
7896 MOV #$10,&BASEADR               \                                               set hexadecimal base
7897 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
7898 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
7899 LO2HI                           \                                               switch from assembler to FORTH
7900     LCD_CLEAR                   \                                               set LCD cursor at home
7901     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
7902     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
7903     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
7904     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
7905 HI2LO                           \     --                                        switch from FORTH to assembler
7906 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
7907 MOV @PSP+,TOS                   \     -- TOS
7908 RET
7909 ENDASM
7910
7911 \ ******************************\
7912 ASM BACKGROUND                  \
7913 \ ******************************\
7914 BEGIN
7915 \     ...                         \ insert here your background task
7916 \     ...                         \
7917 \     ...                         \
7918     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
7919     BIS &LPM_MODE,SR            \
7920 \ ******************************\
7921 \ here start all interrupts     \
7922 \ ******************************\
7923 \ here return all interrupts    \
7924 \ ******************************\
7925 AGAIN                           \
7926 ENDASM                          \
7927 \ ******************************\
7928
7929 \ ------------------------------\
7930 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
7931 \ ------------------------------\
7932 \     ...                         \ init specific I/O sys as you want
7933 \     ...                         \ before executing default WARM
7934     MOV #WARM,X                 \ ['] WARM 
7935     ADD #4,X                    \ >BODY
7936     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
7937 ENDASM
7938 \ ------------------------------\
7939
7940 \ ------------------------------\
7941 CODE STOP                       \ stops multitasking, must to be used before downloading app
7942 \ ------------------------------\
7943 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
7944     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
7945     MOV X,-2(X)                 \ restore the default background: SLEEP
7946     MOV #WARM,X
7947     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
7948     BIC.B #RC5,&IR_IE           \ clear RC5_Int
7949     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
7950     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
7951     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
7952     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
7953     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
7954 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
7955 ECHO                            \
7956 ." RC5toLCD is removed,"
7957 ."  type START to restart"
7958  WARM                           \ performs reset to reset all interrupt vectors.    
7959 ;
7960 \ ------------------------------\
7961
7962 \ ------------------------------\
7963 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
7964 \ ------------------------------\
7965 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
7966 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
7967 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
7968 \                           --       \ID input divider \ 10 = /4
7969 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
7970 \                                 -  \TBCLR TimerB Clear
7971 \                                  - \TBIE
7972 \                                   -\TBIFG
7973 \ -------------------------------\
7974 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
7975 \                  --                 \CM Capture Mode
7976 \                    --               \CCIS
7977 \                       -             \SCS
7978 \                        --           \CLLD
7979 \                          -          \CAP
7980 \                            ---      \OUTMOD \ 011 = set/reset
7981 \                               -     \CCIE
7982 \                                 -   \CCI
7983 \                                  -  \OUT
7984 \                                   - \COV
7985 \                                    -\CCIFG
7986 \ -------------------------------\
7987 \ LCD_TIM_CCRx                   \
7988 \ -------------------------------\
7989 \ LCD_TIM_EX0                    \ 
7990 \ ------------------------------\
7991 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
7992 \ ------------------------------\
7993 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
7994 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
7995 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
7996     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
7997 [THEN]
7998 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
7999     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
8000 [THEN]
8001     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
8002 \ ------------------------------\
8003 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
8004 \ ------------------------------\
8005 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
8006     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
8007 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
8008 \ ------------------------------\
8009     BIS.B #LCDVo,&LCDVo_DIR     \
8010     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
8011 \ ------------------------------\
8012     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
8013     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
8014 \ ------------------------------\
8015     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
8016     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
8017 \ ******************************\
8018 \ init RC5_Int                  \
8019 \ ******************************\
8020     BIS.B #RC5,&IR_IE           \ enable RC5_Int
8021     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
8022     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
8023 \ ******************************\
8024 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
8025 \ ******************************\
8026 \              %01 0001 0100    \ TAxCTL
8027 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
8028 \                  --           \ ID        divided by 1
8029 \                    --         \ MC        MODE = up to TAxCCRn
8030 \                        -      \ TACLR     clear timer count
8031 \                         -     \ TAIE
8032 \                          -    \ TAIFG
8033 \ ------------------------------\
8034 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
8035 \ ------------------------------\
8036 \                        000    \ TAxEX0
8037 \                        ---    \ TAIDEX    pre divisor
8038 \ ------------------------------\
8039 \          %0000 0000 0000 0101 \ TAxCCR0
8040     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
8041 \ ------------------------------\
8042 \          %0000 0000 0001 0000 \ TAxCCTL0
8043 \                   -           \ CAP capture/compare mode = compare
8044 \                        -      \ CCIEn
8045 \                             - \ CCIFGn
8046     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
8047 \ ------------------------------\
8048     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
8049 \ ------------------------------\
8050 \ define LPM mode for ACCEPT    \
8051 \ ------------------------------\
8052 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
8053 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
8054 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
8055 \ ------------------------------\
8056 \ activate I/O                  \
8057 \ ------------------------------\
8058 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
8059 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
8060 \ ------------------------------\
8061 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
8062 \ ------------------------------\
8063 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
8064 \ CMP #2,Y                        \ Power_ON event
8065 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
8066 CMP #4,Y                        \
8067 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
8068 \ CMP #6,Y                        \
8069 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
8070 \ CMP #$0A,Y                      \
8071 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
8072 \ CMP #$16,Y                      \
8073 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
8074 \ ------------------------------\
8075 COLON                           \
8076 \ ------------------------------\
8077 \ Init LCD 2x20                 \
8078 \ ------------------------------\
8079     #1000 20_US                 \ 1- wait 20 ms
8080     %011 TOP_LCD                \ 2- send DB5=DB4=1
8081     #205 20_US                  \ 3- wait 4,1 ms
8082     %011 TOP_LCD                \ 4- send again DB5=DB4=1
8083     #5 20_US                    \ 5- wait 0,1 ms
8084     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
8085     #2 20_US                    \    wait 40 us = LCD cycle
8086     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
8087     #2 20_US                    \    wait 40 us = LCD cycle
8088     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
8089     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
8090     LCD_CLEAR                   \ 10- "LCD_Clear"
8091     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
8092     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
8093     LCD_CLEAR                   \ 10- "LCD_Clear"
8094     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
8095     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
8096     CR ." I love you"           \ display message on LCD
8097     ['] CR >BODY IS CR          \ CR executes its default value
8098     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
8099     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
8100     PWR_STATE ABORT             \ init DP and continues with ABORT
8101 ;                               \
8102 \ ------------------------------\
8103
8104 \ ------------------------------\
8105 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
8106 \ ------------------------------\
8107 MOV #SLEEP,X                    \ replace default background process SLEEP
8108 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
8109 MOV #WARM,X                     \ replace default WARM
8110 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
8111 MOV X,PC                        \ then execute new WARM
8112 ENDCODE 
8113 \ ------------------------------\
8114
8115 ECHO
8116             ; downloading RC5toLCD.4th is done
8117 RST_HERE    ; this app is protected against <reset>
8118
8119
8120 RST_STATE
8121
8122 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
8123
8124 [UNDEFINED] MARKER [IF]
8125 \  https://forth-standard.org/standard/core/MARKER
8126 \  MARKER
8127 \ ( "<spaces>name" -- )
8128 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
8129 \ with the execution semantics defined below.
8130
8131 \ name Execution: ( -- )
8132 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
8133 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
8134 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
8135 \ not necessarily provided. No other contextual information such as numeric base is affected
8136 \
8137 : MARKER
8138 CREATE
8139 HI2LO
8140 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
8141 SUB #2,Y            \ 1 Y = LFA
8142 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
8143 ADD #4,&DP          \ 3 add 2 cells
8144 LO2HI
8145 DOES>
8146 HI2LO
8147 MOV @RSP+,IP        \ -- PFA
8148 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
8149 MOV @TOS,&INIDP     \       set DP value for RST_STATE
8150 MOV @PSP+,TOS       \ --
8151 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
8152 ENDCODE
8153 [THEN]
8154
8155 MARKER {RC5TOLCD}
8156
8157 [UNDEFINED] @ [IF]
8158 \ https://forth-standard.org/standard/core/Fetch
8159 \ @     c-addr -- char   fetch char from memory
8160 CODE @
8161 MOV @TOS,TOS
8162 MOV @IP+,PC
8163 ENDCODE
8164 [THEN]
8165
8166 [UNDEFINED] CONSTANT [IF]
8167 \ https://forth-standard.org/standard/core/CONSTANT
8168 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
8169 : CONSTANT 
8170 CREATE
8171 HI2LO
8172 MOV TOS,-2(W)           \   PFA = n
8173 MOV @PSP+,TOS
8174 MOV @RSP+,IP
8175 MOV @IP+,PC
8176 ENDCODE
8177 [THEN]
8178
8179 [UNDEFINED] STATE [IF]
8180 \ https://forth-standard.org/standard/core/STATE
8181 \ STATE   -- a-addr       holds compiler state
8182 STATEADR CONSTANT STATE
8183 [THEN]
8184
8185 [UNDEFINED] = [IF]
8186 \ https://forth-standard.org/standard/core/Equal
8187 \ =      x1 x2 -- flag         test x1=x2
8188 CODE =
8189 SUB @PSP+,TOS   \ 2
8190 0<> IF          \ 2
8191     AND #0,TOS  \ 1
8192     MOV @IP+,PC \ 4
8193 THEN
8194 XOR #-1,TOS     \ 1 flag Z = 1
8195 MOV @IP+,PC     \ 4
8196 ENDCODE
8197 [THEN]
8198
8199 [UNDEFINED] IF [IF]
8200 \ https://forth-standard.org/standard/core/IF
8201 \ IF       -- IFadr    initialize conditional forward branch
8202 CODE IF       \ immediate
8203 SUB #2,PSP              \
8204 MOV TOS,0(PSP)          \
8205 MOV &DP,TOS             \ -- HERE
8206 ADD #4,&DP            \           compile one word, reserve one word
8207 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
8208 ADD #2,TOS              \ -- HERE+2=IFadr
8209 MOV @IP+,PC
8210 ENDCODE IMMEDIATE
8211 [THEN]
8212
8213 [UNDEFINED] THEN [IF]
8214 \ https://forth-standard.org/standard/core/THEN
8215 \ THEN     IFadr --                resolve forward branch
8216 CODE THEN               \ immediate
8217 MOV &DP,0(TOS)          \ -- IFadr
8218 MOV @PSP+,TOS           \ --
8219 MOV @IP+,PC
8220 ENDCODE IMMEDIATE
8221 [THEN]
8222
8223 [UNDEFINED] ELSE [IF]
8224 \ https://forth-standard.org/standard/core/ELSE
8225 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
8226 CODE ELSE     \ immediate
8227 ADD #4,&DP              \ make room to compile two words
8228 MOV &DP,W               \ W=HERE+4
8229 MOV #BRAN,-4(W)
8230 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
8231 SUB #2,W                \ HERE+2
8232 MOV W,TOS               \ -- ELSEadr
8233 MOV @IP+,PC
8234 ENDCODE IMMEDIATE
8235 [THEN]
8236
8237 [UNDEFINED] DEFER [IF]
8238 \ https://forth-standard.org/standard/core/DEFER
8239 \ DEFER "<spaces>name"   --
8240 \ Skip leading space delimiters. Parse name delimited by a space.
8241 \ Create a definition for name with the execution semantics defined below.
8242
8243 \ name Execution:   --
8244 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
8245 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
8246 : DEFER
8247 CREATE
8248 HI2LO
8249 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
8250 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
8251 MOV @RSP+,IP
8252 MOV @IP+,PC
8253 ENDCODE
8254 [THEN]
8255
8256 [UNDEFINED] DEFER! [IF]
8257 \ https://forth-standard.org/standard/core/DEFERStore
8258 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
8259 CODE DEFER!             \ xt2 xt1 --
8260 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
8261 MOV @PSP+,TOS           \ --
8262 MOV @IP+,PC
8263 ENDCODE
8264 [THEN]
8265
8266 [UNDEFINED] IS [IF]
8267 \ https://forth-standard.org/standard/core/IS
8268 \ IS <name>        xt --
8269 \ used as is :
8270 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
8271 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
8272 \ or in a definition : ... ['] U. IS DISPLAY ...
8273 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
8274 \
8275 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
8276 : IS
8277 STATE @
8278 IF  POSTPONE ['] POSTPONE DEFER! 
8279 ELSE ' DEFER! 
8280 THEN
8281 ; IMMEDIATE
8282 [THEN]
8283
8284 [UNDEFINED] >BODY [IF]
8285 \ https://forth-standard.org/standard/core/toBODY
8286 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
8287 CODE >BODY
8288 ADD #4,TOS
8289 MOV @IP+,PC
8290 ENDCODE
8291 [THEN]
8292
8293 \ CODE 20uS           \ n --      8MHz version
8294 \ BEGIN               \ 4 + 16 ~ loop
8295 \     MOV #39,rDOCON   \ 39
8296 \     BEGIN           \ 4 ~ loop
8297 \         NOP
8298 \         SUB #1,rDOCON
8299 \     0=  UNTIL
8300 \     SUB #1,TOS      \ 1
8301 \ 0= UNTIL
8302 \ MOV #XDOCON,rDOCON  \ 2
8303 \ MOV @PSP+,TOS
8304 \ MOV @RSP+,IP        \
8305 \ ENDCODE
8306
8307 CODE 20_US                      \ n --      n * 20 us
8308 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
8309     BEGIN
8310         BIT #1,&LCD_TIM_CTL     \ 3
8311     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
8312     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
8313     SUB #1,TOS                  \ 1
8314 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
8315 MOV @PSP+,TOS                   \ 2
8316 MOV @IP+,PC                     \ 4
8317 ENDCODE
8318
8319 CODE TOP_LCD                    \ LCD Sample
8320 \                               \ if write : %xxxx_WWWW --
8321 \                               \ if read  : -- %0000_RRRR
8322     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
8323     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
8324 0= IF                           \ write LCD bits pattern
8325     AND.B #LCD_DB,TOS           \ 
8326     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
8327     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
8328     MOV @PSP+,TOS               \
8329     MOV @IP+,PC
8330 THEN                            \ read LCD bits pattern
8331     SUB #2,PSP
8332     MOV TOS,0(PSP)
8333     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
8334     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
8335     AND.B #LCD_DB,TOS           \
8336     MOV @IP+,PC
8337 ENDCODE
8338
8339 CODE LCD_WRC                    \ char --         Write Char
8340     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
8341 BW1 SUB #2,PSP                  \
8342     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
8343     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
8344     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
8345     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
8346 COLON                           \ high level word starts here 
8347     TOP_LCD 2 20_US             \ write high nibble first
8348     TOP_LCD 2 20_US 
8349 ;
8350
8351 CODE LCD_WRF                    \ func --         Write Fonction
8352     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
8353     GOTO BW1
8354 ENDCODE
8355
8356 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
8357 : LCD_HOME $02 LCD_WRF 100 20_us ;
8358
8359 \ [UNDEFINED] OR [IF]
8360
8361 \ \ https://forth-standard.org/standard/core/OR
8362 \ \ C OR     x1 x2 -- x3           logical OR
8363 \ CODE OR
8364 \ BIS @PSP+,TOS
8365 \ MOV @IP+,PC
8366 \ ENDCODE
8367
8368 \ [THEN]
8369
8370 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
8371 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
8372 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
8373 \ : LCD_FN_SET        $20 OR LCD_WrF ;
8374 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
8375 \ : LCD_GOTO          $80 OR LCD_WrF ;
8376
8377
8378 \ CODE LCD_RDS                    \ -- status       Read Status
8379 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
8380 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
8381 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
8382 \ COLON                           \ starts a FORTH word
8383 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
8384 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
8385 \ HI2LO                           \ switch from FORTH to assembler
8386 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
8387 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
8388 \     MOV @RSP+,IP                \ restore IP saved by COLON
8389 \     MOV @IP+,PC                 \
8390 \ ENDCODE
8391
8392 \ CODE LCD_RDC                    \ -- char         Read Char
8393 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
8394 \     GOTO BW1
8395 \ ENDCODE
8396
8397
8398 \ ******************************\
8399 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
8400 \ ******************************\
8401 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
8402 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
8403 BIT.B #SW2,&SW2_IN              \ test switch S2
8404 0= IF                           \ case of switch S2 pressed
8405     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
8406     U< IF
8407         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
8408     THEN
8409 ELSE
8410     BIT.B #SW1,&SW1_IN          \ test switch S1 input
8411     0= IF                       \ case of Switch S1 pressed
8412         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
8413         U>= IF                  \
8414            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
8415         THEN                    \
8416     THEN                        \
8417 THEN                            \
8418 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
8419 RET                             \ 5
8420 ENDASM
8421
8422 \ ******************************\
8423 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
8424 \ ******************************\
8425 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
8426 \ ******************************\
8427 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
8428 \                               \       SMclock = 8|16|24 MHz
8429 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
8430 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
8431 \                               \       SR(9)=new Toggle bit memory (ADD on)
8432 \ ******************************\
8433 \ RC5_FirstStartBitHalfCycle:   \
8434 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
8435 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
8436 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
8437 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
8438 \ [THEN]
8439 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
8440     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
8441 [THEN]
8442 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
8443     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
8444 [THEN]
8445 MOV #1778,X                     \ RC5_Period * 1us
8446 MOV #14,W                       \ count of loop
8447 BEGIN                           \
8448 \ ******************************\
8449 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
8450 \ ******************************\                   |
8451 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
8452 \ RC5_Compute_3/4_Period:       \                   |
8453     RRUM    #1,X                \ X=1/2 cycle       |
8454     MOV     X,Y                 \                   ^
8455     RRUM    #1,Y                \ Y=1/4
8456     ADD     X,Y                 \ Y=3/4 cycle
8457     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
8458     U>= UNTIL                   \ 2
8459 \ ******************************\
8460 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
8461 \ ******************************\
8462     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
8463     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
8464     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
8465     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
8466     SUB     #1,W                \ decrement count loop
8467 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
8468 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
8469 0<> WHILE                       \ ----> out of loop ----+
8470     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
8471     BEGIN                       \                       |
8472         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
8473         CMP Y,X                 \ 1                     |   cycle time out of bound ?
8474         U>= IF                  \ 2                 ^   |   yes:
8475         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
8476         GOTO BW1                \                   |   |      quit on truncated RC5 message
8477         THEN                    \                   |   |
8478         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
8479     0<> UNTIL                   \ 2                 |   |
8480 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
8481 \ ******************************\                       |
8482 \ RC5_SampleEndOf:              \ <---------------------+
8483 \ ******************************\
8484 BIC #$30,&RC5_TIM_CTL           \   stop timer
8485 \ ******************************\
8486 \ RC5_ComputeNewRC5word         \
8487 \ ******************************\
8488 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
8489 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
8490 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
8491 \ ******************************\
8492 \ RC5_ComputeC6bit              \
8493 \ ******************************\
8494 BIT     #BIT14,T                \ test /C6 bit in T
8495 0= IF   BIS #BIT6,X             \ set C6 bit in X
8496 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
8497 \ ******************************\
8498 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
8499 \ ******************************\
8500 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
8501 \ ******************************\
8502 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
8503 XOR     @RSP,T                  \ (new XOR old) Toggle bits
8504 BIT     #UF10,T                 \ repeated RC5_command ?
8505 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
8506 XOR #UF10,0(RSP)                \ 5 toggle bit memory
8507 \ ******************************\
8508 \ Display IR_RC5 code           \
8509 \ ******************************\
8510 SUB #8,PSP                      \ TOS -- x x x x TOS
8511 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
8512 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
8513 MOV #$10,&BASEADR               \                                               set hexadecimal base
8514 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
8515 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
8516 LO2HI                           \                                               switch from assembler to FORTH
8517     LCD_CLEAR                   \                                               set LCD cursor at home
8518     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
8519     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
8520     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
8521     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
8522 HI2LO                           \     --                                        switch from FORTH to assembler
8523 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
8524 MOV @PSP+,TOS                   \     -- TOS
8525 RET
8526 ENDASM
8527
8528 \ ******************************\
8529 ASM BACKGROUND                  \
8530 \ ******************************\
8531 BEGIN
8532 \     ...                         \ insert here your background task
8533 \     ...                         \
8534 \     ...                         \
8535     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
8536     BIS &LPM_MODE,SR            \
8537 \ ******************************\
8538 \ here start all interrupts     \
8539 \ ******************************\
8540 \ here return all interrupts    \
8541 \ ******************************\
8542 AGAIN                           \
8543 ENDASM                          \
8544 \ ******************************\
8545
8546 \ ------------------------------\
8547 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
8548 \ ------------------------------\
8549 \     ...                         \ init specific I/O sys as you want
8550 \     ...                         \ before executing default WARM
8551     MOV #WARM,X                 \ ['] WARM 
8552     ADD #4,X                    \ >BODY
8553     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
8554 ENDASM
8555 \ ------------------------------\
8556
8557 \ ------------------------------\
8558 CODE STOP                       \ stops multitasking, must to be used before downloading app
8559 \ ------------------------------\
8560 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
8561     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
8562     MOV X,-2(X)                 \ restore the default background: SLEEP
8563     MOV #WARM,X
8564     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
8565     BIC.B #RC5,&IR_IE           \ clear RC5_Int
8566     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
8567     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
8568     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
8569     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
8570     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
8571 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
8572 ECHO                            \
8573 ." RC5toLCD is removed,"
8574 ."  type START to restart"
8575  WARM                           \ performs reset to reset all interrupt vectors.    
8576 ;
8577 \ ------------------------------\
8578
8579 \ ------------------------------\
8580 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
8581 \ ------------------------------\
8582 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
8583 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
8584 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
8585 \                           --       \ID input divider \ 10 = /4
8586 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
8587 \                                 -  \TBCLR TimerB Clear
8588 \                                  - \TBIE
8589 \                                   -\TBIFG
8590 \ -------------------------------\
8591 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
8592 \                  --                 \CM Capture Mode
8593 \                    --               \CCIS
8594 \                       -             \SCS
8595 \                        --           \CLLD
8596 \                          -          \CAP
8597 \                            ---      \OUTMOD \ 011 = set/reset
8598 \                               -     \CCIE
8599 \                                 -   \CCI
8600 \                                  -  \OUT
8601 \                                   - \COV
8602 \                                    -\CCIFG
8603 \ -------------------------------\
8604 \ LCD_TIM_CCRx                   \
8605 \ -------------------------------\
8606 \ LCD_TIM_EX0                    \ 
8607 \ ------------------------------\
8608 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
8609 \ ------------------------------\
8610 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
8611 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
8612 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
8613     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
8614 [THEN]
8615 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
8616     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
8617 [THEN]
8618     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
8619 \ ------------------------------\
8620 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
8621 \ ------------------------------\
8622 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
8623     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
8624 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
8625 \ ------------------------------\
8626     BIS.B #LCDVo,&LCDVo_DIR     \
8627     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
8628 \ ------------------------------\
8629     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
8630     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
8631 \ ------------------------------\
8632     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
8633     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
8634 \ ******************************\
8635 \ init RC5_Int                  \
8636 \ ******************************\
8637     BIS.B #RC5,&IR_IE           \ enable RC5_Int
8638     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
8639     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
8640 \ ******************************\
8641 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
8642 \ ******************************\
8643 \              %01 0001 0100    \ TAxCTL
8644 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
8645 \                  --           \ ID        divided by 1
8646 \                    --         \ MC        MODE = up to TAxCCRn
8647 \                        -      \ TACLR     clear timer count
8648 \                         -     \ TAIE
8649 \                          -    \ TAIFG
8650 \ ------------------------------\
8651 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
8652 \ ------------------------------\
8653 \                        000    \ TAxEX0
8654 \                        ---    \ TAIDEX    pre divisor
8655 \ ------------------------------\
8656 \          %0000 0000 0000 0101 \ TAxCCR0
8657     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
8658 \ ------------------------------\
8659 \          %0000 0000 0001 0000 \ TAxCCTL0
8660 \                   -           \ CAP capture/compare mode = compare
8661 \                        -      \ CCIEn
8662 \                             - \ CCIFGn
8663     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
8664 \ ------------------------------\
8665     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
8666 \ ------------------------------\
8667 \ define LPM mode for ACCEPT    \
8668 \ ------------------------------\
8669 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
8670 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
8671 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
8672 \ ------------------------------\
8673 \ activate I/O                  \
8674 \ ------------------------------\
8675 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
8676 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
8677 \ ------------------------------\
8678 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
8679 \ ------------------------------\
8680 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
8681 \ CMP #2,Y                        \ Power_ON event
8682 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
8683 CMP #4,Y                        \
8684 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
8685 \ CMP #6,Y                        \
8686 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
8687 \ CMP #$0A,Y                      \
8688 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
8689 \ CMP #$16,Y                      \
8690 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
8691 \ ------------------------------\
8692 COLON                           \
8693 \ ------------------------------\
8694 \ Init LCD 2x20                 \
8695 \ ------------------------------\
8696     #1000 20_US                 \ 1- wait 20 ms
8697     %011 TOP_LCD                \ 2- send DB5=DB4=1
8698     #205 20_US                  \ 3- wait 4,1 ms
8699     %011 TOP_LCD                \ 4- send again DB5=DB4=1
8700     #5 20_US                    \ 5- wait 0,1 ms
8701     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
8702     #2 20_US                    \    wait 40 us = LCD cycle
8703     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
8704     #2 20_US                    \    wait 40 us = LCD cycle
8705     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
8706     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
8707     LCD_CLEAR                   \ 10- "LCD_Clear"
8708     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
8709     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
8710     LCD_CLEAR                   \ 10- "LCD_Clear"
8711     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
8712     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
8713     CR ." I love you"           \ display message on LCD
8714     ['] CR >BODY IS CR          \ CR executes its default value
8715     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
8716     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
8717     PWR_STATE ABORT             \ init DP and continues with ABORT
8718 ;                               \
8719 \ ------------------------------\
8720
8721 \ ------------------------------\
8722 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
8723 \ ------------------------------\
8724 MOV #SLEEP,X                    \ replace default background process SLEEP
8725 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
8726 MOV #WARM,X                     \ replace default WARM
8727 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
8728 MOV X,PC                        \ then execute new WARM
8729 ENDCODE 
8730 \ ------------------------------\
8731
8732 ECHO
8733             ; downloading RC5toLCD.4th is done
8734 RST_HERE    ; this app is protected against <reset>
8735
8736
8737 RST_STATE
8738
8739 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
8740
8741 [UNDEFINED] MARKER [IF]
8742 \  https://forth-standard.org/standard/core/MARKER
8743 \  MARKER
8744 \ ( "<spaces>name" -- )
8745 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
8746 \ with the execution semantics defined below.
8747
8748 \ name Execution: ( -- )
8749 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
8750 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
8751 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
8752 \ not necessarily provided. No other contextual information such as numeric base is affected
8753 \
8754 : MARKER
8755 CREATE
8756 HI2LO
8757 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
8758 SUB #2,Y            \ 1 Y = LFA
8759 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
8760 ADD #4,&DP          \ 3 add 2 cells
8761 LO2HI
8762 DOES>
8763 HI2LO
8764 MOV @RSP+,IP        \ -- PFA
8765 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
8766 MOV @TOS,&INIDP     \       set DP value for RST_STATE
8767 MOV @PSP+,TOS       \ --
8768 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
8769 ENDCODE
8770 [THEN]
8771
8772 MARKER {RC5TOLCD}
8773
8774 [UNDEFINED] @ [IF]
8775 \ https://forth-standard.org/standard/core/Fetch
8776 \ @     c-addr -- char   fetch char from memory
8777 CODE @
8778 MOV @TOS,TOS
8779 MOV @IP+,PC
8780 ENDCODE
8781 [THEN]
8782
8783 [UNDEFINED] CONSTANT [IF]
8784 \ https://forth-standard.org/standard/core/CONSTANT
8785 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
8786 : CONSTANT 
8787 CREATE
8788 HI2LO
8789 MOV TOS,-2(W)           \   PFA = n
8790 MOV @PSP+,TOS
8791 MOV @RSP+,IP
8792 MOV @IP+,PC
8793 ENDCODE
8794 [THEN]
8795
8796 [UNDEFINED] STATE [IF]
8797 \ https://forth-standard.org/standard/core/STATE
8798 \ STATE   -- a-addr       holds compiler state
8799 STATEADR CONSTANT STATE
8800 [THEN]
8801
8802 [UNDEFINED] = [IF]
8803 \ https://forth-standard.org/standard/core/Equal
8804 \ =      x1 x2 -- flag         test x1=x2
8805 CODE =
8806 SUB @PSP+,TOS   \ 2
8807 0<> IF          \ 2
8808     AND #0,TOS  \ 1
8809     MOV @IP+,PC \ 4
8810 THEN
8811 XOR #-1,TOS     \ 1 flag Z = 1
8812 MOV @IP+,PC     \ 4
8813 ENDCODE
8814 [THEN]
8815
8816 [UNDEFINED] IF [IF]
8817 \ https://forth-standard.org/standard/core/IF
8818 \ IF       -- IFadr    initialize conditional forward branch
8819 CODE IF       \ immediate
8820 SUB #2,PSP              \
8821 MOV TOS,0(PSP)          \
8822 MOV &DP,TOS             \ -- HERE
8823 ADD #4,&DP            \           compile one word, reserve one word
8824 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
8825 ADD #2,TOS              \ -- HERE+2=IFadr
8826 MOV @IP+,PC
8827 ENDCODE IMMEDIATE
8828 [THEN]
8829
8830 [UNDEFINED] THEN [IF]
8831 \ https://forth-standard.org/standard/core/THEN
8832 \ THEN     IFadr --                resolve forward branch
8833 CODE THEN               \ immediate
8834 MOV &DP,0(TOS)          \ -- IFadr
8835 MOV @PSP+,TOS           \ --
8836 MOV @IP+,PC
8837 ENDCODE IMMEDIATE
8838 [THEN]
8839
8840 [UNDEFINED] ELSE [IF]
8841 \ https://forth-standard.org/standard/core/ELSE
8842 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
8843 CODE ELSE     \ immediate
8844 ADD #4,&DP              \ make room to compile two words
8845 MOV &DP,W               \ W=HERE+4
8846 MOV #BRAN,-4(W)
8847 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
8848 SUB #2,W                \ HERE+2
8849 MOV W,TOS               \ -- ELSEadr
8850 MOV @IP+,PC
8851 ENDCODE IMMEDIATE
8852 [THEN]
8853
8854 [UNDEFINED] DEFER [IF]
8855 \ https://forth-standard.org/standard/core/DEFER
8856 \ DEFER "<spaces>name"   --
8857 \ Skip leading space delimiters. Parse name delimited by a space.
8858 \ Create a definition for name with the execution semantics defined below.
8859
8860 \ name Execution:   --
8861 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
8862 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
8863 : DEFER
8864 CREATE
8865 HI2LO
8866 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
8867 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
8868 MOV @RSP+,IP
8869 MOV @IP+,PC
8870 ENDCODE
8871 [THEN]
8872
8873 [UNDEFINED] DEFER! [IF]
8874 \ https://forth-standard.org/standard/core/DEFERStore
8875 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
8876 CODE DEFER!             \ xt2 xt1 --
8877 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
8878 MOV @PSP+,TOS           \ --
8879 MOV @IP+,PC
8880 ENDCODE
8881 [THEN]
8882
8883 [UNDEFINED] IS [IF]
8884 \ https://forth-standard.org/standard/core/IS
8885 \ IS <name>        xt --
8886 \ used as is :
8887 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
8888 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
8889 \ or in a definition : ... ['] U. IS DISPLAY ...
8890 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
8891 \
8892 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
8893 : IS
8894 STATE @
8895 IF  POSTPONE ['] POSTPONE DEFER! 
8896 ELSE ' DEFER! 
8897 THEN
8898 ; IMMEDIATE
8899 [THEN]
8900
8901 [UNDEFINED] >BODY [IF]
8902 \ https://forth-standard.org/standard/core/toBODY
8903 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
8904 CODE >BODY
8905 ADD #4,TOS
8906 MOV @IP+,PC
8907 ENDCODE
8908 [THEN]
8909
8910 \ CODE 20uS           \ n --      8MHz version
8911 \ BEGIN               \ 4 + 16 ~ loop
8912 \     MOV #39,rDOCON   \ 39
8913 \     BEGIN           \ 4 ~ loop
8914 \         NOP
8915 \         SUB #1,rDOCON
8916 \     0=  UNTIL
8917 \     SUB #1,TOS      \ 1
8918 \ 0= UNTIL
8919 \ MOV #XDOCON,rDOCON  \ 2
8920 \ MOV @PSP+,TOS
8921 \ MOV @RSP+,IP        \
8922 \ ENDCODE
8923
8924 CODE 20_US                      \ n --      n * 20 us
8925 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
8926     BEGIN
8927         BIT #1,&LCD_TIM_CTL     \ 3
8928     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
8929     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
8930     SUB #1,TOS                  \ 1
8931 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
8932 MOV @PSP+,TOS                   \ 2
8933 MOV @IP+,PC                     \ 4
8934 ENDCODE
8935
8936 CODE TOP_LCD                    \ LCD Sample
8937 \                               \ if write : %xxxx_WWWW --
8938 \                               \ if read  : -- %0000_RRRR
8939     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
8940     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
8941 0= IF                           \ write LCD bits pattern
8942     AND.B #LCD_DB,TOS           \ 
8943     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
8944     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
8945     MOV @PSP+,TOS               \
8946     MOV @IP+,PC
8947 THEN                            \ read LCD bits pattern
8948     SUB #2,PSP
8949     MOV TOS,0(PSP)
8950     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
8951     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
8952     AND.B #LCD_DB,TOS           \
8953     MOV @IP+,PC
8954 ENDCODE
8955
8956 CODE LCD_WRC                    \ char --         Write Char
8957     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
8958 BW1 SUB #2,PSP                  \
8959     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
8960     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
8961     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
8962     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
8963 COLON                           \ high level word starts here 
8964     TOP_LCD 2 20_US             \ write high nibble first
8965     TOP_LCD 2 20_US 
8966 ;
8967
8968 CODE LCD_WRF                    \ func --         Write Fonction
8969     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
8970     GOTO BW1
8971 ENDCODE
8972
8973 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
8974 : LCD_HOME $02 LCD_WRF 100 20_us ;
8975
8976 \ [UNDEFINED] OR [IF]
8977
8978 \ \ https://forth-standard.org/standard/core/OR
8979 \ \ C OR     x1 x2 -- x3           logical OR
8980 \ CODE OR
8981 \ BIS @PSP+,TOS
8982 \ MOV @IP+,PC
8983 \ ENDCODE
8984
8985 \ [THEN]
8986
8987 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
8988 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
8989 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
8990 \ : LCD_FN_SET        $20 OR LCD_WrF ;
8991 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
8992 \ : LCD_GOTO          $80 OR LCD_WrF ;
8993
8994
8995 \ CODE LCD_RDS                    \ -- status       Read Status
8996 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
8997 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
8998 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
8999 \ COLON                           \ starts a FORTH word
9000 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
9001 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
9002 \ HI2LO                           \ switch from FORTH to assembler
9003 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
9004 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
9005 \     MOV @RSP+,IP                \ restore IP saved by COLON
9006 \     MOV @IP+,PC                 \
9007 \ ENDCODE
9008
9009 \ CODE LCD_RDC                    \ -- char         Read Char
9010 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
9011 \     GOTO BW1
9012 \ ENDCODE
9013
9014
9015 \ ******************************\
9016 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
9017 \ ******************************\
9018 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
9019 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
9020 BIT.B #SW2,&SW2_IN              \ test switch S2
9021 0= IF                           \ case of switch S2 pressed
9022     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
9023     U< IF
9024         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
9025     THEN
9026 ELSE
9027     BIT.B #SW1,&SW1_IN          \ test switch S1 input
9028     0= IF                       \ case of Switch S1 pressed
9029         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
9030         U>= IF                  \
9031            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
9032         THEN                    \
9033     THEN                        \
9034 THEN                            \
9035 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
9036 RET                             \ 5
9037 ENDASM
9038
9039 \ ******************************\
9040 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
9041 \ ******************************\
9042 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
9043 \ ******************************\
9044 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
9045 \                               \       SMclock = 8|16|24 MHz
9046 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
9047 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
9048 \                               \       SR(9)=new Toggle bit memory (ADD on)
9049 \ ******************************\
9050 \ RC5_FirstStartBitHalfCycle:   \
9051 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
9052 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
9053 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
9054 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
9055 \ [THEN]
9056 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
9057     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
9058 [THEN]
9059 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
9060     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
9061 [THEN]
9062 MOV #1778,X                     \ RC5_Period * 1us
9063 MOV #14,W                       \ count of loop
9064 BEGIN                           \
9065 \ ******************************\
9066 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
9067 \ ******************************\                   |
9068 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
9069 \ RC5_Compute_3/4_Period:       \                   |
9070     RRUM    #1,X                \ X=1/2 cycle       |
9071     MOV     X,Y                 \                   ^
9072     RRUM    #1,Y                \ Y=1/4
9073     ADD     X,Y                 \ Y=3/4 cycle
9074     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
9075     U>= UNTIL                   \ 2
9076 \ ******************************\
9077 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
9078 \ ******************************\
9079     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
9080     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
9081     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
9082     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
9083     SUB     #1,W                \ decrement count loop
9084 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
9085 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
9086 0<> WHILE                       \ ----> out of loop ----+
9087     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
9088     BEGIN                       \                       |
9089         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
9090         CMP Y,X                 \ 1                     |   cycle time out of bound ?
9091         U>= IF                  \ 2                 ^   |   yes:
9092         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
9093         GOTO BW1                \                   |   |      quit on truncated RC5 message
9094         THEN                    \                   |   |
9095         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
9096     0<> UNTIL                   \ 2                 |   |
9097 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
9098 \ ******************************\                       |
9099 \ RC5_SampleEndOf:              \ <---------------------+
9100 \ ******************************\
9101 BIC #$30,&RC5_TIM_CTL           \   stop timer
9102 \ ******************************\
9103 \ RC5_ComputeNewRC5word         \
9104 \ ******************************\
9105 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
9106 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
9107 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
9108 \ ******************************\
9109 \ RC5_ComputeC6bit              \
9110 \ ******************************\
9111 BIT     #BIT14,T                \ test /C6 bit in T
9112 0= IF   BIS #BIT6,X             \ set C6 bit in X
9113 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
9114 \ ******************************\
9115 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
9116 \ ******************************\
9117 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
9118 \ ******************************\
9119 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
9120 XOR     @RSP,T                  \ (new XOR old) Toggle bits
9121 BIT     #UF10,T                 \ repeated RC5_command ?
9122 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
9123 XOR #UF10,0(RSP)                \ 5 toggle bit memory
9124 \ ******************************\
9125 \ Display IR_RC5 code           \
9126 \ ******************************\
9127 SUB #8,PSP                      \ TOS -- x x x x TOS
9128 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
9129 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
9130 MOV #$10,&BASEADR               \                                               set hexadecimal base
9131 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
9132 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
9133 LO2HI                           \                                               switch from assembler to FORTH
9134     LCD_CLEAR                   \                                               set LCD cursor at home
9135     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
9136     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
9137     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
9138     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
9139 HI2LO                           \     --                                        switch from FORTH to assembler
9140 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
9141 MOV @PSP+,TOS                   \     -- TOS
9142 RET
9143 ENDASM
9144
9145 \ ******************************\
9146 ASM BACKGROUND                  \
9147 \ ******************************\
9148 BEGIN
9149 \     ...                         \ insert here your background task
9150 \     ...                         \
9151 \     ...                         \
9152     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
9153     BIS &LPM_MODE,SR            \
9154 \ ******************************\
9155 \ here start all interrupts     \
9156 \ ******************************\
9157 \ here return all interrupts    \
9158 \ ******************************\
9159 AGAIN                           \
9160 ENDASM                          \
9161 \ ******************************\
9162
9163 \ ------------------------------\
9164 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
9165 \ ------------------------------\
9166 \     ...                         \ init specific I/O sys as you want
9167 \     ...                         \ before executing default WARM
9168     MOV #WARM,X                 \ ['] WARM 
9169     ADD #4,X                    \ >BODY
9170     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
9171 ENDASM
9172 \ ------------------------------\
9173
9174 \ ------------------------------\
9175 CODE STOP                       \ stops multitasking, must to be used before downloading app
9176 \ ------------------------------\
9177 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
9178     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
9179     MOV X,-2(X)                 \ restore the default background: SLEEP
9180     MOV #WARM,X
9181     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
9182     BIC.B #RC5,&IR_IE           \ clear RC5_Int
9183     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
9184     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
9185     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
9186     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
9187     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
9188 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
9189 ECHO                            \
9190 ." RC5toLCD is removed,"
9191 ."  type START to restart"
9192  WARM                           \ performs reset to reset all interrupt vectors.    
9193 ;
9194 \ ------------------------------\
9195
9196 \ ------------------------------\
9197 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
9198 \ ------------------------------\
9199 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
9200 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
9201 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
9202 \                           --       \ID input divider \ 10 = /4
9203 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
9204 \                                 -  \TBCLR TimerB Clear
9205 \                                  - \TBIE
9206 \                                   -\TBIFG
9207 \ -------------------------------\
9208 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
9209 \                  --                 \CM Capture Mode
9210 \                    --               \CCIS
9211 \                       -             \SCS
9212 \                        --           \CLLD
9213 \                          -          \CAP
9214 \                            ---      \OUTMOD \ 011 = set/reset
9215 \                               -     \CCIE
9216 \                                 -   \CCI
9217 \                                  -  \OUT
9218 \                                   - \COV
9219 \                                    -\CCIFG
9220 \ -------------------------------\
9221 \ LCD_TIM_CCRx                   \
9222 \ -------------------------------\
9223 \ LCD_TIM_EX0                    \ 
9224 \ ------------------------------\
9225 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
9226 \ ------------------------------\
9227 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
9228 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
9229 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
9230     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
9231 [THEN]
9232 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
9233     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
9234 [THEN]
9235     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
9236 \ ------------------------------\
9237 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
9238 \ ------------------------------\
9239 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
9240     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
9241 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
9242 \ ------------------------------\
9243     BIS.B #LCDVo,&LCDVo_DIR     \
9244     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
9245 \ ------------------------------\
9246     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
9247     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
9248 \ ------------------------------\
9249     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
9250     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
9251 \ ******************************\
9252 \ init RC5_Int                  \
9253 \ ******************************\
9254     BIS.B #RC5,&IR_IE           \ enable RC5_Int
9255     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
9256     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
9257 \ ******************************\
9258 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
9259 \ ******************************\
9260 \              %01 0001 0100    \ TAxCTL
9261 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
9262 \                  --           \ ID        divided by 1
9263 \                    --         \ MC        MODE = up to TAxCCRn
9264 \                        -      \ TACLR     clear timer count
9265 \                         -     \ TAIE
9266 \                          -    \ TAIFG
9267 \ ------------------------------\
9268 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
9269 \ ------------------------------\
9270 \                        000    \ TAxEX0
9271 \                        ---    \ TAIDEX    pre divisor
9272 \ ------------------------------\
9273 \          %0000 0000 0000 0101 \ TAxCCR0
9274     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
9275 \ ------------------------------\
9276 \          %0000 0000 0001 0000 \ TAxCCTL0
9277 \                   -           \ CAP capture/compare mode = compare
9278 \                        -      \ CCIEn
9279 \                             - \ CCIFGn
9280     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
9281 \ ------------------------------\
9282     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
9283 \ ------------------------------\
9284 \ define LPM mode for ACCEPT    \
9285 \ ------------------------------\
9286 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
9287 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
9288 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
9289 \ ------------------------------\
9290 \ activate I/O                  \
9291 \ ------------------------------\
9292 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
9293 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
9294 \ ------------------------------\
9295 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
9296 \ ------------------------------\
9297 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
9298 \ CMP #2,Y                        \ Power_ON event
9299 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
9300 CMP #4,Y                        \
9301 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
9302 \ CMP #6,Y                        \
9303 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
9304 \ CMP #$0A,Y                      \
9305 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
9306 \ CMP #$16,Y                      \
9307 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
9308 \ ------------------------------\
9309 COLON                           \
9310 \ ------------------------------\
9311 \ Init LCD 2x20                 \
9312 \ ------------------------------\
9313     #1000 20_US                 \ 1- wait 20 ms
9314     %011 TOP_LCD                \ 2- send DB5=DB4=1
9315     #205 20_US                  \ 3- wait 4,1 ms
9316     %011 TOP_LCD                \ 4- send again DB5=DB4=1
9317     #5 20_US                    \ 5- wait 0,1 ms
9318     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
9319     #2 20_US                    \    wait 40 us = LCD cycle
9320     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
9321     #2 20_US                    \    wait 40 us = LCD cycle
9322     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
9323     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
9324     LCD_CLEAR                   \ 10- "LCD_Clear"
9325     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
9326     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
9327     LCD_CLEAR                   \ 10- "LCD_Clear"
9328     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
9329     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
9330     CR ." I love you"           \ display message on LCD
9331     ['] CR >BODY IS CR          \ CR executes its default value
9332     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
9333     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
9334     PWR_STATE ABORT             \ init DP and continues with ABORT
9335 ;                               \
9336 \ ------------------------------\
9337
9338 \ ------------------------------\
9339 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
9340 \ ------------------------------\
9341 MOV #SLEEP,X                    \ replace default background process SLEEP
9342 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
9343 MOV #WARM,X                     \ replace default WARM
9344 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
9345 MOV X,PC                        \ then execute new WARM
9346 ENDCODE 
9347 \ ------------------------------\
9348
9349 ECHO
9350             ; downloading RC5toLCD.4th is done
9351 RST_HERE    ; this app is protected against <reset>
9352
9353
9354 RST_STATE
9355
9356 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
9357
9358 [UNDEFINED] MARKER [IF]
9359 \  https://forth-standard.org/standard/core/MARKER
9360 \  MARKER
9361 \ ( "<spaces>name" -- )
9362 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
9363 \ with the execution semantics defined below.
9364
9365 \ name Execution: ( -- )
9366 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
9367 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
9368 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
9369 \ not necessarily provided. No other contextual information such as numeric base is affected
9370 \
9371 : MARKER
9372 CREATE
9373 HI2LO
9374 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
9375 SUB #2,Y            \ 1 Y = LFA
9376 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
9377 ADD #4,&DP          \ 3 add 2 cells
9378 LO2HI
9379 DOES>
9380 HI2LO
9381 MOV @RSP+,IP        \ -- PFA
9382 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
9383 MOV @TOS,&INIDP     \       set DP value for RST_STATE
9384 MOV @PSP+,TOS       \ --
9385 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
9386 ENDCODE
9387 [THEN]
9388
9389 MARKER {RC5TOLCD}
9390
9391 [UNDEFINED] @ [IF]
9392 \ https://forth-standard.org/standard/core/Fetch
9393 \ @     c-addr -- char   fetch char from memory
9394 CODE @
9395 MOV @TOS,TOS
9396 MOV @IP+,PC
9397 ENDCODE
9398 [THEN]
9399
9400 [UNDEFINED] CONSTANT [IF]
9401 \ https://forth-standard.org/standard/core/CONSTANT
9402 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
9403 : CONSTANT 
9404 CREATE
9405 HI2LO
9406 MOV TOS,-2(W)           \   PFA = n
9407 MOV @PSP+,TOS
9408 MOV @RSP+,IP
9409 MOV @IP+,PC
9410 ENDCODE
9411 [THEN]
9412
9413 [UNDEFINED] STATE [IF]
9414 \ https://forth-standard.org/standard/core/STATE
9415 \ STATE   -- a-addr       holds compiler state
9416 STATEADR CONSTANT STATE
9417 [THEN]
9418
9419 [UNDEFINED] = [IF]
9420 \ https://forth-standard.org/standard/core/Equal
9421 \ =      x1 x2 -- flag         test x1=x2
9422 CODE =
9423 SUB @PSP+,TOS   \ 2
9424 0<> IF          \ 2
9425     AND #0,TOS  \ 1
9426     MOV @IP+,PC \ 4
9427 THEN
9428 XOR #-1,TOS     \ 1 flag Z = 1
9429 MOV @IP+,PC     \ 4
9430 ENDCODE
9431 [THEN]
9432
9433 [UNDEFINED] IF [IF]
9434 \ https://forth-standard.org/standard/core/IF
9435 \ IF       -- IFadr    initialize conditional forward branch
9436 CODE IF       \ immediate
9437 SUB #2,PSP              \
9438 MOV TOS,0(PSP)          \
9439 MOV &DP,TOS             \ -- HERE
9440 ADD #4,&DP            \           compile one word, reserve one word
9441 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
9442 ADD #2,TOS              \ -- HERE+2=IFadr
9443 MOV @IP+,PC
9444 ENDCODE IMMEDIATE
9445 [THEN]
9446
9447 [UNDEFINED] THEN [IF]
9448 \ https://forth-standard.org/standard/core/THEN
9449 \ THEN     IFadr --                resolve forward branch
9450 CODE THEN               \ immediate
9451 MOV &DP,0(TOS)          \ -- IFadr
9452 MOV @PSP+,TOS           \ --
9453 MOV @IP+,PC
9454 ENDCODE IMMEDIATE
9455 [THEN]
9456
9457 [UNDEFINED] ELSE [IF]
9458 \ https://forth-standard.org/standard/core/ELSE
9459 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
9460 CODE ELSE     \ immediate
9461 ADD #4,&DP              \ make room to compile two words
9462 MOV &DP,W               \ W=HERE+4
9463 MOV #BRAN,-4(W)
9464 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
9465 SUB #2,W                \ HERE+2
9466 MOV W,TOS               \ -- ELSEadr
9467 MOV @IP+,PC
9468 ENDCODE IMMEDIATE
9469 [THEN]
9470
9471 [UNDEFINED] DEFER [IF]
9472 \ https://forth-standard.org/standard/core/DEFER
9473 \ DEFER "<spaces>name"   --
9474 \ Skip leading space delimiters. Parse name delimited by a space.
9475 \ Create a definition for name with the execution semantics defined below.
9476
9477 \ name Execution:   --
9478 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
9479 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
9480 : DEFER
9481 CREATE
9482 HI2LO
9483 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
9484 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
9485 MOV @RSP+,IP
9486 MOV @IP+,PC
9487 ENDCODE
9488 [THEN]
9489
9490 [UNDEFINED] DEFER! [IF]
9491 \ https://forth-standard.org/standard/core/DEFERStore
9492 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
9493 CODE DEFER!             \ xt2 xt1 --
9494 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
9495 MOV @PSP+,TOS           \ --
9496 MOV @IP+,PC
9497 ENDCODE
9498 [THEN]
9499
9500 [UNDEFINED] IS [IF]
9501 \ https://forth-standard.org/standard/core/IS
9502 \ IS <name>        xt --
9503 \ used as is :
9504 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
9505 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
9506 \ or in a definition : ... ['] U. IS DISPLAY ...
9507 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
9508 \
9509 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
9510 : IS
9511 STATE @
9512 IF  POSTPONE ['] POSTPONE DEFER! 
9513 ELSE ' DEFER! 
9514 THEN
9515 ; IMMEDIATE
9516 [THEN]
9517
9518 [UNDEFINED] >BODY [IF]
9519 \ https://forth-standard.org/standard/core/toBODY
9520 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
9521 CODE >BODY
9522 ADD #4,TOS
9523 MOV @IP+,PC
9524 ENDCODE
9525 [THEN]
9526
9527 \ CODE 20uS           \ n --      8MHz version
9528 \ BEGIN               \ 4 + 16 ~ loop
9529 \     MOV #39,rDOCON   \ 39
9530 \     BEGIN           \ 4 ~ loop
9531 \         NOP
9532 \         SUB #1,rDOCON
9533 \     0=  UNTIL
9534 \     SUB #1,TOS      \ 1
9535 \ 0= UNTIL
9536 \ MOV #XDOCON,rDOCON  \ 2
9537 \ MOV @PSP+,TOS
9538 \ MOV @RSP+,IP        \
9539 \ ENDCODE
9540
9541 CODE 20_US                      \ n --      n * 20 us
9542 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
9543     BEGIN
9544         BIT #1,&LCD_TIM_CTL     \ 3
9545     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
9546     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
9547     SUB #1,TOS                  \ 1
9548 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
9549 MOV @PSP+,TOS                   \ 2
9550 MOV @IP+,PC                     \ 4
9551 ENDCODE
9552
9553 CODE TOP_LCD                    \ LCD Sample
9554 \                               \ if write : %xxxx_WWWW --
9555 \                               \ if read  : -- %0000_RRRR
9556     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
9557     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
9558 0= IF                           \ write LCD bits pattern
9559     AND.B #LCD_DB,TOS           \ 
9560     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
9561     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
9562     MOV @PSP+,TOS               \
9563     MOV @IP+,PC
9564 THEN                            \ read LCD bits pattern
9565     SUB #2,PSP
9566     MOV TOS,0(PSP)
9567     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
9568     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
9569     AND.B #LCD_DB,TOS           \
9570     MOV @IP+,PC
9571 ENDCODE
9572
9573 CODE LCD_WRC                    \ char --         Write Char
9574     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
9575 BW1 SUB #2,PSP                  \
9576     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
9577     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
9578     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
9579     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
9580 COLON                           \ high level word starts here 
9581     TOP_LCD 2 20_US             \ write high nibble first
9582     TOP_LCD 2 20_US 
9583 ;
9584
9585 CODE LCD_WRF                    \ func --         Write Fonction
9586     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
9587     GOTO BW1
9588 ENDCODE
9589
9590 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
9591 : LCD_HOME $02 LCD_WRF 100 20_us ;
9592
9593 \ [UNDEFINED] OR [IF]
9594
9595 \ \ https://forth-standard.org/standard/core/OR
9596 \ \ C OR     x1 x2 -- x3           logical OR
9597 \ CODE OR
9598 \ BIS @PSP+,TOS
9599 \ MOV @IP+,PC
9600 \ ENDCODE
9601
9602 \ [THEN]
9603
9604 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
9605 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
9606 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
9607 \ : LCD_FN_SET        $20 OR LCD_WrF ;
9608 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
9609 \ : LCD_GOTO          $80 OR LCD_WrF ;
9610
9611
9612 \ CODE LCD_RDS                    \ -- status       Read Status
9613 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
9614 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
9615 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
9616 \ COLON                           \ starts a FORTH word
9617 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
9618 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
9619 \ HI2LO                           \ switch from FORTH to assembler
9620 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
9621 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
9622 \     MOV @RSP+,IP                \ restore IP saved by COLON
9623 \     MOV @IP+,PC                 \
9624 \ ENDCODE
9625
9626 \ CODE LCD_RDC                    \ -- char         Read Char
9627 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
9628 \     GOTO BW1
9629 \ ENDCODE
9630
9631
9632 \ ******************************\
9633 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
9634 \ ******************************\
9635 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
9636 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
9637 BIT.B #SW2,&SW2_IN              \ test switch S2
9638 0= IF                           \ case of switch S2 pressed
9639     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
9640     U< IF
9641         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
9642     THEN
9643 ELSE
9644     BIT.B #SW1,&SW1_IN          \ test switch S1 input
9645     0= IF                       \ case of Switch S1 pressed
9646         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
9647         U>= IF                  \
9648            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
9649         THEN                    \
9650     THEN                        \
9651 THEN                            \
9652 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
9653 RET                             \ 5
9654 ENDASM
9655
9656 \ ******************************\
9657 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
9658 \ ******************************\
9659 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
9660 \ ******************************\
9661 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
9662 \                               \       SMclock = 8|16|24 MHz
9663 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
9664 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
9665 \                               \       SR(9)=new Toggle bit memory (ADD on)
9666 \ ******************************\
9667 \ RC5_FirstStartBitHalfCycle:   \
9668 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
9669 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
9670 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
9671 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
9672 \ [THEN]
9673 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
9674     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
9675 [THEN]
9676 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
9677     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
9678 [THEN]
9679 MOV #1778,X                     \ RC5_Period * 1us
9680 MOV #14,W                       \ count of loop
9681 BEGIN                           \
9682 \ ******************************\
9683 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
9684 \ ******************************\                   |
9685 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
9686 \ RC5_Compute_3/4_Period:       \                   |
9687     RRUM    #1,X                \ X=1/2 cycle       |
9688     MOV     X,Y                 \                   ^
9689     RRUM    #1,Y                \ Y=1/4
9690     ADD     X,Y                 \ Y=3/4 cycle
9691     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
9692     U>= UNTIL                   \ 2
9693 \ ******************************\
9694 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
9695 \ ******************************\
9696     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
9697     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
9698     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
9699     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
9700     SUB     #1,W                \ decrement count loop
9701 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
9702 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
9703 0<> WHILE                       \ ----> out of loop ----+
9704     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
9705     BEGIN                       \                       |
9706         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
9707         CMP Y,X                 \ 1                     |   cycle time out of bound ?
9708         U>= IF                  \ 2                 ^   |   yes:
9709         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
9710         GOTO BW1                \                   |   |      quit on truncated RC5 message
9711         THEN                    \                   |   |
9712         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
9713     0<> UNTIL                   \ 2                 |   |
9714 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
9715 \ ******************************\                       |
9716 \ RC5_SampleEndOf:              \ <---------------------+
9717 \ ******************************\
9718 BIC #$30,&RC5_TIM_CTL           \   stop timer
9719 \ ******************************\
9720 \ RC5_ComputeNewRC5word         \
9721 \ ******************************\
9722 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
9723 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
9724 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
9725 \ ******************************\
9726 \ RC5_ComputeC6bit              \
9727 \ ******************************\
9728 BIT     #BIT14,T                \ test /C6 bit in T
9729 0= IF   BIS #BIT6,X             \ set C6 bit in X
9730 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
9731 \ ******************************\
9732 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
9733 \ ******************************\
9734 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
9735 \ ******************************\
9736 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
9737 XOR     @RSP,T                  \ (new XOR old) Toggle bits
9738 BIT     #UF10,T                 \ repeated RC5_command ?
9739 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
9740 XOR #UF10,0(RSP)                \ 5 toggle bit memory
9741 \ ******************************\
9742 \ Display IR_RC5 code           \
9743 \ ******************************\
9744 SUB #8,PSP                      \ TOS -- x x x x TOS
9745 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
9746 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
9747 MOV #$10,&BASEADR               \                                               set hexadecimal base
9748 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
9749 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
9750 LO2HI                           \                                               switch from assembler to FORTH
9751     LCD_CLEAR                   \                                               set LCD cursor at home
9752     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
9753     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
9754     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
9755     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
9756 HI2LO                           \     --                                        switch from FORTH to assembler
9757 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
9758 MOV @PSP+,TOS                   \     -- TOS
9759 RET
9760 ENDASM
9761
9762 \ ******************************\
9763 ASM BACKGROUND                  \
9764 \ ******************************\
9765 BEGIN
9766 \     ...                         \ insert here your background task
9767 \     ...                         \
9768 \     ...                         \
9769     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
9770     BIS &LPM_MODE,SR            \
9771 \ ******************************\
9772 \ here start all interrupts     \
9773 \ ******************************\
9774 \ here return all interrupts    \
9775 \ ******************************\
9776 AGAIN                           \
9777 ENDASM                          \
9778 \ ******************************\
9779
9780 \ ------------------------------\
9781 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
9782 \ ------------------------------\
9783 \     ...                         \ init specific I/O sys as you want
9784 \     ...                         \ before executing default WARM
9785     MOV #WARM,X                 \ ['] WARM 
9786     ADD #4,X                    \ >BODY
9787     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
9788 ENDASM
9789 \ ------------------------------\
9790
9791 \ ------------------------------\
9792 CODE STOP                       \ stops multitasking, must to be used before downloading app
9793 \ ------------------------------\
9794 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
9795     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
9796     MOV X,-2(X)                 \ restore the default background: SLEEP
9797     MOV #WARM,X
9798     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
9799     BIC.B #RC5,&IR_IE           \ clear RC5_Int
9800     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
9801     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
9802     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
9803     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
9804     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
9805 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
9806 ECHO                            \
9807 ." RC5toLCD is removed,"
9808 ."  type START to restart"
9809  WARM                           \ performs reset to reset all interrupt vectors.    
9810 ;
9811 \ ------------------------------\
9812
9813 \ ------------------------------\
9814 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
9815 \ ------------------------------\
9816 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
9817 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
9818 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
9819 \                           --       \ID input divider \ 10 = /4
9820 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
9821 \                                 -  \TBCLR TimerB Clear
9822 \                                  - \TBIE
9823 \                                   -\TBIFG
9824 \ -------------------------------\
9825 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
9826 \                  --                 \CM Capture Mode
9827 \                    --               \CCIS
9828 \                       -             \SCS
9829 \                        --           \CLLD
9830 \                          -          \CAP
9831 \                            ---      \OUTMOD \ 011 = set/reset
9832 \                               -     \CCIE
9833 \                                 -   \CCI
9834 \                                  -  \OUT
9835 \                                   - \COV
9836 \                                    -\CCIFG
9837 \ -------------------------------\
9838 \ LCD_TIM_CCRx                   \
9839 \ -------------------------------\
9840 \ LCD_TIM_EX0                    \ 
9841 \ ------------------------------\
9842 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
9843 \ ------------------------------\
9844 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
9845 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
9846 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
9847     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
9848 [THEN]
9849 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
9850     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
9851 [THEN]
9852     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
9853 \ ------------------------------\
9854 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
9855 \ ------------------------------\
9856 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
9857     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
9858 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
9859 \ ------------------------------\
9860     BIS.B #LCDVo,&LCDVo_DIR     \
9861     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
9862 \ ------------------------------\
9863     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
9864     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
9865 \ ------------------------------\
9866     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
9867     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
9868 \ ******************************\
9869 \ init RC5_Int                  \
9870 \ ******************************\
9871     BIS.B #RC5,&IR_IE           \ enable RC5_Int
9872     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
9873     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
9874 \ ******************************\
9875 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
9876 \ ******************************\
9877 \              %01 0001 0100    \ TAxCTL
9878 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
9879 \                  --           \ ID        divided by 1
9880 \                    --         \ MC        MODE = up to TAxCCRn
9881 \                        -      \ TACLR     clear timer count
9882 \                         -     \ TAIE
9883 \                          -    \ TAIFG
9884 \ ------------------------------\
9885 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
9886 \ ------------------------------\
9887 \                        000    \ TAxEX0
9888 \                        ---    \ TAIDEX    pre divisor
9889 \ ------------------------------\
9890 \          %0000 0000 0000 0101 \ TAxCCR0
9891     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
9892 \ ------------------------------\
9893 \          %0000 0000 0001 0000 \ TAxCCTL0
9894 \                   -           \ CAP capture/compare mode = compare
9895 \                        -      \ CCIEn
9896 \                             - \ CCIFGn
9897     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
9898 \ ------------------------------\
9899     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
9900 \ ------------------------------\
9901 \ define LPM mode for ACCEPT    \
9902 \ ------------------------------\
9903 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
9904 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
9905 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
9906 \ ------------------------------\
9907 \ activate I/O                  \
9908 \ ------------------------------\
9909 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
9910 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
9911 \ ------------------------------\
9912 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
9913 \ ------------------------------\
9914 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
9915 \ CMP #2,Y                        \ Power_ON event
9916 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
9917 CMP #4,Y                        \
9918 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
9919 \ CMP #6,Y                        \
9920 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
9921 \ CMP #$0A,Y                      \
9922 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
9923 \ CMP #$16,Y                      \
9924 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
9925 \ ------------------------------\
9926 COLON                           \
9927 \ ------------------------------\
9928 \ Init LCD 2x20                 \
9929 \ ------------------------------\
9930     #1000 20_US                 \ 1- wait 20 ms
9931     %011 TOP_LCD                \ 2- send DB5=DB4=1
9932     #205 20_US                  \ 3- wait 4,1 ms
9933     %011 TOP_LCD                \ 4- send again DB5=DB4=1
9934     #5 20_US                    \ 5- wait 0,1 ms
9935     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
9936     #2 20_US                    \    wait 40 us = LCD cycle
9937     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
9938     #2 20_US                    \    wait 40 us = LCD cycle
9939     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
9940     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
9941     LCD_CLEAR                   \ 10- "LCD_Clear"
9942     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
9943     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
9944     LCD_CLEAR                   \ 10- "LCD_Clear"
9945     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
9946     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
9947     CR ." I love you"           \ display message on LCD
9948     ['] CR >BODY IS CR          \ CR executes its default value
9949     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
9950     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
9951     PWR_STATE ABORT             \ init DP and continues with ABORT
9952 ;                               \
9953 \ ------------------------------\
9954
9955 \ ------------------------------\
9956 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
9957 \ ------------------------------\
9958 MOV #SLEEP,X                    \ replace default background process SLEEP
9959 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
9960 MOV #WARM,X                     \ replace default WARM
9961 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
9962 MOV X,PC                        \ then execute new WARM
9963 ENDCODE 
9964 \ ------------------------------\
9965
9966 ECHO
9967             ; downloading RC5toLCD.4th is done
9968 RST_HERE    ; this app is protected against <reset>
9969
9970
9971 RST_STATE
9972
9973 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
9974
9975 [UNDEFINED] MARKER [IF]
9976 \  https://forth-standard.org/standard/core/MARKER
9977 \  MARKER
9978 \ ( "<spaces>name" -- )
9979 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
9980 \ with the execution semantics defined below.
9981
9982 \ name Execution: ( -- )
9983 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
9984 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
9985 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
9986 \ not necessarily provided. No other contextual information such as numeric base is affected
9987 \
9988 : MARKER
9989 CREATE
9990 HI2LO
9991 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
9992 SUB #2,Y            \ 1 Y = LFA
9993 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
9994 ADD #4,&DP          \ 3 add 2 cells
9995 LO2HI
9996 DOES>
9997 HI2LO
9998 MOV @RSP+,IP        \ -- PFA
9999 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
10000 MOV @TOS,&INIDP     \       set DP value for RST_STATE
10001 MOV @PSP+,TOS       \ --
10002 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
10003 ENDCODE
10004 [THEN]
10005
10006 MARKER {RC5TOLCD}
10007
10008 [UNDEFINED] @ [IF]
10009 \ https://forth-standard.org/standard/core/Fetch
10010 \ @     c-addr -- char   fetch char from memory
10011 CODE @
10012 MOV @TOS,TOS
10013 MOV @IP+,PC
10014 ENDCODE
10015 [THEN]
10016
10017 [UNDEFINED] CONSTANT [IF]
10018 \ https://forth-standard.org/standard/core/CONSTANT
10019 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
10020 : CONSTANT 
10021 CREATE
10022 HI2LO
10023 MOV TOS,-2(W)           \   PFA = n
10024 MOV @PSP+,TOS
10025 MOV @RSP+,IP
10026 MOV @IP+,PC
10027 ENDCODE
10028 [THEN]
10029
10030 [UNDEFINED] STATE [IF]
10031 \ https://forth-standard.org/standard/core/STATE
10032 \ STATE   -- a-addr       holds compiler state
10033 STATEADR CONSTANT STATE
10034 [THEN]
10035
10036 [UNDEFINED] = [IF]
10037 \ https://forth-standard.org/standard/core/Equal
10038 \ =      x1 x2 -- flag         test x1=x2
10039 CODE =
10040 SUB @PSP+,TOS   \ 2
10041 0<> IF          \ 2
10042     AND #0,TOS  \ 1
10043     MOV @IP+,PC \ 4
10044 THEN
10045 XOR #-1,TOS     \ 1 flag Z = 1
10046 MOV @IP+,PC     \ 4
10047 ENDCODE
10048 [THEN]
10049
10050 [UNDEFINED] IF [IF]
10051 \ https://forth-standard.org/standard/core/IF
10052 \ IF       -- IFadr    initialize conditional forward branch
10053 CODE IF       \ immediate
10054 SUB #2,PSP              \
10055 MOV TOS,0(PSP)          \
10056 MOV &DP,TOS             \ -- HERE
10057 ADD #4,&DP            \           compile one word, reserve one word
10058 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
10059 ADD #2,TOS              \ -- HERE+2=IFadr
10060 MOV @IP+,PC
10061 ENDCODE IMMEDIATE
10062 [THEN]
10063
10064 [UNDEFINED] THEN [IF]
10065 \ https://forth-standard.org/standard/core/THEN
10066 \ THEN     IFadr --                resolve forward branch
10067 CODE THEN               \ immediate
10068 MOV &DP,0(TOS)          \ -- IFadr
10069 MOV @PSP+,TOS           \ --
10070 MOV @IP+,PC
10071 ENDCODE IMMEDIATE
10072 [THEN]
10073
10074 [UNDEFINED] ELSE [IF]
10075 \ https://forth-standard.org/standard/core/ELSE
10076 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
10077 CODE ELSE     \ immediate
10078 ADD #4,&DP              \ make room to compile two words
10079 MOV &DP,W               \ W=HERE+4
10080 MOV #BRAN,-4(W)
10081 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
10082 SUB #2,W                \ HERE+2
10083 MOV W,TOS               \ -- ELSEadr
10084 MOV @IP+,PC
10085 ENDCODE IMMEDIATE
10086 [THEN]
10087
10088 [UNDEFINED] DEFER [IF]
10089 \ https://forth-standard.org/standard/core/DEFER
10090 \ DEFER "<spaces>name"   --
10091 \ Skip leading space delimiters. Parse name delimited by a space.
10092 \ Create a definition for name with the execution semantics defined below.
10093
10094 \ name Execution:   --
10095 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
10096 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
10097 : DEFER
10098 CREATE
10099 HI2LO
10100 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
10101 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
10102 MOV @RSP+,IP
10103 MOV @IP+,PC
10104 ENDCODE
10105 [THEN]
10106
10107 [UNDEFINED] DEFER! [IF]
10108 \ https://forth-standard.org/standard/core/DEFERStore
10109 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
10110 CODE DEFER!             \ xt2 xt1 --
10111 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
10112 MOV @PSP+,TOS           \ --
10113 MOV @IP+,PC
10114 ENDCODE
10115 [THEN]
10116
10117 [UNDEFINED] IS [IF]
10118 \ https://forth-standard.org/standard/core/IS
10119 \ IS <name>        xt --
10120 \ used as is :
10121 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
10122 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
10123 \ or in a definition : ... ['] U. IS DISPLAY ...
10124 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
10125 \
10126 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
10127 : IS
10128 STATE @
10129 IF  POSTPONE ['] POSTPONE DEFER! 
10130 ELSE ' DEFER! 
10131 THEN
10132 ; IMMEDIATE
10133 [THEN]
10134
10135 [UNDEFINED] >BODY [IF]
10136 \ https://forth-standard.org/standard/core/toBODY
10137 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
10138 CODE >BODY
10139 ADD #4,TOS
10140 MOV @IP+,PC
10141 ENDCODE
10142 [THEN]
10143
10144 \ CODE 20uS           \ n --      8MHz version
10145 \ BEGIN               \ 4 + 16 ~ loop
10146 \     MOV #39,rDOCON   \ 39
10147 \     BEGIN           \ 4 ~ loop
10148 \         NOP
10149 \         SUB #1,rDOCON
10150 \     0=  UNTIL
10151 \     SUB #1,TOS      \ 1
10152 \ 0= UNTIL
10153 \ MOV #XDOCON,rDOCON  \ 2
10154 \ MOV @PSP+,TOS
10155 \ MOV @RSP+,IP        \
10156 \ ENDCODE
10157
10158 CODE 20_US                      \ n --      n * 20 us
10159 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
10160     BEGIN
10161         BIT #1,&LCD_TIM_CTL     \ 3
10162     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
10163     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
10164     SUB #1,TOS                  \ 1
10165 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
10166 MOV @PSP+,TOS                   \ 2
10167 MOV @IP+,PC                     \ 4
10168 ENDCODE
10169
10170 CODE TOP_LCD                    \ LCD Sample
10171 \                               \ if write : %xxxx_WWWW --
10172 \                               \ if read  : -- %0000_RRRR
10173     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
10174     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
10175 0= IF                           \ write LCD bits pattern
10176     AND.B #LCD_DB,TOS           \ 
10177     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
10178     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
10179     MOV @PSP+,TOS               \
10180     MOV @IP+,PC
10181 THEN                            \ read LCD bits pattern
10182     SUB #2,PSP
10183     MOV TOS,0(PSP)
10184     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
10185     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
10186     AND.B #LCD_DB,TOS           \
10187     MOV @IP+,PC
10188 ENDCODE
10189
10190 CODE LCD_WRC                    \ char --         Write Char
10191     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
10192 BW1 SUB #2,PSP                  \
10193     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
10194     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
10195     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
10196     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
10197 COLON                           \ high level word starts here 
10198     TOP_LCD 2 20_US             \ write high nibble first
10199     TOP_LCD 2 20_US 
10200 ;
10201
10202 CODE LCD_WRF                    \ func --         Write Fonction
10203     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
10204     GOTO BW1
10205 ENDCODE
10206
10207 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
10208 : LCD_HOME $02 LCD_WRF 100 20_us ;
10209
10210 \ [UNDEFINED] OR [IF]
10211
10212 \ \ https://forth-standard.org/standard/core/OR
10213 \ \ C OR     x1 x2 -- x3           logical OR
10214 \ CODE OR
10215 \ BIS @PSP+,TOS
10216 \ MOV @IP+,PC
10217 \ ENDCODE
10218
10219 \ [THEN]
10220
10221 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
10222 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
10223 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
10224 \ : LCD_FN_SET        $20 OR LCD_WrF ;
10225 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
10226 \ : LCD_GOTO          $80 OR LCD_WrF ;
10227
10228
10229 \ CODE LCD_RDS                    \ -- status       Read Status
10230 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
10231 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
10232 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
10233 \ COLON                           \ starts a FORTH word
10234 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
10235 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
10236 \ HI2LO                           \ switch from FORTH to assembler
10237 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
10238 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
10239 \     MOV @RSP+,IP                \ restore IP saved by COLON
10240 \     MOV @IP+,PC                 \
10241 \ ENDCODE
10242
10243 \ CODE LCD_RDC                    \ -- char         Read Char
10244 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
10245 \     GOTO BW1
10246 \ ENDCODE
10247
10248
10249 \ ******************************\
10250 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
10251 \ ******************************\
10252 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
10253 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
10254 BIT.B #SW2,&SW2_IN              \ test switch S2
10255 0= IF                           \ case of switch S2 pressed
10256     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
10257     U< IF
10258         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
10259     THEN
10260 ELSE
10261     BIT.B #SW1,&SW1_IN          \ test switch S1 input
10262     0= IF                       \ case of Switch S1 pressed
10263         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
10264         U>= IF                  \
10265            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
10266         THEN                    \
10267     THEN                        \
10268 THEN                            \
10269 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
10270 RET                             \ 5
10271 ENDASM
10272
10273 \ ******************************\
10274 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
10275 \ ******************************\
10276 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
10277 \ ******************************\
10278 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
10279 \                               \       SMclock = 8|16|24 MHz
10280 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
10281 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
10282 \                               \       SR(9)=new Toggle bit memory (ADD on)
10283 \ ******************************\
10284 \ RC5_FirstStartBitHalfCycle:   \
10285 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
10286 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
10287 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
10288 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
10289 \ [THEN]
10290 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
10291     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
10292 [THEN]
10293 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
10294     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
10295 [THEN]
10296 MOV #1778,X                     \ RC5_Period * 1us
10297 MOV #14,W                       \ count of loop
10298 BEGIN                           \
10299 \ ******************************\
10300 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
10301 \ ******************************\                   |
10302 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
10303 \ RC5_Compute_3/4_Period:       \                   |
10304     RRUM    #1,X                \ X=1/2 cycle       |
10305     MOV     X,Y                 \                   ^
10306     RRUM    #1,Y                \ Y=1/4
10307     ADD     X,Y                 \ Y=3/4 cycle
10308     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
10309     U>= UNTIL                   \ 2
10310 \ ******************************\
10311 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
10312 \ ******************************\
10313     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
10314     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
10315     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
10316     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
10317     SUB     #1,W                \ decrement count loop
10318 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
10319 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
10320 0<> WHILE                       \ ----> out of loop ----+
10321     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
10322     BEGIN                       \                       |
10323         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
10324         CMP Y,X                 \ 1                     |   cycle time out of bound ?
10325         U>= IF                  \ 2                 ^   |   yes:
10326         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
10327         GOTO BW1                \                   |   |      quit on truncated RC5 message
10328         THEN                    \                   |   |
10329         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
10330     0<> UNTIL                   \ 2                 |   |
10331 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
10332 \ ******************************\                       |
10333 \ RC5_SampleEndOf:              \ <---------------------+
10334 \ ******************************\
10335 BIC #$30,&RC5_TIM_CTL           \   stop timer
10336 \ ******************************\
10337 \ RC5_ComputeNewRC5word         \
10338 \ ******************************\
10339 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
10340 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
10341 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
10342 \ ******************************\
10343 \ RC5_ComputeC6bit              \
10344 \ ******************************\
10345 BIT     #BIT14,T                \ test /C6 bit in T
10346 0= IF   BIS #BIT6,X             \ set C6 bit in X
10347 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
10348 \ ******************************\
10349 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
10350 \ ******************************\
10351 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
10352 \ ******************************\
10353 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
10354 XOR     @RSP,T                  \ (new XOR old) Toggle bits
10355 BIT     #UF10,T                 \ repeated RC5_command ?
10356 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
10357 XOR #UF10,0(RSP)                \ 5 toggle bit memory
10358 \ ******************************\
10359 \ Display IR_RC5 code           \
10360 \ ******************************\
10361 SUB #8,PSP                      \ TOS -- x x x x TOS
10362 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
10363 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
10364 MOV #$10,&BASEADR               \                                               set hexadecimal base
10365 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
10366 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
10367 LO2HI                           \                                               switch from assembler to FORTH
10368     LCD_CLEAR                   \                                               set LCD cursor at home
10369     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
10370     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
10371     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
10372     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
10373 HI2LO                           \     --                                        switch from FORTH to assembler
10374 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
10375 MOV @PSP+,TOS                   \     -- TOS
10376 RET
10377 ENDASM
10378
10379 \ ******************************\
10380 ASM BACKGROUND                  \
10381 \ ******************************\
10382 BEGIN
10383 \     ...                         \ insert here your background task
10384 \     ...                         \
10385 \     ...                         \
10386     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
10387     BIS &LPM_MODE,SR            \
10388 \ ******************************\
10389 \ here start all interrupts     \
10390 \ ******************************\
10391 \ here return all interrupts    \
10392 \ ******************************\
10393 AGAIN                           \
10394 ENDASM                          \
10395 \ ******************************\
10396
10397 \ ------------------------------\
10398 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
10399 \ ------------------------------\
10400 \     ...                         \ init specific I/O sys as you want
10401 \     ...                         \ before executing default WARM
10402     MOV #WARM,X                 \ ['] WARM 
10403     ADD #4,X                    \ >BODY
10404     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
10405 ENDASM
10406 \ ------------------------------\
10407
10408 \ ------------------------------\
10409 CODE STOP                       \ stops multitasking, must to be used before downloading app
10410 \ ------------------------------\
10411 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
10412     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
10413     MOV X,-2(X)                 \ restore the default background: SLEEP
10414     MOV #WARM,X
10415     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
10416     BIC.B #RC5,&IR_IE           \ clear RC5_Int
10417     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
10418     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
10419     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
10420     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
10421     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
10422 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
10423 ECHO                            \
10424 ." RC5toLCD is removed,"
10425 ."  type START to restart"
10426  WARM                           \ performs reset to reset all interrupt vectors.    
10427 ;
10428 \ ------------------------------\
10429
10430 \ ------------------------------\
10431 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
10432 \ ------------------------------\
10433 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
10434 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
10435 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
10436 \                           --       \ID input divider \ 10 = /4
10437 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
10438 \                                 -  \TBCLR TimerB Clear
10439 \                                  - \TBIE
10440 \                                   -\TBIFG
10441 \ -------------------------------\
10442 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
10443 \                  --                 \CM Capture Mode
10444 \                    --               \CCIS
10445 \                       -             \SCS
10446 \                        --           \CLLD
10447 \                          -          \CAP
10448 \                            ---      \OUTMOD \ 011 = set/reset
10449 \                               -     \CCIE
10450 \                                 -   \CCI
10451 \                                  -  \OUT
10452 \                                   - \COV
10453 \                                    -\CCIFG
10454 \ -------------------------------\
10455 \ LCD_TIM_CCRx                   \
10456 \ -------------------------------\
10457 \ LCD_TIM_EX0                    \ 
10458 \ ------------------------------\
10459 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
10460 \ ------------------------------\
10461 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
10462 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
10463 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
10464     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
10465 [THEN]
10466 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
10467     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
10468 [THEN]
10469     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
10470 \ ------------------------------\
10471 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
10472 \ ------------------------------\
10473 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
10474     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
10475 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
10476 \ ------------------------------\
10477     BIS.B #LCDVo,&LCDVo_DIR     \
10478     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
10479 \ ------------------------------\
10480     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
10481     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
10482 \ ------------------------------\
10483     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
10484     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
10485 \ ******************************\
10486 \ init RC5_Int                  \
10487 \ ******************************\
10488     BIS.B #RC5,&IR_IE           \ enable RC5_Int
10489     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
10490     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
10491 \ ******************************\
10492 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
10493 \ ******************************\
10494 \              %01 0001 0100    \ TAxCTL
10495 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
10496 \                  --           \ ID        divided by 1
10497 \                    --         \ MC        MODE = up to TAxCCRn
10498 \                        -      \ TACLR     clear timer count
10499 \                         -     \ TAIE
10500 \                          -    \ TAIFG
10501 \ ------------------------------\
10502 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
10503 \ ------------------------------\
10504 \                        000    \ TAxEX0
10505 \                        ---    \ TAIDEX    pre divisor
10506 \ ------------------------------\
10507 \          %0000 0000 0000 0101 \ TAxCCR0
10508     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
10509 \ ------------------------------\
10510 \          %0000 0000 0001 0000 \ TAxCCTL0
10511 \                   -           \ CAP capture/compare mode = compare
10512 \                        -      \ CCIEn
10513 \                             - \ CCIFGn
10514     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
10515 \ ------------------------------\
10516     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
10517 \ ------------------------------\
10518 \ define LPM mode for ACCEPT    \
10519 \ ------------------------------\
10520 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
10521 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
10522 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
10523 \ ------------------------------\
10524 \ activate I/O                  \
10525 \ ------------------------------\
10526 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
10527 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
10528 \ ------------------------------\
10529 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
10530 \ ------------------------------\
10531 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
10532 \ CMP #2,Y                        \ Power_ON event
10533 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
10534 CMP #4,Y                        \
10535 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
10536 \ CMP #6,Y                        \
10537 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
10538 \ CMP #$0A,Y                      \
10539 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
10540 \ CMP #$16,Y                      \
10541 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
10542 \ ------------------------------\
10543 COLON                           \
10544 \ ------------------------------\
10545 \ Init LCD 2x20                 \
10546 \ ------------------------------\
10547     #1000 20_US                 \ 1- wait 20 ms
10548     %011 TOP_LCD                \ 2- send DB5=DB4=1
10549     #205 20_US                  \ 3- wait 4,1 ms
10550     %011 TOP_LCD                \ 4- send again DB5=DB4=1
10551     #5 20_US                    \ 5- wait 0,1 ms
10552     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
10553     #2 20_US                    \    wait 40 us = LCD cycle
10554     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
10555     #2 20_US                    \    wait 40 us = LCD cycle
10556     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
10557     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
10558     LCD_CLEAR                   \ 10- "LCD_Clear"
10559     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
10560     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
10561     LCD_CLEAR                   \ 10- "LCD_Clear"
10562     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
10563     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
10564     CR ." I love you"           \ display message on LCD
10565     ['] CR >BODY IS CR          \ CR executes its default value
10566     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
10567     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
10568     PWR_STATE ABORT             \ init DP and continues with ABORT
10569 ;                               \
10570 \ ------------------------------\
10571
10572 \ ------------------------------\
10573 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
10574 \ ------------------------------\
10575 MOV #SLEEP,X                    \ replace default background process SLEEP
10576 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
10577 MOV #WARM,X                     \ replace default WARM
10578 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
10579 MOV X,PC                        \ then execute new WARM
10580 ENDCODE 
10581 \ ------------------------------\
10582
10583 ECHO
10584             ; downloading RC5toLCD.4th is done
10585 RST_HERE    ; this app is protected against <reset>
10586
10587
10588 RST_STATE
10589
10590 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
10591
10592 [UNDEFINED] MARKER [IF]
10593 \  https://forth-standard.org/standard/core/MARKER
10594 \  MARKER
10595 \ ( "<spaces>name" -- )
10596 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
10597 \ with the execution semantics defined below.
10598
10599 \ name Execution: ( -- )
10600 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
10601 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
10602 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
10603 \ not necessarily provided. No other contextual information such as numeric base is affected
10604 \
10605 : MARKER
10606 CREATE
10607 HI2LO
10608 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
10609 SUB #2,Y            \ 1 Y = LFA
10610 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
10611 ADD #4,&DP          \ 3 add 2 cells
10612 LO2HI
10613 DOES>
10614 HI2LO
10615 MOV @RSP+,IP        \ -- PFA
10616 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
10617 MOV @TOS,&INIDP     \       set DP value for RST_STATE
10618 MOV @PSP+,TOS       \ --
10619 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
10620 ENDCODE
10621 [THEN]
10622
10623 MARKER {RC5TOLCD}
10624
10625 [UNDEFINED] @ [IF]
10626 \ https://forth-standard.org/standard/core/Fetch
10627 \ @     c-addr -- char   fetch char from memory
10628 CODE @
10629 MOV @TOS,TOS
10630 MOV @IP+,PC
10631 ENDCODE
10632 [THEN]
10633
10634 [UNDEFINED] CONSTANT [IF]
10635 \ https://forth-standard.org/standard/core/CONSTANT
10636 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
10637 : CONSTANT 
10638 CREATE
10639 HI2LO
10640 MOV TOS,-2(W)           \   PFA = n
10641 MOV @PSP+,TOS
10642 MOV @RSP+,IP
10643 MOV @IP+,PC
10644 ENDCODE
10645 [THEN]
10646
10647 [UNDEFINED] STATE [IF]
10648 \ https://forth-standard.org/standard/core/STATE
10649 \ STATE   -- a-addr       holds compiler state
10650 STATEADR CONSTANT STATE
10651 [THEN]
10652
10653 [UNDEFINED] = [IF]
10654 \ https://forth-standard.org/standard/core/Equal
10655 \ =      x1 x2 -- flag         test x1=x2
10656 CODE =
10657 SUB @PSP+,TOS   \ 2
10658 0<> IF          \ 2
10659     AND #0,TOS  \ 1
10660     MOV @IP+,PC \ 4
10661 THEN
10662 XOR #-1,TOS     \ 1 flag Z = 1
10663 MOV @IP+,PC     \ 4
10664 ENDCODE
10665 [THEN]
10666
10667 [UNDEFINED] IF [IF]
10668 \ https://forth-standard.org/standard/core/IF
10669 \ IF       -- IFadr    initialize conditional forward branch
10670 CODE IF       \ immediate
10671 SUB #2,PSP              \
10672 MOV TOS,0(PSP)          \
10673 MOV &DP,TOS             \ -- HERE
10674 ADD #4,&DP            \           compile one word, reserve one word
10675 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
10676 ADD #2,TOS              \ -- HERE+2=IFadr
10677 MOV @IP+,PC
10678 ENDCODE IMMEDIATE
10679 [THEN]
10680
10681 [UNDEFINED] THEN [IF]
10682 \ https://forth-standard.org/standard/core/THEN
10683 \ THEN     IFadr --                resolve forward branch
10684 CODE THEN               \ immediate
10685 MOV &DP,0(TOS)          \ -- IFadr
10686 MOV @PSP+,TOS           \ --
10687 MOV @IP+,PC
10688 ENDCODE IMMEDIATE
10689 [THEN]
10690
10691 [UNDEFINED] ELSE [IF]
10692 \ https://forth-standard.org/standard/core/ELSE
10693 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
10694 CODE ELSE     \ immediate
10695 ADD #4,&DP              \ make room to compile two words
10696 MOV &DP,W               \ W=HERE+4
10697 MOV #BRAN,-4(W)
10698 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
10699 SUB #2,W                \ HERE+2
10700 MOV W,TOS               \ -- ELSEadr
10701 MOV @IP+,PC
10702 ENDCODE IMMEDIATE
10703 [THEN]
10704
10705 [UNDEFINED] DEFER [IF]
10706 \ https://forth-standard.org/standard/core/DEFER
10707 \ DEFER "<spaces>name"   --
10708 \ Skip leading space delimiters. Parse name delimited by a space.
10709 \ Create a definition for name with the execution semantics defined below.
10710
10711 \ name Execution:   --
10712 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
10713 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
10714 : DEFER
10715 CREATE
10716 HI2LO
10717 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
10718 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
10719 MOV @RSP+,IP
10720 MOV @IP+,PC
10721 ENDCODE
10722 [THEN]
10723
10724 [UNDEFINED] DEFER! [IF]
10725 \ https://forth-standard.org/standard/core/DEFERStore
10726 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
10727 CODE DEFER!             \ xt2 xt1 --
10728 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
10729 MOV @PSP+,TOS           \ --
10730 MOV @IP+,PC
10731 ENDCODE
10732 [THEN]
10733
10734 [UNDEFINED] IS [IF]
10735 \ https://forth-standard.org/standard/core/IS
10736 \ IS <name>        xt --
10737 \ used as is :
10738 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
10739 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
10740 \ or in a definition : ... ['] U. IS DISPLAY ...
10741 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
10742 \
10743 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
10744 : IS
10745 STATE @
10746 IF  POSTPONE ['] POSTPONE DEFER! 
10747 ELSE ' DEFER! 
10748 THEN
10749 ; IMMEDIATE
10750 [THEN]
10751
10752 [UNDEFINED] >BODY [IF]
10753 \ https://forth-standard.org/standard/core/toBODY
10754 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
10755 CODE >BODY
10756 ADD #4,TOS
10757 MOV @IP+,PC
10758 ENDCODE
10759 [THEN]
10760
10761 \ CODE 20uS           \ n --      8MHz version
10762 \ BEGIN               \ 4 + 16 ~ loop
10763 \     MOV #39,rDOCON   \ 39
10764 \     BEGIN           \ 4 ~ loop
10765 \         NOP
10766 \         SUB #1,rDOCON
10767 \     0=  UNTIL
10768 \     SUB #1,TOS      \ 1
10769 \ 0= UNTIL
10770 \ MOV #XDOCON,rDOCON  \ 2
10771 \ MOV @PSP+,TOS
10772 \ MOV @RSP+,IP        \
10773 \ ENDCODE
10774
10775 CODE 20_US                      \ n --      n * 20 us
10776 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
10777     BEGIN
10778         BIT #1,&LCD_TIM_CTL     \ 3
10779     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
10780     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
10781     SUB #1,TOS                  \ 1
10782 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
10783 MOV @PSP+,TOS                   \ 2
10784 MOV @IP+,PC                     \ 4
10785 ENDCODE
10786
10787 CODE TOP_LCD                    \ LCD Sample
10788 \                               \ if write : %xxxx_WWWW --
10789 \                               \ if read  : -- %0000_RRRR
10790     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
10791     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
10792 0= IF                           \ write LCD bits pattern
10793     AND.B #LCD_DB,TOS           \ 
10794     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
10795     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
10796     MOV @PSP+,TOS               \
10797     MOV @IP+,PC
10798 THEN                            \ read LCD bits pattern
10799     SUB #2,PSP
10800     MOV TOS,0(PSP)
10801     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
10802     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
10803     AND.B #LCD_DB,TOS           \
10804     MOV @IP+,PC
10805 ENDCODE
10806
10807 CODE LCD_WRC                    \ char --         Write Char
10808     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
10809 BW1 SUB #2,PSP                  \
10810     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
10811     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
10812     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
10813     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
10814 COLON                           \ high level word starts here 
10815     TOP_LCD 2 20_US             \ write high nibble first
10816     TOP_LCD 2 20_US 
10817 ;
10818
10819 CODE LCD_WRF                    \ func --         Write Fonction
10820     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
10821     GOTO BW1
10822 ENDCODE
10823
10824 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
10825 : LCD_HOME $02 LCD_WRF 100 20_us ;
10826
10827 \ [UNDEFINED] OR [IF]
10828
10829 \ \ https://forth-standard.org/standard/core/OR
10830 \ \ C OR     x1 x2 -- x3           logical OR
10831 \ CODE OR
10832 \ BIS @PSP+,TOS
10833 \ MOV @IP+,PC
10834 \ ENDCODE
10835
10836 \ [THEN]
10837
10838 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
10839 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
10840 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
10841 \ : LCD_FN_SET        $20 OR LCD_WrF ;
10842 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
10843 \ : LCD_GOTO          $80 OR LCD_WrF ;
10844
10845
10846 \ CODE LCD_RDS                    \ -- status       Read Status
10847 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
10848 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
10849 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
10850 \ COLON                           \ starts a FORTH word
10851 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
10852 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
10853 \ HI2LO                           \ switch from FORTH to assembler
10854 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
10855 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
10856 \     MOV @RSP+,IP                \ restore IP saved by COLON
10857 \     MOV @IP+,PC                 \
10858 \ ENDCODE
10859
10860 \ CODE LCD_RDC                    \ -- char         Read Char
10861 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
10862 \     GOTO BW1
10863 \ ENDCODE
10864
10865
10866 \ ******************************\
10867 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
10868 \ ******************************\
10869 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
10870 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
10871 BIT.B #SW2,&SW2_IN              \ test switch S2
10872 0= IF                           \ case of switch S2 pressed
10873     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
10874     U< IF
10875         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
10876     THEN
10877 ELSE
10878     BIT.B #SW1,&SW1_IN          \ test switch S1 input
10879     0= IF                       \ case of Switch S1 pressed
10880         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
10881         U>= IF                  \
10882            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
10883         THEN                    \
10884     THEN                        \
10885 THEN                            \
10886 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
10887 RET                             \ 5
10888 ENDASM
10889
10890 \ ******************************\
10891 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
10892 \ ******************************\
10893 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
10894 \ ******************************\
10895 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
10896 \                               \       SMclock = 8|16|24 MHz
10897 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
10898 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
10899 \                               \       SR(9)=new Toggle bit memory (ADD on)
10900 \ ******************************\
10901 \ RC5_FirstStartBitHalfCycle:   \
10902 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
10903 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
10904 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
10905 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
10906 \ [THEN]
10907 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
10908     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
10909 [THEN]
10910 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
10911     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
10912 [THEN]
10913 MOV #1778,X                     \ RC5_Period * 1us
10914 MOV #14,W                       \ count of loop
10915 BEGIN                           \
10916 \ ******************************\
10917 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
10918 \ ******************************\                   |
10919 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
10920 \ RC5_Compute_3/4_Period:       \                   |
10921     RRUM    #1,X                \ X=1/2 cycle       |
10922     MOV     X,Y                 \                   ^
10923     RRUM    #1,Y                \ Y=1/4
10924     ADD     X,Y                 \ Y=3/4 cycle
10925     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
10926     U>= UNTIL                   \ 2
10927 \ ******************************\
10928 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
10929 \ ******************************\
10930     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
10931     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
10932     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
10933     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
10934     SUB     #1,W                \ decrement count loop
10935 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
10936 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
10937 0<> WHILE                       \ ----> out of loop ----+
10938     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
10939     BEGIN                       \                       |
10940         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
10941         CMP Y,X                 \ 1                     |   cycle time out of bound ?
10942         U>= IF                  \ 2                 ^   |   yes:
10943         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
10944         GOTO BW1                \                   |   |      quit on truncated RC5 message
10945         THEN                    \                   |   |
10946         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
10947     0<> UNTIL                   \ 2                 |   |
10948 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
10949 \ ******************************\                       |
10950 \ RC5_SampleEndOf:              \ <---------------------+
10951 \ ******************************\
10952 BIC #$30,&RC5_TIM_CTL           \   stop timer
10953 \ ******************************\
10954 \ RC5_ComputeNewRC5word         \
10955 \ ******************************\
10956 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
10957 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
10958 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
10959 \ ******************************\
10960 \ RC5_ComputeC6bit              \
10961 \ ******************************\
10962 BIT     #BIT14,T                \ test /C6 bit in T
10963 0= IF   BIS #BIT6,X             \ set C6 bit in X
10964 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
10965 \ ******************************\
10966 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
10967 \ ******************************\
10968 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
10969 \ ******************************\
10970 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
10971 XOR     @RSP,T                  \ (new XOR old) Toggle bits
10972 BIT     #UF10,T                 \ repeated RC5_command ?
10973 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
10974 XOR #UF10,0(RSP)                \ 5 toggle bit memory
10975 \ ******************************\
10976 \ Display IR_RC5 code           \
10977 \ ******************************\
10978 SUB #8,PSP                      \ TOS -- x x x x TOS
10979 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
10980 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
10981 MOV #$10,&BASEADR               \                                               set hexadecimal base
10982 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
10983 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
10984 LO2HI                           \                                               switch from assembler to FORTH
10985     LCD_CLEAR                   \                                               set LCD cursor at home
10986     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
10987     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
10988     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
10989     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
10990 HI2LO                           \     --                                        switch from FORTH to assembler
10991 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
10992 MOV @PSP+,TOS                   \     -- TOS
10993 RET
10994 ENDASM
10995
10996 \ ******************************\
10997 ASM BACKGROUND                  \
10998 \ ******************************\
10999 BEGIN
11000 \     ...                         \ insert here your background task
11001 \     ...                         \
11002 \     ...                         \
11003     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
11004     BIS &LPM_MODE,SR            \
11005 \ ******************************\
11006 \ here start all interrupts     \
11007 \ ******************************\
11008 \ here return all interrupts    \
11009 \ ******************************\
11010 AGAIN                           \
11011 ENDASM                          \
11012 \ ******************************\
11013
11014 \ ------------------------------\
11015 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
11016 \ ------------------------------\
11017 \     ...                         \ init specific I/O sys as you want
11018 \     ...                         \ before executing default WARM
11019     MOV #WARM,X                 \ ['] WARM 
11020     ADD #4,X                    \ >BODY
11021     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
11022 ENDASM
11023 \ ------------------------------\
11024
11025 \ ------------------------------\
11026 CODE STOP                       \ stops multitasking, must to be used before downloading app
11027 \ ------------------------------\
11028 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
11029     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
11030     MOV X,-2(X)                 \ restore the default background: SLEEP
11031     MOV #WARM,X
11032     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
11033     BIC.B #RC5,&IR_IE           \ clear RC5_Int
11034     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
11035     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
11036     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
11037     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
11038     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
11039 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
11040 ECHO                            \
11041 ." RC5toLCD is removed,"
11042 ."  type START to restart"
11043  WARM                           \ performs reset to reset all interrupt vectors.    
11044 ;
11045 \ ------------------------------\
11046
11047 \ ------------------------------\
11048 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
11049 \ ------------------------------\
11050 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
11051 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
11052 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
11053 \                           --       \ID input divider \ 10 = /4
11054 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
11055 \                                 -  \TBCLR TimerB Clear
11056 \                                  - \TBIE
11057 \                                   -\TBIFG
11058 \ -------------------------------\
11059 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
11060 \                  --                 \CM Capture Mode
11061 \                    --               \CCIS
11062 \                       -             \SCS
11063 \                        --           \CLLD
11064 \                          -          \CAP
11065 \                            ---      \OUTMOD \ 011 = set/reset
11066 \                               -     \CCIE
11067 \                                 -   \CCI
11068 \                                  -  \OUT
11069 \                                   - \COV
11070 \                                    -\CCIFG
11071 \ -------------------------------\
11072 \ LCD_TIM_CCRx                   \
11073 \ -------------------------------\
11074 \ LCD_TIM_EX0                    \ 
11075 \ ------------------------------\
11076 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
11077 \ ------------------------------\
11078 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
11079 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
11080 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
11081     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
11082 [THEN]
11083 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
11084     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
11085 [THEN]
11086     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
11087 \ ------------------------------\
11088 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
11089 \ ------------------------------\
11090 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
11091     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
11092 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
11093 \ ------------------------------\
11094     BIS.B #LCDVo,&LCDVo_DIR     \
11095     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
11096 \ ------------------------------\
11097     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
11098     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
11099 \ ------------------------------\
11100     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
11101     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
11102 \ ******************************\
11103 \ init RC5_Int                  \
11104 \ ******************************\
11105     BIS.B #RC5,&IR_IE           \ enable RC5_Int
11106     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
11107     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
11108 \ ******************************\
11109 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
11110 \ ******************************\
11111 \              %01 0001 0100    \ TAxCTL
11112 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
11113 \                  --           \ ID        divided by 1
11114 \                    --         \ MC        MODE = up to TAxCCRn
11115 \                        -      \ TACLR     clear timer count
11116 \                         -     \ TAIE
11117 \                          -    \ TAIFG
11118 \ ------------------------------\
11119 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
11120 \ ------------------------------\
11121 \                        000    \ TAxEX0
11122 \                        ---    \ TAIDEX    pre divisor
11123 \ ------------------------------\
11124 \          %0000 0000 0000 0101 \ TAxCCR0
11125     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
11126 \ ------------------------------\
11127 \          %0000 0000 0001 0000 \ TAxCCTL0
11128 \                   -           \ CAP capture/compare mode = compare
11129 \                        -      \ CCIEn
11130 \                             - \ CCIFGn
11131     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
11132 \ ------------------------------\
11133     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
11134 \ ------------------------------\
11135 \ define LPM mode for ACCEPT    \
11136 \ ------------------------------\
11137 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
11138 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
11139 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
11140 \ ------------------------------\
11141 \ activate I/O                  \
11142 \ ------------------------------\
11143 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
11144 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
11145 \ ------------------------------\
11146 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
11147 \ ------------------------------\
11148 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
11149 \ CMP #2,Y                        \ Power_ON event
11150 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
11151 CMP #4,Y                        \
11152 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
11153 \ CMP #6,Y                        \
11154 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
11155 \ CMP #$0A,Y                      \
11156 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
11157 \ CMP #$16,Y                      \
11158 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
11159 \ ------------------------------\
11160 COLON                           \
11161 \ ------------------------------\
11162 \ Init LCD 2x20                 \
11163 \ ------------------------------\
11164     #1000 20_US                 \ 1- wait 20 ms
11165     %011 TOP_LCD                \ 2- send DB5=DB4=1
11166     #205 20_US                  \ 3- wait 4,1 ms
11167     %011 TOP_LCD                \ 4- send again DB5=DB4=1
11168     #5 20_US                    \ 5- wait 0,1 ms
11169     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
11170     #2 20_US                    \    wait 40 us = LCD cycle
11171     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
11172     #2 20_US                    \    wait 40 us = LCD cycle
11173     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
11174     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
11175     LCD_CLEAR                   \ 10- "LCD_Clear"
11176     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
11177     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
11178     LCD_CLEAR                   \ 10- "LCD_Clear"
11179     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
11180     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
11181     CR ." I love you"           \ display message on LCD
11182     ['] CR >BODY IS CR          \ CR executes its default value
11183     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
11184     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
11185     PWR_STATE ABORT             \ init DP and continues with ABORT
11186 ;                               \
11187 \ ------------------------------\
11188
11189 \ ------------------------------\
11190 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
11191 \ ------------------------------\
11192 MOV #SLEEP,X                    \ replace default background process SLEEP
11193 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
11194 MOV #WARM,X                     \ replace default WARM
11195 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
11196 MOV X,PC                        \ then execute new WARM
11197 ENDCODE 
11198 \ ------------------------------\
11199
11200 ECHO
11201             ; downloading RC5toLCD.4th is done
11202 RST_HERE    ; this app is protected against <reset>
11203
11204
11205 RST_STATE
11206
11207 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
11208
11209 [UNDEFINED] MARKER [IF]
11210 \  https://forth-standard.org/standard/core/MARKER
11211 \  MARKER
11212 \ ( "<spaces>name" -- )
11213 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
11214 \ with the execution semantics defined below.
11215
11216 \ name Execution: ( -- )
11217 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
11218 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
11219 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
11220 \ not necessarily provided. No other contextual information such as numeric base is affected
11221 \
11222 : MARKER
11223 CREATE
11224 HI2LO
11225 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
11226 SUB #2,Y            \ 1 Y = LFA
11227 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
11228 ADD #4,&DP          \ 3 add 2 cells
11229 LO2HI
11230 DOES>
11231 HI2LO
11232 MOV @RSP+,IP        \ -- PFA
11233 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
11234 MOV @TOS,&INIDP     \       set DP value for RST_STATE
11235 MOV @PSP+,TOS       \ --
11236 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
11237 ENDCODE
11238 [THEN]
11239
11240 MARKER {RC5TOLCD}
11241
11242 [UNDEFINED] @ [IF]
11243 \ https://forth-standard.org/standard/core/Fetch
11244 \ @     c-addr -- char   fetch char from memory
11245 CODE @
11246 MOV @TOS,TOS
11247 MOV @IP+,PC
11248 ENDCODE
11249 [THEN]
11250
11251 [UNDEFINED] CONSTANT [IF]
11252 \ https://forth-standard.org/standard/core/CONSTANT
11253 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
11254 : CONSTANT 
11255 CREATE
11256 HI2LO
11257 MOV TOS,-2(W)           \   PFA = n
11258 MOV @PSP+,TOS
11259 MOV @RSP+,IP
11260 MOV @IP+,PC
11261 ENDCODE
11262 [THEN]
11263
11264 [UNDEFINED] STATE [IF]
11265 \ https://forth-standard.org/standard/core/STATE
11266 \ STATE   -- a-addr       holds compiler state
11267 STATEADR CONSTANT STATE
11268 [THEN]
11269
11270 [UNDEFINED] = [IF]
11271 \ https://forth-standard.org/standard/core/Equal
11272 \ =      x1 x2 -- flag         test x1=x2
11273 CODE =
11274 SUB @PSP+,TOS   \ 2
11275 0<> IF          \ 2
11276     AND #0,TOS  \ 1
11277     MOV @IP+,PC \ 4
11278 THEN
11279 XOR #-1,TOS     \ 1 flag Z = 1
11280 MOV @IP+,PC     \ 4
11281 ENDCODE
11282 [THEN]
11283
11284 [UNDEFINED] IF [IF]
11285 \ https://forth-standard.org/standard/core/IF
11286 \ IF       -- IFadr    initialize conditional forward branch
11287 CODE IF       \ immediate
11288 SUB #2,PSP              \
11289 MOV TOS,0(PSP)          \
11290 MOV &DP,TOS             \ -- HERE
11291 ADD #4,&DP            \           compile one word, reserve one word
11292 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
11293 ADD #2,TOS              \ -- HERE+2=IFadr
11294 MOV @IP+,PC
11295 ENDCODE IMMEDIATE
11296 [THEN]
11297
11298 [UNDEFINED] THEN [IF]
11299 \ https://forth-standard.org/standard/core/THEN
11300 \ THEN     IFadr --                resolve forward branch
11301 CODE THEN               \ immediate
11302 MOV &DP,0(TOS)          \ -- IFadr
11303 MOV @PSP+,TOS           \ --
11304 MOV @IP+,PC
11305 ENDCODE IMMEDIATE
11306 [THEN]
11307
11308 [UNDEFINED] ELSE [IF]
11309 \ https://forth-standard.org/standard/core/ELSE
11310 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
11311 CODE ELSE     \ immediate
11312 ADD #4,&DP              \ make room to compile two words
11313 MOV &DP,W               \ W=HERE+4
11314 MOV #BRAN,-4(W)
11315 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
11316 SUB #2,W                \ HERE+2
11317 MOV W,TOS               \ -- ELSEadr
11318 MOV @IP+,PC
11319 ENDCODE IMMEDIATE
11320 [THEN]
11321
11322 [UNDEFINED] DEFER [IF]
11323 \ https://forth-standard.org/standard/core/DEFER
11324 \ DEFER "<spaces>name"   --
11325 \ Skip leading space delimiters. Parse name delimited by a space.
11326 \ Create a definition for name with the execution semantics defined below.
11327
11328 \ name Execution:   --
11329 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
11330 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
11331 : DEFER
11332 CREATE
11333 HI2LO
11334 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
11335 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
11336 MOV @RSP+,IP
11337 MOV @IP+,PC
11338 ENDCODE
11339 [THEN]
11340
11341 [UNDEFINED] DEFER! [IF]
11342 \ https://forth-standard.org/standard/core/DEFERStore
11343 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
11344 CODE DEFER!             \ xt2 xt1 --
11345 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
11346 MOV @PSP+,TOS           \ --
11347 MOV @IP+,PC
11348 ENDCODE
11349 [THEN]
11350
11351 [UNDEFINED] IS [IF]
11352 \ https://forth-standard.org/standard/core/IS
11353 \ IS <name>        xt --
11354 \ used as is :
11355 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
11356 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
11357 \ or in a definition : ... ['] U. IS DISPLAY ...
11358 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
11359 \
11360 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
11361 : IS
11362 STATE @
11363 IF  POSTPONE ['] POSTPONE DEFER! 
11364 ELSE ' DEFER! 
11365 THEN
11366 ; IMMEDIATE
11367 [THEN]
11368
11369 [UNDEFINED] >BODY [IF]
11370 \ https://forth-standard.org/standard/core/toBODY
11371 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
11372 CODE >BODY
11373 ADD #4,TOS
11374 MOV @IP+,PC
11375 ENDCODE
11376 [THEN]
11377
11378 \ CODE 20uS           \ n --      8MHz version
11379 \ BEGIN               \ 4 + 16 ~ loop
11380 \     MOV #39,rDOCON   \ 39
11381 \     BEGIN           \ 4 ~ loop
11382 \         NOP
11383 \         SUB #1,rDOCON
11384 \     0=  UNTIL
11385 \     SUB #1,TOS      \ 1
11386 \ 0= UNTIL
11387 \ MOV #XDOCON,rDOCON  \ 2
11388 \ MOV @PSP+,TOS
11389 \ MOV @RSP+,IP        \
11390 \ ENDCODE
11391
11392 CODE 20_US                      \ n --      n * 20 us
11393 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
11394     BEGIN
11395         BIT #1,&LCD_TIM_CTL     \ 3
11396     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
11397     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
11398     SUB #1,TOS                  \ 1
11399 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
11400 MOV @PSP+,TOS                   \ 2
11401 MOV @IP+,PC                     \ 4
11402 ENDCODE
11403
11404 CODE TOP_LCD                    \ LCD Sample
11405 \                               \ if write : %xxxx_WWWW --
11406 \                               \ if read  : -- %0000_RRRR
11407     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
11408     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
11409 0= IF                           \ write LCD bits pattern
11410     AND.B #LCD_DB,TOS           \ 
11411     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
11412     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
11413     MOV @PSP+,TOS               \
11414     MOV @IP+,PC
11415 THEN                            \ read LCD bits pattern
11416     SUB #2,PSP
11417     MOV TOS,0(PSP)
11418     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
11419     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
11420     AND.B #LCD_DB,TOS           \
11421     MOV @IP+,PC
11422 ENDCODE
11423
11424 CODE LCD_WRC                    \ char --         Write Char
11425     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
11426 BW1 SUB #2,PSP                  \
11427     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
11428     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
11429     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
11430     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
11431 COLON                           \ high level word starts here 
11432     TOP_LCD 2 20_US             \ write high nibble first
11433     TOP_LCD 2 20_US 
11434 ;
11435
11436 CODE LCD_WRF                    \ func --         Write Fonction
11437     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
11438     GOTO BW1
11439 ENDCODE
11440
11441 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
11442 : LCD_HOME $02 LCD_WRF 100 20_us ;
11443
11444 \ [UNDEFINED] OR [IF]
11445
11446 \ \ https://forth-standard.org/standard/core/OR
11447 \ \ C OR     x1 x2 -- x3           logical OR
11448 \ CODE OR
11449 \ BIS @PSP+,TOS
11450 \ MOV @IP+,PC
11451 \ ENDCODE
11452
11453 \ [THEN]
11454
11455 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
11456 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
11457 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
11458 \ : LCD_FN_SET        $20 OR LCD_WrF ;
11459 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
11460 \ : LCD_GOTO          $80 OR LCD_WrF ;
11461
11462
11463 \ CODE LCD_RDS                    \ -- status       Read Status
11464 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
11465 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
11466 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
11467 \ COLON                           \ starts a FORTH word
11468 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
11469 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
11470 \ HI2LO                           \ switch from FORTH to assembler
11471 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
11472 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
11473 \     MOV @RSP+,IP                \ restore IP saved by COLON
11474 \     MOV @IP+,PC                 \
11475 \ ENDCODE
11476
11477 \ CODE LCD_RDC                    \ -- char         Read Char
11478 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
11479 \     GOTO BW1
11480 \ ENDCODE
11481
11482
11483 \ ******************************\
11484 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
11485 \ ******************************\
11486 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
11487 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
11488 BIT.B #SW2,&SW2_IN              \ test switch S2
11489 0= IF                           \ case of switch S2 pressed
11490     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
11491     U< IF
11492         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
11493     THEN
11494 ELSE
11495     BIT.B #SW1,&SW1_IN          \ test switch S1 input
11496     0= IF                       \ case of Switch S1 pressed
11497         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
11498         U>= IF                  \
11499            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
11500         THEN                    \
11501     THEN                        \
11502 THEN                            \
11503 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
11504 RET                             \ 5
11505 ENDASM
11506
11507 \ ******************************\
11508 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
11509 \ ******************************\
11510 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
11511 \ ******************************\
11512 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
11513 \                               \       SMclock = 8|16|24 MHz
11514 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
11515 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
11516 \                               \       SR(9)=new Toggle bit memory (ADD on)
11517 \ ******************************\
11518 \ RC5_FirstStartBitHalfCycle:   \
11519 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
11520 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
11521 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
11522 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
11523 \ [THEN]
11524 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
11525     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
11526 [THEN]
11527 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
11528     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
11529 [THEN]
11530 MOV #1778,X                     \ RC5_Period * 1us
11531 MOV #14,W                       \ count of loop
11532 BEGIN                           \
11533 \ ******************************\
11534 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
11535 \ ******************************\                   |
11536 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
11537 \ RC5_Compute_3/4_Period:       \                   |
11538     RRUM    #1,X                \ X=1/2 cycle       |
11539     MOV     X,Y                 \                   ^
11540     RRUM    #1,Y                \ Y=1/4
11541     ADD     X,Y                 \ Y=3/4 cycle
11542     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
11543     U>= UNTIL                   \ 2
11544 \ ******************************\
11545 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
11546 \ ******************************\
11547     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
11548     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
11549     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
11550     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
11551     SUB     #1,W                \ decrement count loop
11552 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
11553 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
11554 0<> WHILE                       \ ----> out of loop ----+
11555     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
11556     BEGIN                       \                       |
11557         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
11558         CMP Y,X                 \ 1                     |   cycle time out of bound ?
11559         U>= IF                  \ 2                 ^   |   yes:
11560         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
11561         GOTO BW1                \                   |   |      quit on truncated RC5 message
11562         THEN                    \                   |   |
11563         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
11564     0<> UNTIL                   \ 2                 |   |
11565 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
11566 \ ******************************\                       |
11567 \ RC5_SampleEndOf:              \ <---------------------+
11568 \ ******************************\
11569 BIC #$30,&RC5_TIM_CTL           \   stop timer
11570 \ ******************************\
11571 \ RC5_ComputeNewRC5word         \
11572 \ ******************************\
11573 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
11574 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
11575 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
11576 \ ******************************\
11577 \ RC5_ComputeC6bit              \
11578 \ ******************************\
11579 BIT     #BIT14,T                \ test /C6 bit in T
11580 0= IF   BIS #BIT6,X             \ set C6 bit in X
11581 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
11582 \ ******************************\
11583 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
11584 \ ******************************\
11585 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
11586 \ ******************************\
11587 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
11588 XOR     @RSP,T                  \ (new XOR old) Toggle bits
11589 BIT     #UF10,T                 \ repeated RC5_command ?
11590 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
11591 XOR #UF10,0(RSP)                \ 5 toggle bit memory
11592 \ ******************************\
11593 \ Display IR_RC5 code           \
11594 \ ******************************\
11595 SUB #8,PSP                      \ TOS -- x x x x TOS
11596 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
11597 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
11598 MOV #$10,&BASEADR               \                                               set hexadecimal base
11599 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
11600 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
11601 LO2HI                           \                                               switch from assembler to FORTH
11602     LCD_CLEAR                   \                                               set LCD cursor at home
11603     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
11604     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
11605     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
11606     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
11607 HI2LO                           \     --                                        switch from FORTH to assembler
11608 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
11609 MOV @PSP+,TOS                   \     -- TOS
11610 RET
11611 ENDASM
11612
11613 \ ******************************\
11614 ASM BACKGROUND                  \
11615 \ ******************************\
11616 BEGIN
11617 \     ...                         \ insert here your background task
11618 \     ...                         \
11619 \     ...                         \
11620     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
11621     BIS &LPM_MODE,SR            \
11622 \ ******************************\
11623 \ here start all interrupts     \
11624 \ ******************************\
11625 \ here return all interrupts    \
11626 \ ******************************\
11627 AGAIN                           \
11628 ENDASM                          \
11629 \ ******************************\
11630
11631 \ ------------------------------\
11632 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
11633 \ ------------------------------\
11634 \     ...                         \ init specific I/O sys as you want
11635 \     ...                         \ before executing default WARM
11636     MOV #WARM,X                 \ ['] WARM 
11637     ADD #4,X                    \ >BODY
11638     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
11639 ENDASM
11640 \ ------------------------------\
11641
11642 \ ------------------------------\
11643 CODE STOP                       \ stops multitasking, must to be used before downloading app
11644 \ ------------------------------\
11645 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
11646     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
11647     MOV X,-2(X)                 \ restore the default background: SLEEP
11648     MOV #WARM,X
11649     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
11650     BIC.B #RC5,&IR_IE           \ clear RC5_Int
11651     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
11652     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
11653     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
11654     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
11655     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
11656 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
11657 ECHO                            \
11658 ." RC5toLCD is removed,"
11659 ."  type START to restart"
11660  WARM                           \ performs reset to reset all interrupt vectors.    
11661 ;
11662 \ ------------------------------\
11663
11664 \ ------------------------------\
11665 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
11666 \ ------------------------------\
11667 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
11668 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
11669 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
11670 \                           --       \ID input divider \ 10 = /4
11671 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
11672 \                                 -  \TBCLR TimerB Clear
11673 \                                  - \TBIE
11674 \                                   -\TBIFG
11675 \ -------------------------------\
11676 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
11677 \                  --                 \CM Capture Mode
11678 \                    --               \CCIS
11679 \                       -             \SCS
11680 \                        --           \CLLD
11681 \                          -          \CAP
11682 \                            ---      \OUTMOD \ 011 = set/reset
11683 \                               -     \CCIE
11684 \                                 -   \CCI
11685 \                                  -  \OUT
11686 \                                   - \COV
11687 \                                    -\CCIFG
11688 \ -------------------------------\
11689 \ LCD_TIM_CCRx                   \
11690 \ -------------------------------\
11691 \ LCD_TIM_EX0                    \ 
11692 \ ------------------------------\
11693 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
11694 \ ------------------------------\
11695 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
11696 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
11697 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
11698     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
11699 [THEN]
11700 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
11701     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
11702 [THEN]
11703     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
11704 \ ------------------------------\
11705 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
11706 \ ------------------------------\
11707 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
11708     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
11709 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
11710 \ ------------------------------\
11711     BIS.B #LCDVo,&LCDVo_DIR     \
11712     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
11713 \ ------------------------------\
11714     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
11715     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
11716 \ ------------------------------\
11717     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
11718     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
11719 \ ******************************\
11720 \ init RC5_Int                  \
11721 \ ******************************\
11722     BIS.B #RC5,&IR_IE           \ enable RC5_Int
11723     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
11724     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
11725 \ ******************************\
11726 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
11727 \ ******************************\
11728 \              %01 0001 0100    \ TAxCTL
11729 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
11730 \                  --           \ ID        divided by 1
11731 \                    --         \ MC        MODE = up to TAxCCRn
11732 \                        -      \ TACLR     clear timer count
11733 \                         -     \ TAIE
11734 \                          -    \ TAIFG
11735 \ ------------------------------\
11736 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
11737 \ ------------------------------\
11738 \                        000    \ TAxEX0
11739 \                        ---    \ TAIDEX    pre divisor
11740 \ ------------------------------\
11741 \          %0000 0000 0000 0101 \ TAxCCR0
11742     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
11743 \ ------------------------------\
11744 \          %0000 0000 0001 0000 \ TAxCCTL0
11745 \                   -           \ CAP capture/compare mode = compare
11746 \                        -      \ CCIEn
11747 \                             - \ CCIFGn
11748     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
11749 \ ------------------------------\
11750     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
11751 \ ------------------------------\
11752 \ define LPM mode for ACCEPT    \
11753 \ ------------------------------\
11754 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
11755 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
11756 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
11757 \ ------------------------------\
11758 \ activate I/O                  \
11759 \ ------------------------------\
11760 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
11761 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
11762 \ ------------------------------\
11763 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
11764 \ ------------------------------\
11765 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
11766 \ CMP #2,Y                        \ Power_ON event
11767 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
11768 CMP #4,Y                        \
11769 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
11770 \ CMP #6,Y                        \
11771 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
11772 \ CMP #$0A,Y                      \
11773 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
11774 \ CMP #$16,Y                      \
11775 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
11776 \ ------------------------------\
11777 COLON                           \
11778 \ ------------------------------\
11779 \ Init LCD 2x20                 \
11780 \ ------------------------------\
11781     #1000 20_US                 \ 1- wait 20 ms
11782     %011 TOP_LCD                \ 2- send DB5=DB4=1
11783     #205 20_US                  \ 3- wait 4,1 ms
11784     %011 TOP_LCD                \ 4- send again DB5=DB4=1
11785     #5 20_US                    \ 5- wait 0,1 ms
11786     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
11787     #2 20_US                    \    wait 40 us = LCD cycle
11788     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
11789     #2 20_US                    \    wait 40 us = LCD cycle
11790     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
11791     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
11792     LCD_CLEAR                   \ 10- "LCD_Clear"
11793     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
11794     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
11795     LCD_CLEAR                   \ 10- "LCD_Clear"
11796     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
11797     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
11798     CR ." I love you"           \ display message on LCD
11799     ['] CR >BODY IS CR          \ CR executes its default value
11800     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
11801     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
11802     PWR_STATE ABORT             \ init DP and continues with ABORT
11803 ;                               \
11804 \ ------------------------------\
11805
11806 \ ------------------------------\
11807 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
11808 \ ------------------------------\
11809 MOV #SLEEP,X                    \ replace default background process SLEEP
11810 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
11811 MOV #WARM,X                     \ replace default WARM
11812 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
11813 MOV X,PC                        \ then execute new WARM
11814 ENDCODE 
11815 \ ------------------------------\
11816
11817 ECHO
11818             ; downloading RC5toLCD.4th is done
11819 RST_HERE    ; this app is protected against <reset>
11820
11821
11822 RST_STATE
11823
11824 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
11825
11826 [UNDEFINED] MARKER [IF]
11827 \  https://forth-standard.org/standard/core/MARKER
11828 \  MARKER
11829 \ ( "<spaces>name" -- )
11830 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
11831 \ with the execution semantics defined below.
11832
11833 \ name Execution: ( -- )
11834 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
11835 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
11836 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
11837 \ not necessarily provided. No other contextual information such as numeric base is affected
11838 \
11839 : MARKER
11840 CREATE
11841 HI2LO
11842 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
11843 SUB #2,Y            \ 1 Y = LFA
11844 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
11845 ADD #4,&DP          \ 3 add 2 cells
11846 LO2HI
11847 DOES>
11848 HI2LO
11849 MOV @RSP+,IP        \ -- PFA
11850 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
11851 MOV @TOS,&INIDP     \       set DP value for RST_STATE
11852 MOV @PSP+,TOS       \ --
11853 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
11854 ENDCODE
11855 [THEN]
11856
11857 MARKER {RC5TOLCD}
11858
11859 [UNDEFINED] @ [IF]
11860 \ https://forth-standard.org/standard/core/Fetch
11861 \ @     c-addr -- char   fetch char from memory
11862 CODE @
11863 MOV @TOS,TOS
11864 MOV @IP+,PC
11865 ENDCODE
11866 [THEN]
11867
11868 [UNDEFINED] CONSTANT [IF]
11869 \ https://forth-standard.org/standard/core/CONSTANT
11870 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
11871 : CONSTANT 
11872 CREATE
11873 HI2LO
11874 MOV TOS,-2(W)           \   PFA = n
11875 MOV @PSP+,TOS
11876 MOV @RSP+,IP
11877 MOV @IP+,PC
11878 ENDCODE
11879 [THEN]
11880
11881 [UNDEFINED] STATE [IF]
11882 \ https://forth-standard.org/standard/core/STATE
11883 \ STATE   -- a-addr       holds compiler state
11884 STATEADR CONSTANT STATE
11885 [THEN]
11886
11887 [UNDEFINED] = [IF]
11888 \ https://forth-standard.org/standard/core/Equal
11889 \ =      x1 x2 -- flag         test x1=x2
11890 CODE =
11891 SUB @PSP+,TOS   \ 2
11892 0<> IF          \ 2
11893     AND #0,TOS  \ 1
11894     MOV @IP+,PC \ 4
11895 THEN
11896 XOR #-1,TOS     \ 1 flag Z = 1
11897 MOV @IP+,PC     \ 4
11898 ENDCODE
11899 [THEN]
11900
11901 [UNDEFINED] IF [IF]
11902 \ https://forth-standard.org/standard/core/IF
11903 \ IF       -- IFadr    initialize conditional forward branch
11904 CODE IF       \ immediate
11905 SUB #2,PSP              \
11906 MOV TOS,0(PSP)          \
11907 MOV &DP,TOS             \ -- HERE
11908 ADD #4,&DP            \           compile one word, reserve one word
11909 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
11910 ADD #2,TOS              \ -- HERE+2=IFadr
11911 MOV @IP+,PC
11912 ENDCODE IMMEDIATE
11913 [THEN]
11914
11915 [UNDEFINED] THEN [IF]
11916 \ https://forth-standard.org/standard/core/THEN
11917 \ THEN     IFadr --                resolve forward branch
11918 CODE THEN               \ immediate
11919 MOV &DP,0(TOS)          \ -- IFadr
11920 MOV @PSP+,TOS           \ --
11921 MOV @IP+,PC
11922 ENDCODE IMMEDIATE
11923 [THEN]
11924
11925 [UNDEFINED] ELSE [IF]
11926 \ https://forth-standard.org/standard/core/ELSE
11927 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
11928 CODE ELSE     \ immediate
11929 ADD #4,&DP              \ make room to compile two words
11930 MOV &DP,W               \ W=HERE+4
11931 MOV #BRAN,-4(W)
11932 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
11933 SUB #2,W                \ HERE+2
11934 MOV W,TOS               \ -- ELSEadr
11935 MOV @IP+,PC
11936 ENDCODE IMMEDIATE
11937 [THEN]
11938
11939 [UNDEFINED] DEFER [IF]
11940 \ https://forth-standard.org/standard/core/DEFER
11941 \ DEFER "<spaces>name"   --
11942 \ Skip leading space delimiters. Parse name delimited by a space.
11943 \ Create a definition for name with the execution semantics defined below.
11944
11945 \ name Execution:   --
11946 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
11947 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
11948 : DEFER
11949 CREATE
11950 HI2LO
11951 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
11952 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
11953 MOV @RSP+,IP
11954 MOV @IP+,PC
11955 ENDCODE
11956 [THEN]
11957
11958 [UNDEFINED] DEFER! [IF]
11959 \ https://forth-standard.org/standard/core/DEFERStore
11960 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
11961 CODE DEFER!             \ xt2 xt1 --
11962 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
11963 MOV @PSP+,TOS           \ --
11964 MOV @IP+,PC
11965 ENDCODE
11966 [THEN]
11967
11968 [UNDEFINED] IS [IF]
11969 \ https://forth-standard.org/standard/core/IS
11970 \ IS <name>        xt --
11971 \ used as is :
11972 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
11973 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
11974 \ or in a definition : ... ['] U. IS DISPLAY ...
11975 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
11976 \
11977 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
11978 : IS
11979 STATE @
11980 IF  POSTPONE ['] POSTPONE DEFER! 
11981 ELSE ' DEFER! 
11982 THEN
11983 ; IMMEDIATE
11984 [THEN]
11985
11986 [UNDEFINED] >BODY [IF]
11987 \ https://forth-standard.org/standard/core/toBODY
11988 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
11989 CODE >BODY
11990 ADD #4,TOS
11991 MOV @IP+,PC
11992 ENDCODE
11993 [THEN]
11994
11995 \ CODE 20uS           \ n --      8MHz version
11996 \ BEGIN               \ 4 + 16 ~ loop
11997 \     MOV #39,rDOCON   \ 39
11998 \     BEGIN           \ 4 ~ loop
11999 \         NOP
12000 \         SUB #1,rDOCON
12001 \     0=  UNTIL
12002 \     SUB #1,TOS      \ 1
12003 \ 0= UNTIL
12004 \ MOV #XDOCON,rDOCON  \ 2
12005 \ MOV @PSP+,TOS
12006 \ MOV @RSP+,IP        \
12007 \ ENDCODE
12008
12009 CODE 20_US                      \ n --      n * 20 us
12010 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
12011     BEGIN
12012         BIT #1,&LCD_TIM_CTL     \ 3
12013     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
12014     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
12015     SUB #1,TOS                  \ 1
12016 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
12017 MOV @PSP+,TOS                   \ 2
12018 MOV @IP+,PC                     \ 4
12019 ENDCODE
12020
12021 CODE TOP_LCD                    \ LCD Sample
12022 \                               \ if write : %xxxx_WWWW --
12023 \                               \ if read  : -- %0000_RRRR
12024     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
12025     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
12026 0= IF                           \ write LCD bits pattern
12027     AND.B #LCD_DB,TOS           \ 
12028     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
12029     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
12030     MOV @PSP+,TOS               \
12031     MOV @IP+,PC
12032 THEN                            \ read LCD bits pattern
12033     SUB #2,PSP
12034     MOV TOS,0(PSP)
12035     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
12036     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
12037     AND.B #LCD_DB,TOS           \
12038     MOV @IP+,PC
12039 ENDCODE
12040
12041 CODE LCD_WRC                    \ char --         Write Char
12042     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
12043 BW1 SUB #2,PSP                  \
12044     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
12045     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
12046     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
12047     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
12048 COLON                           \ high level word starts here 
12049     TOP_LCD 2 20_US             \ write high nibble first
12050     TOP_LCD 2 20_US 
12051 ;
12052
12053 CODE LCD_WRF                    \ func --         Write Fonction
12054     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
12055     GOTO BW1
12056 ENDCODE
12057
12058 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
12059 : LCD_HOME $02 LCD_WRF 100 20_us ;
12060
12061 \ [UNDEFINED] OR [IF]
12062
12063 \ \ https://forth-standard.org/standard/core/OR
12064 \ \ C OR     x1 x2 -- x3           logical OR
12065 \ CODE OR
12066 \ BIS @PSP+,TOS
12067 \ MOV @IP+,PC
12068 \ ENDCODE
12069
12070 \ [THEN]
12071
12072 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
12073 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
12074 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
12075 \ : LCD_FN_SET        $20 OR LCD_WrF ;
12076 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
12077 \ : LCD_GOTO          $80 OR LCD_WrF ;
12078
12079
12080 \ CODE LCD_RDS                    \ -- status       Read Status
12081 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
12082 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
12083 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
12084 \ COLON                           \ starts a FORTH word
12085 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
12086 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
12087 \ HI2LO                           \ switch from FORTH to assembler
12088 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
12089 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
12090 \     MOV @RSP+,IP                \ restore IP saved by COLON
12091 \     MOV @IP+,PC                 \
12092 \ ENDCODE
12093
12094 \ CODE LCD_RDC                    \ -- char         Read Char
12095 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
12096 \     GOTO BW1
12097 \ ENDCODE
12098
12099
12100 \ ******************************\
12101 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
12102 \ ******************************\
12103 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
12104 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
12105 BIT.B #SW2,&SW2_IN              \ test switch S2
12106 0= IF                           \ case of switch S2 pressed
12107     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
12108     U< IF
12109         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
12110     THEN
12111 ELSE
12112     BIT.B #SW1,&SW1_IN          \ test switch S1 input
12113     0= IF                       \ case of Switch S1 pressed
12114         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
12115         U>= IF                  \
12116            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
12117         THEN                    \
12118     THEN                        \
12119 THEN                            \
12120 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
12121 RET                             \ 5
12122 ENDASM
12123
12124 \ ******************************\
12125 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
12126 \ ******************************\
12127 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
12128 \ ******************************\
12129 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
12130 \                               \       SMclock = 8|16|24 MHz
12131 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
12132 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
12133 \                               \       SR(9)=new Toggle bit memory (ADD on)
12134 \ ******************************\
12135 \ RC5_FirstStartBitHalfCycle:   \
12136 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
12137 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
12138 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
12139 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
12140 \ [THEN]
12141 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
12142     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
12143 [THEN]
12144 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
12145     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
12146 [THEN]
12147 MOV #1778,X                     \ RC5_Period * 1us
12148 MOV #14,W                       \ count of loop
12149 BEGIN                           \
12150 \ ******************************\
12151 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
12152 \ ******************************\                   |
12153 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
12154 \ RC5_Compute_3/4_Period:       \                   |
12155     RRUM    #1,X                \ X=1/2 cycle       |
12156     MOV     X,Y                 \                   ^
12157     RRUM    #1,Y                \ Y=1/4
12158     ADD     X,Y                 \ Y=3/4 cycle
12159     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
12160     U>= UNTIL                   \ 2
12161 \ ******************************\
12162 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
12163 \ ******************************\
12164     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
12165     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
12166     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
12167     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
12168     SUB     #1,W                \ decrement count loop
12169 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
12170 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
12171 0<> WHILE                       \ ----> out of loop ----+
12172     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
12173     BEGIN                       \                       |
12174         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
12175         CMP Y,X                 \ 1                     |   cycle time out of bound ?
12176         U>= IF                  \ 2                 ^   |   yes:
12177         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
12178         GOTO BW1                \                   |   |      quit on truncated RC5 message
12179         THEN                    \                   |   |
12180         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
12181     0<> UNTIL                   \ 2                 |   |
12182 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
12183 \ ******************************\                       |
12184 \ RC5_SampleEndOf:              \ <---------------------+
12185 \ ******************************\
12186 BIC #$30,&RC5_TIM_CTL           \   stop timer
12187 \ ******************************\
12188 \ RC5_ComputeNewRC5word         \
12189 \ ******************************\
12190 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
12191 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
12192 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
12193 \ ******************************\
12194 \ RC5_ComputeC6bit              \
12195 \ ******************************\
12196 BIT     #BIT14,T                \ test /C6 bit in T
12197 0= IF   BIS #BIT6,X             \ set C6 bit in X
12198 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
12199 \ ******************************\
12200 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
12201 \ ******************************\
12202 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
12203 \ ******************************\
12204 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
12205 XOR     @RSP,T                  \ (new XOR old) Toggle bits
12206 BIT     #UF10,T                 \ repeated RC5_command ?
12207 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
12208 XOR #UF10,0(RSP)                \ 5 toggle bit memory
12209 \ ******************************\
12210 \ Display IR_RC5 code           \
12211 \ ******************************\
12212 SUB #8,PSP                      \ TOS -- x x x x TOS
12213 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
12214 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
12215 MOV #$10,&BASEADR               \                                               set hexadecimal base
12216 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
12217 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
12218 LO2HI                           \                                               switch from assembler to FORTH
12219     LCD_CLEAR                   \                                               set LCD cursor at home
12220     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
12221     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
12222     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
12223     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
12224 HI2LO                           \     --                                        switch from FORTH to assembler
12225 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
12226 MOV @PSP+,TOS                   \     -- TOS
12227 RET
12228 ENDASM
12229
12230 \ ******************************\
12231 ASM BACKGROUND                  \
12232 \ ******************************\
12233 BEGIN
12234 \     ...                         \ insert here your background task
12235 \     ...                         \
12236 \     ...                         \
12237     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
12238     BIS &LPM_MODE,SR            \
12239 \ ******************************\
12240 \ here start all interrupts     \
12241 \ ******************************\
12242 \ here return all interrupts    \
12243 \ ******************************\
12244 AGAIN                           \
12245 ENDASM                          \
12246 \ ******************************\
12247
12248 \ ------------------------------\
12249 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
12250 \ ------------------------------\
12251 \     ...                         \ init specific I/O sys as you want
12252 \     ...                         \ before executing default WARM
12253     MOV #WARM,X                 \ ['] WARM 
12254     ADD #4,X                    \ >BODY
12255     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
12256 ENDASM
12257 \ ------------------------------\
12258
12259 \ ------------------------------\
12260 CODE STOP                       \ stops multitasking, must to be used before downloading app
12261 \ ------------------------------\
12262 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
12263     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
12264     MOV X,-2(X)                 \ restore the default background: SLEEP
12265     MOV #WARM,X
12266     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
12267     BIC.B #RC5,&IR_IE           \ clear RC5_Int
12268     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
12269     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
12270     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
12271     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
12272     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
12273 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
12274 ECHO                            \
12275 ." RC5toLCD is removed,"
12276 ."  type START to restart"
12277  WARM                           \ performs reset to reset all interrupt vectors.    
12278 ;
12279 \ ------------------------------\
12280
12281 \ ------------------------------\
12282 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
12283 \ ------------------------------\
12284 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
12285 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
12286 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
12287 \                           --       \ID input divider \ 10 = /4
12288 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
12289 \                                 -  \TBCLR TimerB Clear
12290 \                                  - \TBIE
12291 \                                   -\TBIFG
12292 \ -------------------------------\
12293 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
12294 \                  --                 \CM Capture Mode
12295 \                    --               \CCIS
12296 \                       -             \SCS
12297 \                        --           \CLLD
12298 \                          -          \CAP
12299 \                            ---      \OUTMOD \ 011 = set/reset
12300 \                               -     \CCIE
12301 \                                 -   \CCI
12302 \                                  -  \OUT
12303 \                                   - \COV
12304 \                                    -\CCIFG
12305 \ -------------------------------\
12306 \ LCD_TIM_CCRx                   \
12307 \ -------------------------------\
12308 \ LCD_TIM_EX0                    \ 
12309 \ ------------------------------\
12310 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
12311 \ ------------------------------\
12312 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
12313 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
12314 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
12315     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
12316 [THEN]
12317 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
12318     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
12319 [THEN]
12320     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
12321 \ ------------------------------\
12322 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
12323 \ ------------------------------\
12324 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
12325     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
12326 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
12327 \ ------------------------------\
12328     BIS.B #LCDVo,&LCDVo_DIR     \
12329     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
12330 \ ------------------------------\
12331     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
12332     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
12333 \ ------------------------------\
12334     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
12335     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
12336 \ ******************************\
12337 \ init RC5_Int                  \
12338 \ ******************************\
12339     BIS.B #RC5,&IR_IE           \ enable RC5_Int
12340     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
12341     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
12342 \ ******************************\
12343 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
12344 \ ******************************\
12345 \              %01 0001 0100    \ TAxCTL
12346 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
12347 \                  --           \ ID        divided by 1
12348 \                    --         \ MC        MODE = up to TAxCCRn
12349 \                        -      \ TACLR     clear timer count
12350 \                         -     \ TAIE
12351 \                          -    \ TAIFG
12352 \ ------------------------------\
12353 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
12354 \ ------------------------------\
12355 \                        000    \ TAxEX0
12356 \                        ---    \ TAIDEX    pre divisor
12357 \ ------------------------------\
12358 \          %0000 0000 0000 0101 \ TAxCCR0
12359     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
12360 \ ------------------------------\
12361 \          %0000 0000 0001 0000 \ TAxCCTL0
12362 \                   -           \ CAP capture/compare mode = compare
12363 \                        -      \ CCIEn
12364 \                             - \ CCIFGn
12365     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
12366 \ ------------------------------\
12367     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
12368 \ ------------------------------\
12369 \ define LPM mode for ACCEPT    \
12370 \ ------------------------------\
12371 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
12372 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
12373 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
12374 \ ------------------------------\
12375 \ activate I/O                  \
12376 \ ------------------------------\
12377 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
12378 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
12379 \ ------------------------------\
12380 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
12381 \ ------------------------------\
12382 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
12383 \ CMP #2,Y                        \ Power_ON event
12384 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
12385 CMP #4,Y                        \
12386 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
12387 \ CMP #6,Y                        \
12388 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
12389 \ CMP #$0A,Y                      \
12390 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
12391 \ CMP #$16,Y                      \
12392 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
12393 \ ------------------------------\
12394 COLON                           \
12395 \ ------------------------------\
12396 \ Init LCD 2x20                 \
12397 \ ------------------------------\
12398     #1000 20_US                 \ 1- wait 20 ms
12399     %011 TOP_LCD                \ 2- send DB5=DB4=1
12400     #205 20_US                  \ 3- wait 4,1 ms
12401     %011 TOP_LCD                \ 4- send again DB5=DB4=1
12402     #5 20_US                    \ 5- wait 0,1 ms
12403     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
12404     #2 20_US                    \    wait 40 us = LCD cycle
12405     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
12406     #2 20_US                    \    wait 40 us = LCD cycle
12407     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
12408     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
12409     LCD_CLEAR                   \ 10- "LCD_Clear"
12410     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
12411     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
12412     LCD_CLEAR                   \ 10- "LCD_Clear"
12413     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
12414     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
12415     CR ." I love you"           \ display message on LCD
12416     ['] CR >BODY IS CR          \ CR executes its default value
12417     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
12418     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
12419     PWR_STATE ABORT             \ init DP and continues with ABORT
12420 ;                               \
12421 \ ------------------------------\
12422
12423 \ ------------------------------\
12424 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
12425 \ ------------------------------\
12426 MOV #SLEEP,X                    \ replace default background process SLEEP
12427 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
12428 MOV #WARM,X                     \ replace default WARM
12429 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
12430 MOV X,PC                        \ then execute new WARM
12431 ENDCODE 
12432 \ ------------------------------\
12433
12434 ECHO
12435             ; downloading RC5toLCD.4th is done
12436 RST_HERE    ; this app is protected against <reset>
12437
12438
12439 RST_STATE
12440
12441 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
12442
12443 [UNDEFINED] MARKER [IF]
12444 \  https://forth-standard.org/standard/core/MARKER
12445 \  MARKER
12446 \ ( "<spaces>name" -- )
12447 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
12448 \ with the execution semantics defined below.
12449
12450 \ name Execution: ( -- )
12451 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
12452 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
12453 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
12454 \ not necessarily provided. No other contextual information such as numeric base is affected
12455 \
12456 : MARKER
12457 CREATE
12458 HI2LO
12459 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
12460 SUB #2,Y            \ 1 Y = LFA
12461 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
12462 ADD #4,&DP          \ 3 add 2 cells
12463 LO2HI
12464 DOES>
12465 HI2LO
12466 MOV @RSP+,IP        \ -- PFA
12467 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
12468 MOV @TOS,&INIDP     \       set DP value for RST_STATE
12469 MOV @PSP+,TOS       \ --
12470 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
12471 ENDCODE
12472 [THEN]
12473
12474 MARKER {RC5TOLCD}
12475
12476 [UNDEFINED] @ [IF]
12477 \ https://forth-standard.org/standard/core/Fetch
12478 \ @     c-addr -- char   fetch char from memory
12479 CODE @
12480 MOV @TOS,TOS
12481 MOV @IP+,PC
12482 ENDCODE
12483 [THEN]
12484
12485 [UNDEFINED] CONSTANT [IF]
12486 \ https://forth-standard.org/standard/core/CONSTANT
12487 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
12488 : CONSTANT 
12489 CREATE
12490 HI2LO
12491 MOV TOS,-2(W)           \   PFA = n
12492 MOV @PSP+,TOS
12493 MOV @RSP+,IP
12494 MOV @IP+,PC
12495 ENDCODE
12496 [THEN]
12497
12498 [UNDEFINED] STATE [IF]
12499 \ https://forth-standard.org/standard/core/STATE
12500 \ STATE   -- a-addr       holds compiler state
12501 STATEADR CONSTANT STATE
12502 [THEN]
12503
12504 [UNDEFINED] = [IF]
12505 \ https://forth-standard.org/standard/core/Equal
12506 \ =      x1 x2 -- flag         test x1=x2
12507 CODE =
12508 SUB @PSP+,TOS   \ 2
12509 0<> IF          \ 2
12510     AND #0,TOS  \ 1
12511     MOV @IP+,PC \ 4
12512 THEN
12513 XOR #-1,TOS     \ 1 flag Z = 1
12514 MOV @IP+,PC     \ 4
12515 ENDCODE
12516 [THEN]
12517
12518 [UNDEFINED] IF [IF]
12519 \ https://forth-standard.org/standard/core/IF
12520 \ IF       -- IFadr    initialize conditional forward branch
12521 CODE IF       \ immediate
12522 SUB #2,PSP              \
12523 MOV TOS,0(PSP)          \
12524 MOV &DP,TOS             \ -- HERE
12525 ADD #4,&DP            \           compile one word, reserve one word
12526 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
12527 ADD #2,TOS              \ -- HERE+2=IFadr
12528 MOV @IP+,PC
12529 ENDCODE IMMEDIATE
12530 [THEN]
12531
12532 [UNDEFINED] THEN [IF]
12533 \ https://forth-standard.org/standard/core/THEN
12534 \ THEN     IFadr --                resolve forward branch
12535 CODE THEN               \ immediate
12536 MOV &DP,0(TOS)          \ -- IFadr
12537 MOV @PSP+,TOS           \ --
12538 MOV @IP+,PC
12539 ENDCODE IMMEDIATE
12540 [THEN]
12541
12542 [UNDEFINED] ELSE [IF]
12543 \ https://forth-standard.org/standard/core/ELSE
12544 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
12545 CODE ELSE     \ immediate
12546 ADD #4,&DP              \ make room to compile two words
12547 MOV &DP,W               \ W=HERE+4
12548 MOV #BRAN,-4(W)
12549 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
12550 SUB #2,W                \ HERE+2
12551 MOV W,TOS               \ -- ELSEadr
12552 MOV @IP+,PC
12553 ENDCODE IMMEDIATE
12554 [THEN]
12555
12556 [UNDEFINED] DEFER [IF]
12557 \ https://forth-standard.org/standard/core/DEFER
12558 \ DEFER "<spaces>name"   --
12559 \ Skip leading space delimiters. Parse name delimited by a space.
12560 \ Create a definition for name with the execution semantics defined below.
12561
12562 \ name Execution:   --
12563 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
12564 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
12565 : DEFER
12566 CREATE
12567 HI2LO
12568 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
12569 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
12570 MOV @RSP+,IP
12571 MOV @IP+,PC
12572 ENDCODE
12573 [THEN]
12574
12575 [UNDEFINED] DEFER! [IF]
12576 \ https://forth-standard.org/standard/core/DEFERStore
12577 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
12578 CODE DEFER!             \ xt2 xt1 --
12579 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
12580 MOV @PSP+,TOS           \ --
12581 MOV @IP+,PC
12582 ENDCODE
12583 [THEN]
12584
12585 [UNDEFINED] IS [IF]
12586 \ https://forth-standard.org/standard/core/IS
12587 \ IS <name>        xt --
12588 \ used as is :
12589 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
12590 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
12591 \ or in a definition : ... ['] U. IS DISPLAY ...
12592 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
12593 \
12594 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
12595 : IS
12596 STATE @
12597 IF  POSTPONE ['] POSTPONE DEFER! 
12598 ELSE ' DEFER! 
12599 THEN
12600 ; IMMEDIATE
12601 [THEN]
12602
12603 [UNDEFINED] >BODY [IF]
12604 \ https://forth-standard.org/standard/core/toBODY
12605 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
12606 CODE >BODY
12607 ADD #4,TOS
12608 MOV @IP+,PC
12609 ENDCODE
12610 [THEN]
12611
12612 \ CODE 20uS           \ n --      8MHz version
12613 \ BEGIN               \ 4 + 16 ~ loop
12614 \     MOV #39,rDOCON   \ 39
12615 \     BEGIN           \ 4 ~ loop
12616 \         NOP
12617 \         SUB #1,rDOCON
12618 \     0=  UNTIL
12619 \     SUB #1,TOS      \ 1
12620 \ 0= UNTIL
12621 \ MOV #XDOCON,rDOCON  \ 2
12622 \ MOV @PSP+,TOS
12623 \ MOV @RSP+,IP        \
12624 \ ENDCODE
12625
12626 CODE 20_US                      \ n --      n * 20 us
12627 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
12628     BEGIN
12629         BIT #1,&LCD_TIM_CTL     \ 3
12630     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
12631     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
12632     SUB #1,TOS                  \ 1
12633 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
12634 MOV @PSP+,TOS                   \ 2
12635 MOV @IP+,PC                     \ 4
12636 ENDCODE
12637
12638 CODE TOP_LCD                    \ LCD Sample
12639 \                               \ if write : %xxxx_WWWW --
12640 \                               \ if read  : -- %0000_RRRR
12641     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
12642     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
12643 0= IF                           \ write LCD bits pattern
12644     AND.B #LCD_DB,TOS           \ 
12645     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
12646     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
12647     MOV @PSP+,TOS               \
12648     MOV @IP+,PC
12649 THEN                            \ read LCD bits pattern
12650     SUB #2,PSP
12651     MOV TOS,0(PSP)
12652     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
12653     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
12654     AND.B #LCD_DB,TOS           \
12655     MOV @IP+,PC
12656 ENDCODE
12657
12658 CODE LCD_WRC                    \ char --         Write Char
12659     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
12660 BW1 SUB #2,PSP                  \
12661     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
12662     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
12663     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
12664     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
12665 COLON                           \ high level word starts here 
12666     TOP_LCD 2 20_US             \ write high nibble first
12667     TOP_LCD 2 20_US 
12668 ;
12669
12670 CODE LCD_WRF                    \ func --         Write Fonction
12671     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
12672     GOTO BW1
12673 ENDCODE
12674
12675 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
12676 : LCD_HOME $02 LCD_WRF 100 20_us ;
12677
12678 \ [UNDEFINED] OR [IF]
12679
12680 \ \ https://forth-standard.org/standard/core/OR
12681 \ \ C OR     x1 x2 -- x3           logical OR
12682 \ CODE OR
12683 \ BIS @PSP+,TOS
12684 \ MOV @IP+,PC
12685 \ ENDCODE
12686
12687 \ [THEN]
12688
12689 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
12690 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
12691 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
12692 \ : LCD_FN_SET        $20 OR LCD_WrF ;
12693 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
12694 \ : LCD_GOTO          $80 OR LCD_WrF ;
12695
12696
12697 \ CODE LCD_RDS                    \ -- status       Read Status
12698 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
12699 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
12700 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
12701 \ COLON                           \ starts a FORTH word
12702 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
12703 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
12704 \ HI2LO                           \ switch from FORTH to assembler
12705 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
12706 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
12707 \     MOV @RSP+,IP                \ restore IP saved by COLON
12708 \     MOV @IP+,PC                 \
12709 \ ENDCODE
12710
12711 \ CODE LCD_RDC                    \ -- char         Read Char
12712 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
12713 \     GOTO BW1
12714 \ ENDCODE
12715
12716
12717 \ ******************************\
12718 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
12719 \ ******************************\
12720 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
12721 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
12722 BIT.B #SW2,&SW2_IN              \ test switch S2
12723 0= IF                           \ case of switch S2 pressed
12724     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
12725     U< IF
12726         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
12727     THEN
12728 ELSE
12729     BIT.B #SW1,&SW1_IN          \ test switch S1 input
12730     0= IF                       \ case of Switch S1 pressed
12731         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
12732         U>= IF                  \
12733            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
12734         THEN                    \
12735     THEN                        \
12736 THEN                            \
12737 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
12738 RET                             \ 5
12739 ENDASM
12740
12741 \ ******************************\
12742 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
12743 \ ******************************\
12744 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
12745 \ ******************************\
12746 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
12747 \                               \       SMclock = 8|16|24 MHz
12748 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
12749 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
12750 \                               \       SR(9)=new Toggle bit memory (ADD on)
12751 \ ******************************\
12752 \ RC5_FirstStartBitHalfCycle:   \
12753 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
12754 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
12755 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
12756 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
12757 \ [THEN]
12758 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
12759     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
12760 [THEN]
12761 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
12762     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
12763 [THEN]
12764 MOV #1778,X                     \ RC5_Period * 1us
12765 MOV #14,W                       \ count of loop
12766 BEGIN                           \
12767 \ ******************************\
12768 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
12769 \ ******************************\                   |
12770 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
12771 \ RC5_Compute_3/4_Period:       \                   |
12772     RRUM    #1,X                \ X=1/2 cycle       |
12773     MOV     X,Y                 \                   ^
12774     RRUM    #1,Y                \ Y=1/4
12775     ADD     X,Y                 \ Y=3/4 cycle
12776     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
12777     U>= UNTIL                   \ 2
12778 \ ******************************\
12779 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
12780 \ ******************************\
12781     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
12782     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
12783     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
12784     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
12785     SUB     #1,W                \ decrement count loop
12786 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
12787 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
12788 0<> WHILE                       \ ----> out of loop ----+
12789     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
12790     BEGIN                       \                       |
12791         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
12792         CMP Y,X                 \ 1                     |   cycle time out of bound ?
12793         U>= IF                  \ 2                 ^   |   yes:
12794         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
12795         GOTO BW1                \                   |   |      quit on truncated RC5 message
12796         THEN                    \                   |   |
12797         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
12798     0<> UNTIL                   \ 2                 |   |
12799 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
12800 \ ******************************\                       |
12801 \ RC5_SampleEndOf:              \ <---------------------+
12802 \ ******************************\
12803 BIC #$30,&RC5_TIM_CTL           \   stop timer
12804 \ ******************************\
12805 \ RC5_ComputeNewRC5word         \
12806 \ ******************************\
12807 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
12808 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
12809 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
12810 \ ******************************\
12811 \ RC5_ComputeC6bit              \
12812 \ ******************************\
12813 BIT     #BIT14,T                \ test /C6 bit in T
12814 0= IF   BIS #BIT6,X             \ set C6 bit in X
12815 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
12816 \ ******************************\
12817 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
12818 \ ******************************\
12819 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
12820 \ ******************************\
12821 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
12822 XOR     @RSP,T                  \ (new XOR old) Toggle bits
12823 BIT     #UF10,T                 \ repeated RC5_command ?
12824 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
12825 XOR #UF10,0(RSP)                \ 5 toggle bit memory
12826 \ ******************************\
12827 \ Display IR_RC5 code           \
12828 \ ******************************\
12829 SUB #8,PSP                      \ TOS -- x x x x TOS
12830 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
12831 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
12832 MOV #$10,&BASEADR               \                                               set hexadecimal base
12833 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
12834 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
12835 LO2HI                           \                                               switch from assembler to FORTH
12836     LCD_CLEAR                   \                                               set LCD cursor at home
12837     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
12838     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
12839     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
12840     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
12841 HI2LO                           \     --                                        switch from FORTH to assembler
12842 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
12843 MOV @PSP+,TOS                   \     -- TOS
12844 RET
12845 ENDASM
12846
12847 \ ******************************\
12848 ASM BACKGROUND                  \
12849 \ ******************************\
12850 BEGIN
12851 \     ...                         \ insert here your background task
12852 \     ...                         \
12853 \     ...                         \
12854     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
12855     BIS &LPM_MODE,SR            \
12856 \ ******************************\
12857 \ here start all interrupts     \
12858 \ ******************************\
12859 \ here return all interrupts    \
12860 \ ******************************\
12861 AGAIN                           \
12862 ENDASM                          \
12863 \ ******************************\
12864
12865 \ ------------------------------\
12866 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
12867 \ ------------------------------\
12868 \     ...                         \ init specific I/O sys as you want
12869 \     ...                         \ before executing default WARM
12870     MOV #WARM,X                 \ ['] WARM 
12871     ADD #4,X                    \ >BODY
12872     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
12873 ENDASM
12874 \ ------------------------------\
12875
12876 \ ------------------------------\
12877 CODE STOP                       \ stops multitasking, must to be used before downloading app
12878 \ ------------------------------\
12879 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
12880     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
12881     MOV X,-2(X)                 \ restore the default background: SLEEP
12882     MOV #WARM,X
12883     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
12884     BIC.B #RC5,&IR_IE           \ clear RC5_Int
12885     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
12886     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
12887     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
12888     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
12889     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
12890 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
12891 ECHO                            \
12892 ." RC5toLCD is removed,"
12893 ."  type START to restart"
12894  WARM                           \ performs reset to reset all interrupt vectors.    
12895 ;
12896 \ ------------------------------\
12897
12898 \ ------------------------------\
12899 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
12900 \ ------------------------------\
12901 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
12902 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
12903 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
12904 \                           --       \ID input divider \ 10 = /4
12905 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
12906 \                                 -  \TBCLR TimerB Clear
12907 \                                  - \TBIE
12908 \                                   -\TBIFG
12909 \ -------------------------------\
12910 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
12911 \                  --                 \CM Capture Mode
12912 \                    --               \CCIS
12913 \                       -             \SCS
12914 \                        --           \CLLD
12915 \                          -          \CAP
12916 \                            ---      \OUTMOD \ 011 = set/reset
12917 \                               -     \CCIE
12918 \                                 -   \CCI
12919 \                                  -  \OUT
12920 \                                   - \COV
12921 \                                    -\CCIFG
12922 \ -------------------------------\
12923 \ LCD_TIM_CCRx                   \
12924 \ -------------------------------\
12925 \ LCD_TIM_EX0                    \ 
12926 \ ------------------------------\
12927 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
12928 \ ------------------------------\
12929 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
12930 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
12931 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
12932     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
12933 [THEN]
12934 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
12935     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
12936 [THEN]
12937     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
12938 \ ------------------------------\
12939 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
12940 \ ------------------------------\
12941 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
12942     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
12943 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
12944 \ ------------------------------\
12945     BIS.B #LCDVo,&LCDVo_DIR     \
12946     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
12947 \ ------------------------------\
12948     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
12949     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
12950 \ ------------------------------\
12951     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
12952     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
12953 \ ******************************\
12954 \ init RC5_Int                  \
12955 \ ******************************\
12956     BIS.B #RC5,&IR_IE           \ enable RC5_Int
12957     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
12958     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
12959 \ ******************************\
12960 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
12961 \ ******************************\
12962 \              %01 0001 0100    \ TAxCTL
12963 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
12964 \                  --           \ ID        divided by 1
12965 \                    --         \ MC        MODE = up to TAxCCRn
12966 \                        -      \ TACLR     clear timer count
12967 \                         -     \ TAIE
12968 \                          -    \ TAIFG
12969 \ ------------------------------\
12970 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
12971 \ ------------------------------\
12972 \                        000    \ TAxEX0
12973 \                        ---    \ TAIDEX    pre divisor
12974 \ ------------------------------\
12975 \          %0000 0000 0000 0101 \ TAxCCR0
12976     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
12977 \ ------------------------------\
12978 \          %0000 0000 0001 0000 \ TAxCCTL0
12979 \                   -           \ CAP capture/compare mode = compare
12980 \                        -      \ CCIEn
12981 \                             - \ CCIFGn
12982     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
12983 \ ------------------------------\
12984     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
12985 \ ------------------------------\
12986 \ define LPM mode for ACCEPT    \
12987 \ ------------------------------\
12988 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
12989 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
12990 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
12991 \ ------------------------------\
12992 \ activate I/O                  \
12993 \ ------------------------------\
12994 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
12995 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
12996 \ ------------------------------\
12997 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
12998 \ ------------------------------\
12999 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
13000 \ CMP #2,Y                        \ Power_ON event
13001 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
13002 CMP #4,Y                        \
13003 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
13004 \ CMP #6,Y                        \
13005 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
13006 \ CMP #$0A,Y                      \
13007 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
13008 \ CMP #$16,Y                      \
13009 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
13010 \ ------------------------------\
13011 COLON                           \
13012 \ ------------------------------\
13013 \ Init LCD 2x20                 \
13014 \ ------------------------------\
13015     #1000 20_US                 \ 1- wait 20 ms
13016     %011 TOP_LCD                \ 2- send DB5=DB4=1
13017     #205 20_US                  \ 3- wait 4,1 ms
13018     %011 TOP_LCD                \ 4- send again DB5=DB4=1
13019     #5 20_US                    \ 5- wait 0,1 ms
13020     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
13021     #2 20_US                    \    wait 40 us = LCD cycle
13022     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
13023     #2 20_US                    \    wait 40 us = LCD cycle
13024     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
13025     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
13026     LCD_CLEAR                   \ 10- "LCD_Clear"
13027     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
13028     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
13029     LCD_CLEAR                   \ 10- "LCD_Clear"
13030     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
13031     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
13032     CR ." I love you"           \ display message on LCD
13033     ['] CR >BODY IS CR          \ CR executes its default value
13034     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
13035     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
13036     PWR_STATE ABORT             \ init DP and continues with ABORT
13037 ;                               \
13038 \ ------------------------------\
13039
13040 \ ------------------------------\
13041 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
13042 \ ------------------------------\
13043 MOV #SLEEP,X                    \ replace default background process SLEEP
13044 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
13045 MOV #WARM,X                     \ replace default WARM
13046 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
13047 MOV X,PC                        \ then execute new WARM
13048 ENDCODE 
13049 \ ------------------------------\
13050
13051 ECHO
13052             ; downloading RC5toLCD.4th is done
13053 RST_HERE    ; this app is protected against <reset>
13054
13055
13056 RST_STATE
13057
13058 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
13059
13060 [UNDEFINED] MARKER [IF]
13061 \  https://forth-standard.org/standard/core/MARKER
13062 \  MARKER
13063 \ ( "<spaces>name" -- )
13064 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
13065 \ with the execution semantics defined below.
13066
13067 \ name Execution: ( -- )
13068 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
13069 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
13070 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
13071 \ not necessarily provided. No other contextual information such as numeric base is affected
13072 \
13073 : MARKER
13074 CREATE
13075 HI2LO
13076 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
13077 SUB #2,Y            \ 1 Y = LFA
13078 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
13079 ADD #4,&DP          \ 3 add 2 cells
13080 LO2HI
13081 DOES>
13082 HI2LO
13083 MOV @RSP+,IP        \ -- PFA
13084 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
13085 MOV @TOS,&INIDP     \       set DP value for RST_STATE
13086 MOV @PSP+,TOS       \ --
13087 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
13088 ENDCODE
13089 [THEN]
13090
13091 MARKER {RC5TOLCD}
13092
13093 [UNDEFINED] @ [IF]
13094 \ https://forth-standard.org/standard/core/Fetch
13095 \ @     c-addr -- char   fetch char from memory
13096 CODE @
13097 MOV @TOS,TOS
13098 MOV @IP+,PC
13099 ENDCODE
13100 [THEN]
13101
13102 [UNDEFINED] CONSTANT [IF]
13103 \ https://forth-standard.org/standard/core/CONSTANT
13104 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
13105 : CONSTANT 
13106 CREATE
13107 HI2LO
13108 MOV TOS,-2(W)           \   PFA = n
13109 MOV @PSP+,TOS
13110 MOV @RSP+,IP
13111 MOV @IP+,PC
13112 ENDCODE
13113 [THEN]
13114
13115 [UNDEFINED] STATE [IF]
13116 \ https://forth-standard.org/standard/core/STATE
13117 \ STATE   -- a-addr       holds compiler state
13118 STATEADR CONSTANT STATE
13119 [THEN]
13120
13121 [UNDEFINED] = [IF]
13122 \ https://forth-standard.org/standard/core/Equal
13123 \ =      x1 x2 -- flag         test x1=x2
13124 CODE =
13125 SUB @PSP+,TOS   \ 2
13126 0<> IF          \ 2
13127     AND #0,TOS  \ 1
13128     MOV @IP+,PC \ 4
13129 THEN
13130 XOR #-1,TOS     \ 1 flag Z = 1
13131 MOV @IP+,PC     \ 4
13132 ENDCODE
13133 [THEN]
13134
13135 [UNDEFINED] IF [IF]
13136 \ https://forth-standard.org/standard/core/IF
13137 \ IF       -- IFadr    initialize conditional forward branch
13138 CODE IF       \ immediate
13139 SUB #2,PSP              \
13140 MOV TOS,0(PSP)          \
13141 MOV &DP,TOS             \ -- HERE
13142 ADD #4,&DP            \           compile one word, reserve one word
13143 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
13144 ADD #2,TOS              \ -- HERE+2=IFadr
13145 MOV @IP+,PC
13146 ENDCODE IMMEDIATE
13147 [THEN]
13148
13149 [UNDEFINED] THEN [IF]
13150 \ https://forth-standard.org/standard/core/THEN
13151 \ THEN     IFadr --                resolve forward branch
13152 CODE THEN               \ immediate
13153 MOV &DP,0(TOS)          \ -- IFadr
13154 MOV @PSP+,TOS           \ --
13155 MOV @IP+,PC
13156 ENDCODE IMMEDIATE
13157 [THEN]
13158
13159 [UNDEFINED] ELSE [IF]
13160 \ https://forth-standard.org/standard/core/ELSE
13161 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
13162 CODE ELSE     \ immediate
13163 ADD #4,&DP              \ make room to compile two words
13164 MOV &DP,W               \ W=HERE+4
13165 MOV #BRAN,-4(W)
13166 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
13167 SUB #2,W                \ HERE+2
13168 MOV W,TOS               \ -- ELSEadr
13169 MOV @IP+,PC
13170 ENDCODE IMMEDIATE
13171 [THEN]
13172
13173 [UNDEFINED] DEFER [IF]
13174 \ https://forth-standard.org/standard/core/DEFER
13175 \ DEFER "<spaces>name"   --
13176 \ Skip leading space delimiters. Parse name delimited by a space.
13177 \ Create a definition for name with the execution semantics defined below.
13178
13179 \ name Execution:   --
13180 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
13181 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
13182 : DEFER
13183 CREATE
13184 HI2LO
13185 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
13186 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
13187 MOV @RSP+,IP
13188 MOV @IP+,PC
13189 ENDCODE
13190 [THEN]
13191
13192 [UNDEFINED] DEFER! [IF]
13193 \ https://forth-standard.org/standard/core/DEFERStore
13194 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
13195 CODE DEFER!             \ xt2 xt1 --
13196 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
13197 MOV @PSP+,TOS           \ --
13198 MOV @IP+,PC
13199 ENDCODE
13200 [THEN]
13201
13202 [UNDEFINED] IS [IF]
13203 \ https://forth-standard.org/standard/core/IS
13204 \ IS <name>        xt --
13205 \ used as is :
13206 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
13207 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
13208 \ or in a definition : ... ['] U. IS DISPLAY ...
13209 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
13210 \
13211 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
13212 : IS
13213 STATE @
13214 IF  POSTPONE ['] POSTPONE DEFER! 
13215 ELSE ' DEFER! 
13216 THEN
13217 ; IMMEDIATE
13218 [THEN]
13219
13220 [UNDEFINED] >BODY [IF]
13221 \ https://forth-standard.org/standard/core/toBODY
13222 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
13223 CODE >BODY
13224 ADD #4,TOS
13225 MOV @IP+,PC
13226 ENDCODE
13227 [THEN]
13228
13229 \ CODE 20uS           \ n --      8MHz version
13230 \ BEGIN               \ 4 + 16 ~ loop
13231 \     MOV #39,rDOCON   \ 39
13232 \     BEGIN           \ 4 ~ loop
13233 \         NOP
13234 \         SUB #1,rDOCON
13235 \     0=  UNTIL
13236 \     SUB #1,TOS      \ 1
13237 \ 0= UNTIL
13238 \ MOV #XDOCON,rDOCON  \ 2
13239 \ MOV @PSP+,TOS
13240 \ MOV @RSP+,IP        \
13241 \ ENDCODE
13242
13243 CODE 20_US                      \ n --      n * 20 us
13244 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
13245     BEGIN
13246         BIT #1,&LCD_TIM_CTL     \ 3
13247     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
13248     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
13249     SUB #1,TOS                  \ 1
13250 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
13251 MOV @PSP+,TOS                   \ 2
13252 MOV @IP+,PC                     \ 4
13253 ENDCODE
13254
13255 CODE TOP_LCD                    \ LCD Sample
13256 \                               \ if write : %xxxx_WWWW --
13257 \                               \ if read  : -- %0000_RRRR
13258     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
13259     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
13260 0= IF                           \ write LCD bits pattern
13261     AND.B #LCD_DB,TOS           \ 
13262     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
13263     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
13264     MOV @PSP+,TOS               \
13265     MOV @IP+,PC
13266 THEN                            \ read LCD bits pattern
13267     SUB #2,PSP
13268     MOV TOS,0(PSP)
13269     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
13270     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
13271     AND.B #LCD_DB,TOS           \
13272     MOV @IP+,PC
13273 ENDCODE
13274
13275 CODE LCD_WRC                    \ char --         Write Char
13276     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
13277 BW1 SUB #2,PSP                  \
13278     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
13279     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
13280     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
13281     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
13282 COLON                           \ high level word starts here 
13283     TOP_LCD 2 20_US             \ write high nibble first
13284     TOP_LCD 2 20_US 
13285 ;
13286
13287 CODE LCD_WRF                    \ func --         Write Fonction
13288     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
13289     GOTO BW1
13290 ENDCODE
13291
13292 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
13293 : LCD_HOME $02 LCD_WRF 100 20_us ;
13294
13295 \ [UNDEFINED] OR [IF]
13296
13297 \ \ https://forth-standard.org/standard/core/OR
13298 \ \ C OR     x1 x2 -- x3           logical OR
13299 \ CODE OR
13300 \ BIS @PSP+,TOS
13301 \ MOV @IP+,PC
13302 \ ENDCODE
13303
13304 \ [THEN]
13305
13306 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
13307 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
13308 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
13309 \ : LCD_FN_SET        $20 OR LCD_WrF ;
13310 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
13311 \ : LCD_GOTO          $80 OR LCD_WrF ;
13312
13313
13314 \ CODE LCD_RDS                    \ -- status       Read Status
13315 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
13316 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
13317 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
13318 \ COLON                           \ starts a FORTH word
13319 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
13320 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
13321 \ HI2LO                           \ switch from FORTH to assembler
13322 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
13323 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
13324 \     MOV @RSP+,IP                \ restore IP saved by COLON
13325 \     MOV @IP+,PC                 \
13326 \ ENDCODE
13327
13328 \ CODE LCD_RDC                    \ -- char         Read Char
13329 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
13330 \     GOTO BW1
13331 \ ENDCODE
13332
13333
13334 \ ******************************\
13335 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
13336 \ ******************************\
13337 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
13338 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
13339 BIT.B #SW2,&SW2_IN              \ test switch S2
13340 0= IF                           \ case of switch S2 pressed
13341     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
13342     U< IF
13343         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
13344     THEN
13345 ELSE
13346     BIT.B #SW1,&SW1_IN          \ test switch S1 input
13347     0= IF                       \ case of Switch S1 pressed
13348         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
13349         U>= IF                  \
13350            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
13351         THEN                    \
13352     THEN                        \
13353 THEN                            \
13354 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
13355 RET                             \ 5
13356 ENDASM
13357
13358 \ ******************************\
13359 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
13360 \ ******************************\
13361 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
13362 \ ******************************\
13363 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
13364 \                               \       SMclock = 8|16|24 MHz
13365 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
13366 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
13367 \                               \       SR(9)=new Toggle bit memory (ADD on)
13368 \ ******************************\
13369 \ RC5_FirstStartBitHalfCycle:   \
13370 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
13371 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
13372 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
13373 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
13374 \ [THEN]
13375 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
13376     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
13377 [THEN]
13378 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
13379     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
13380 [THEN]
13381 MOV #1778,X                     \ RC5_Period * 1us
13382 MOV #14,W                       \ count of loop
13383 BEGIN                           \
13384 \ ******************************\
13385 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
13386 \ ******************************\                   |
13387 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
13388 \ RC5_Compute_3/4_Period:       \                   |
13389     RRUM    #1,X                \ X=1/2 cycle       |
13390     MOV     X,Y                 \                   ^
13391     RRUM    #1,Y                \ Y=1/4
13392     ADD     X,Y                 \ Y=3/4 cycle
13393     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
13394     U>= UNTIL                   \ 2
13395 \ ******************************\
13396 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
13397 \ ******************************\
13398     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
13399     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
13400     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
13401     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
13402     SUB     #1,W                \ decrement count loop
13403 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
13404 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
13405 0<> WHILE                       \ ----> out of loop ----+
13406     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
13407     BEGIN                       \                       |
13408         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
13409         CMP Y,X                 \ 1                     |   cycle time out of bound ?
13410         U>= IF                  \ 2                 ^   |   yes:
13411         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
13412         GOTO BW1                \                   |   |      quit on truncated RC5 message
13413         THEN                    \                   |   |
13414         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
13415     0<> UNTIL                   \ 2                 |   |
13416 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
13417 \ ******************************\                       |
13418 \ RC5_SampleEndOf:              \ <---------------------+
13419 \ ******************************\
13420 BIC #$30,&RC5_TIM_CTL           \   stop timer
13421 \ ******************************\
13422 \ RC5_ComputeNewRC5word         \
13423 \ ******************************\
13424 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
13425 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
13426 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
13427 \ ******************************\
13428 \ RC5_ComputeC6bit              \
13429 \ ******************************\
13430 BIT     #BIT14,T                \ test /C6 bit in T
13431 0= IF   BIS #BIT6,X             \ set C6 bit in X
13432 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
13433 \ ******************************\
13434 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
13435 \ ******************************\
13436 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
13437 \ ******************************\
13438 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
13439 XOR     @RSP,T                  \ (new XOR old) Toggle bits
13440 BIT     #UF10,T                 \ repeated RC5_command ?
13441 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
13442 XOR #UF10,0(RSP)                \ 5 toggle bit memory
13443 \ ******************************\
13444 \ Display IR_RC5 code           \
13445 \ ******************************\
13446 SUB #8,PSP                      \ TOS -- x x x x TOS
13447 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
13448 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
13449 MOV #$10,&BASEADR               \                                               set hexadecimal base
13450 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
13451 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
13452 LO2HI                           \                                               switch from assembler to FORTH
13453     LCD_CLEAR                   \                                               set LCD cursor at home
13454     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
13455     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
13456     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
13457     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
13458 HI2LO                           \     --                                        switch from FORTH to assembler
13459 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
13460 MOV @PSP+,TOS                   \     -- TOS
13461 RET
13462 ENDASM
13463
13464 \ ******************************\
13465 ASM BACKGROUND                  \
13466 \ ******************************\
13467 BEGIN
13468 \     ...                         \ insert here your background task
13469 \     ...                         \
13470 \     ...                         \
13471     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
13472     BIS &LPM_MODE,SR            \
13473 \ ******************************\
13474 \ here start all interrupts     \
13475 \ ******************************\
13476 \ here return all interrupts    \
13477 \ ******************************\
13478 AGAIN                           \
13479 ENDASM                          \
13480 \ ******************************\
13481
13482 \ ------------------------------\
13483 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
13484 \ ------------------------------\
13485 \     ...                         \ init specific I/O sys as you want
13486 \     ...                         \ before executing default WARM
13487     MOV #WARM,X                 \ ['] WARM 
13488     ADD #4,X                    \ >BODY
13489     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
13490 ENDASM
13491 \ ------------------------------\
13492
13493 \ ------------------------------\
13494 CODE STOP                       \ stops multitasking, must to be used before downloading app
13495 \ ------------------------------\
13496 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
13497     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
13498     MOV X,-2(X)                 \ restore the default background: SLEEP
13499     MOV #WARM,X
13500     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
13501     BIC.B #RC5,&IR_IE           \ clear RC5_Int
13502     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
13503     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
13504     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
13505     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
13506     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
13507 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
13508 ECHO                            \
13509 ." RC5toLCD is removed,"
13510 ."  type START to restart"
13511  WARM                           \ performs reset to reset all interrupt vectors.    
13512 ;
13513 \ ------------------------------\
13514
13515 \ ------------------------------\
13516 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
13517 \ ------------------------------\
13518 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
13519 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
13520 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
13521 \                           --       \ID input divider \ 10 = /4
13522 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
13523 \                                 -  \TBCLR TimerB Clear
13524 \                                  - \TBIE
13525 \                                   -\TBIFG
13526 \ -------------------------------\
13527 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
13528 \                  --                 \CM Capture Mode
13529 \                    --               \CCIS
13530 \                       -             \SCS
13531 \                        --           \CLLD
13532 \                          -          \CAP
13533 \                            ---      \OUTMOD \ 011 = set/reset
13534 \                               -     \CCIE
13535 \                                 -   \CCI
13536 \                                  -  \OUT
13537 \                                   - \COV
13538 \                                    -\CCIFG
13539 \ -------------------------------\
13540 \ LCD_TIM_CCRx                   \
13541 \ -------------------------------\
13542 \ LCD_TIM_EX0                    \ 
13543 \ ------------------------------\
13544 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
13545 \ ------------------------------\
13546 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
13547 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
13548 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
13549     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
13550 [THEN]
13551 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
13552     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
13553 [THEN]
13554     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
13555 \ ------------------------------\
13556 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
13557 \ ------------------------------\
13558 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
13559     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
13560 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
13561 \ ------------------------------\
13562     BIS.B #LCDVo,&LCDVo_DIR     \
13563     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
13564 \ ------------------------------\
13565     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
13566     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
13567 \ ------------------------------\
13568     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
13569     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
13570 \ ******************************\
13571 \ init RC5_Int                  \
13572 \ ******************************\
13573     BIS.B #RC5,&IR_IE           \ enable RC5_Int
13574     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
13575     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
13576 \ ******************************\
13577 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
13578 \ ******************************\
13579 \              %01 0001 0100    \ TAxCTL
13580 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
13581 \                  --           \ ID        divided by 1
13582 \                    --         \ MC        MODE = up to TAxCCRn
13583 \                        -      \ TACLR     clear timer count
13584 \                         -     \ TAIE
13585 \                          -    \ TAIFG
13586 \ ------------------------------\
13587 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
13588 \ ------------------------------\
13589 \                        000    \ TAxEX0
13590 \                        ---    \ TAIDEX    pre divisor
13591 \ ------------------------------\
13592 \          %0000 0000 0000 0101 \ TAxCCR0
13593     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
13594 \ ------------------------------\
13595 \          %0000 0000 0001 0000 \ TAxCCTL0
13596 \                   -           \ CAP capture/compare mode = compare
13597 \                        -      \ CCIEn
13598 \                             - \ CCIFGn
13599     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
13600 \ ------------------------------\
13601     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
13602 \ ------------------------------\
13603 \ define LPM mode for ACCEPT    \
13604 \ ------------------------------\
13605 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
13606 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
13607 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
13608 \ ------------------------------\
13609 \ activate I/O                  \
13610 \ ------------------------------\
13611 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
13612 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
13613 \ ------------------------------\
13614 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
13615 \ ------------------------------\
13616 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
13617 \ CMP #2,Y                        \ Power_ON event
13618 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
13619 CMP #4,Y                        \
13620 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
13621 \ CMP #6,Y                        \
13622 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
13623 \ CMP #$0A,Y                      \
13624 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
13625 \ CMP #$16,Y                      \
13626 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
13627 \ ------------------------------\
13628 COLON                           \
13629 \ ------------------------------\
13630 \ Init LCD 2x20                 \
13631 \ ------------------------------\
13632     #1000 20_US                 \ 1- wait 20 ms
13633     %011 TOP_LCD                \ 2- send DB5=DB4=1
13634     #205 20_US                  \ 3- wait 4,1 ms
13635     %011 TOP_LCD                \ 4- send again DB5=DB4=1
13636     #5 20_US                    \ 5- wait 0,1 ms
13637     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
13638     #2 20_US                    \    wait 40 us = LCD cycle
13639     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
13640     #2 20_US                    \    wait 40 us = LCD cycle
13641     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
13642     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
13643     LCD_CLEAR                   \ 10- "LCD_Clear"
13644     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
13645     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
13646     LCD_CLEAR                   \ 10- "LCD_Clear"
13647     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
13648     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
13649     CR ." I love you"           \ display message on LCD
13650     ['] CR >BODY IS CR          \ CR executes its default value
13651     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
13652     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
13653     PWR_STATE ABORT             \ init DP and continues with ABORT
13654 ;                               \
13655 \ ------------------------------\
13656
13657 \ ------------------------------\
13658 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
13659 \ ------------------------------\
13660 MOV #SLEEP,X                    \ replace default background process SLEEP
13661 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
13662 MOV #WARM,X                     \ replace default WARM
13663 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
13664 MOV X,PC                        \ then execute new WARM
13665 ENDCODE 
13666 \ ------------------------------\
13667
13668 ECHO
13669             ; downloading RC5toLCD.4th is done
13670 RST_HERE    ; this app is protected against <reset>
13671
13672
13673 RST_STATE
13674
13675 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
13676
13677 [UNDEFINED] MARKER [IF]
13678 \  https://forth-standard.org/standard/core/MARKER
13679 \  MARKER
13680 \ ( "<spaces>name" -- )
13681 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
13682 \ with the execution semantics defined below.
13683
13684 \ name Execution: ( -- )
13685 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
13686 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
13687 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
13688 \ not necessarily provided. No other contextual information such as numeric base is affected
13689 \
13690 : MARKER
13691 CREATE
13692 HI2LO
13693 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
13694 SUB #2,Y            \ 1 Y = LFA
13695 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
13696 ADD #4,&DP          \ 3 add 2 cells
13697 LO2HI
13698 DOES>
13699 HI2LO
13700 MOV @RSP+,IP        \ -- PFA
13701 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
13702 MOV @TOS,&INIDP     \       set DP value for RST_STATE
13703 MOV @PSP+,TOS       \ --
13704 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
13705 ENDCODE
13706 [THEN]
13707
13708 MARKER {RC5TOLCD}
13709
13710 [UNDEFINED] @ [IF]
13711 \ https://forth-standard.org/standard/core/Fetch
13712 \ @     c-addr -- char   fetch char from memory
13713 CODE @
13714 MOV @TOS,TOS
13715 MOV @IP+,PC
13716 ENDCODE
13717 [THEN]
13718
13719 [UNDEFINED] CONSTANT [IF]
13720 \ https://forth-standard.org/standard/core/CONSTANT
13721 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
13722 : CONSTANT 
13723 CREATE
13724 HI2LO
13725 MOV TOS,-2(W)           \   PFA = n
13726 MOV @PSP+,TOS
13727 MOV @RSP+,IP
13728 MOV @IP+,PC
13729 ENDCODE
13730 [THEN]
13731
13732 [UNDEFINED] STATE [IF]
13733 \ https://forth-standard.org/standard/core/STATE
13734 \ STATE   -- a-addr       holds compiler state
13735 STATEADR CONSTANT STATE
13736 [THEN]
13737
13738 [UNDEFINED] = [IF]
13739 \ https://forth-standard.org/standard/core/Equal
13740 \ =      x1 x2 -- flag         test x1=x2
13741 CODE =
13742 SUB @PSP+,TOS   \ 2
13743 0<> IF          \ 2
13744     AND #0,TOS  \ 1
13745     MOV @IP+,PC \ 4
13746 THEN
13747 XOR #-1,TOS     \ 1 flag Z = 1
13748 MOV @IP+,PC     \ 4
13749 ENDCODE
13750 [THEN]
13751
13752 [UNDEFINED] IF [IF]
13753 \ https://forth-standard.org/standard/core/IF
13754 \ IF       -- IFadr    initialize conditional forward branch
13755 CODE IF       \ immediate
13756 SUB #2,PSP              \
13757 MOV TOS,0(PSP)          \
13758 MOV &DP,TOS             \ -- HERE
13759 ADD #4,&DP            \           compile one word, reserve one word
13760 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
13761 ADD #2,TOS              \ -- HERE+2=IFadr
13762 MOV @IP+,PC
13763 ENDCODE IMMEDIATE
13764 [THEN]
13765
13766 [UNDEFINED] THEN [IF]
13767 \ https://forth-standard.org/standard/core/THEN
13768 \ THEN     IFadr --                resolve forward branch
13769 CODE THEN               \ immediate
13770 MOV &DP,0(TOS)          \ -- IFadr
13771 MOV @PSP+,TOS           \ --
13772 MOV @IP+,PC
13773 ENDCODE IMMEDIATE
13774 [THEN]
13775
13776 [UNDEFINED] ELSE [IF]
13777 \ https://forth-standard.org/standard/core/ELSE
13778 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
13779 CODE ELSE     \ immediate
13780 ADD #4,&DP              \ make room to compile two words
13781 MOV &DP,W               \ W=HERE+4
13782 MOV #BRAN,-4(W)
13783 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
13784 SUB #2,W                \ HERE+2
13785 MOV W,TOS               \ -- ELSEadr
13786 MOV @IP+,PC
13787 ENDCODE IMMEDIATE
13788 [THEN]
13789
13790 [UNDEFINED] DEFER [IF]
13791 \ https://forth-standard.org/standard/core/DEFER
13792 \ DEFER "<spaces>name"   --
13793 \ Skip leading space delimiters. Parse name delimited by a space.
13794 \ Create a definition for name with the execution semantics defined below.
13795
13796 \ name Execution:   --
13797 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
13798 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
13799 : DEFER
13800 CREATE
13801 HI2LO
13802 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
13803 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
13804 MOV @RSP+,IP
13805 MOV @IP+,PC
13806 ENDCODE
13807 [THEN]
13808
13809 [UNDEFINED] DEFER! [IF]
13810 \ https://forth-standard.org/standard/core/DEFERStore
13811 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
13812 CODE DEFER!             \ xt2 xt1 --
13813 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
13814 MOV @PSP+,TOS           \ --
13815 MOV @IP+,PC
13816 ENDCODE
13817 [THEN]
13818
13819 [UNDEFINED] IS [IF]
13820 \ https://forth-standard.org/standard/core/IS
13821 \ IS <name>        xt --
13822 \ used as is :
13823 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
13824 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
13825 \ or in a definition : ... ['] U. IS DISPLAY ...
13826 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
13827 \
13828 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
13829 : IS
13830 STATE @
13831 IF  POSTPONE ['] POSTPONE DEFER! 
13832 ELSE ' DEFER! 
13833 THEN
13834 ; IMMEDIATE
13835 [THEN]
13836
13837 [UNDEFINED] >BODY [IF]
13838 \ https://forth-standard.org/standard/core/toBODY
13839 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
13840 CODE >BODY
13841 ADD #4,TOS
13842 MOV @IP+,PC
13843 ENDCODE
13844 [THEN]
13845
13846 \ CODE 20uS           \ n --      8MHz version
13847 \ BEGIN               \ 4 + 16 ~ loop
13848 \     MOV #39,rDOCON   \ 39
13849 \     BEGIN           \ 4 ~ loop
13850 \         NOP
13851 \         SUB #1,rDOCON
13852 \     0=  UNTIL
13853 \     SUB #1,TOS      \ 1
13854 \ 0= UNTIL
13855 \ MOV #XDOCON,rDOCON  \ 2
13856 \ MOV @PSP+,TOS
13857 \ MOV @RSP+,IP        \
13858 \ ENDCODE
13859
13860 CODE 20_US                      \ n --      n * 20 us
13861 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
13862     BEGIN
13863         BIT #1,&LCD_TIM_CTL     \ 3
13864     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
13865     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
13866     SUB #1,TOS                  \ 1
13867 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
13868 MOV @PSP+,TOS                   \ 2
13869 MOV @IP+,PC                     \ 4
13870 ENDCODE
13871
13872 CODE TOP_LCD                    \ LCD Sample
13873 \                               \ if write : %xxxx_WWWW --
13874 \                               \ if read  : -- %0000_RRRR
13875     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
13876     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
13877 0= IF                           \ write LCD bits pattern
13878     AND.B #LCD_DB,TOS           \ 
13879     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
13880     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
13881     MOV @PSP+,TOS               \
13882     MOV @IP+,PC
13883 THEN                            \ read LCD bits pattern
13884     SUB #2,PSP
13885     MOV TOS,0(PSP)
13886     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
13887     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
13888     AND.B #LCD_DB,TOS           \
13889     MOV @IP+,PC
13890 ENDCODE
13891
13892 CODE LCD_WRC                    \ char --         Write Char
13893     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
13894 BW1 SUB #2,PSP                  \
13895     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
13896     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
13897     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
13898     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
13899 COLON                           \ high level word starts here 
13900     TOP_LCD 2 20_US             \ write high nibble first
13901     TOP_LCD 2 20_US 
13902 ;
13903
13904 CODE LCD_WRF                    \ func --         Write Fonction
13905     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
13906     GOTO BW1
13907 ENDCODE
13908
13909 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
13910 : LCD_HOME $02 LCD_WRF 100 20_us ;
13911
13912 \ [UNDEFINED] OR [IF]
13913
13914 \ \ https://forth-standard.org/standard/core/OR
13915 \ \ C OR     x1 x2 -- x3           logical OR
13916 \ CODE OR
13917 \ BIS @PSP+,TOS
13918 \ MOV @IP+,PC
13919 \ ENDCODE
13920
13921 \ [THEN]
13922
13923 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
13924 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
13925 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
13926 \ : LCD_FN_SET        $20 OR LCD_WrF ;
13927 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
13928 \ : LCD_GOTO          $80 OR LCD_WrF ;
13929
13930
13931 \ CODE LCD_RDS                    \ -- status       Read Status
13932 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
13933 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
13934 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
13935 \ COLON                           \ starts a FORTH word
13936 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
13937 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
13938 \ HI2LO                           \ switch from FORTH to assembler
13939 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
13940 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
13941 \     MOV @RSP+,IP                \ restore IP saved by COLON
13942 \     MOV @IP+,PC                 \
13943 \ ENDCODE
13944
13945 \ CODE LCD_RDC                    \ -- char         Read Char
13946 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
13947 \     GOTO BW1
13948 \ ENDCODE
13949
13950
13951 \ ******************************\
13952 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
13953 \ ******************************\
13954 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
13955 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
13956 BIT.B #SW2,&SW2_IN              \ test switch S2
13957 0= IF                           \ case of switch S2 pressed
13958     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
13959     U< IF
13960         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
13961     THEN
13962 ELSE
13963     BIT.B #SW1,&SW1_IN          \ test switch S1 input
13964     0= IF                       \ case of Switch S1 pressed
13965         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
13966         U>= IF                  \
13967            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
13968         THEN                    \
13969     THEN                        \
13970 THEN                            \
13971 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
13972 RET                             \ 5
13973 ENDASM
13974
13975 \ ******************************\
13976 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
13977 \ ******************************\
13978 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
13979 \ ******************************\
13980 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
13981 \                               \       SMclock = 8|16|24 MHz
13982 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
13983 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
13984 \                               \       SR(9)=new Toggle bit memory (ADD on)
13985 \ ******************************\
13986 \ RC5_FirstStartBitHalfCycle:   \
13987 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
13988 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
13989 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
13990 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
13991 \ [THEN]
13992 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
13993     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
13994 [THEN]
13995 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
13996     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
13997 [THEN]
13998 MOV #1778,X                     \ RC5_Period * 1us
13999 MOV #14,W                       \ count of loop
14000 BEGIN                           \
14001 \ ******************************\
14002 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
14003 \ ******************************\                   |
14004 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
14005 \ RC5_Compute_3/4_Period:       \                   |
14006     RRUM    #1,X                \ X=1/2 cycle       |
14007     MOV     X,Y                 \                   ^
14008     RRUM    #1,Y                \ Y=1/4
14009     ADD     X,Y                 \ Y=3/4 cycle
14010     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
14011     U>= UNTIL                   \ 2
14012 \ ******************************\
14013 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
14014 \ ******************************\
14015     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
14016     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
14017     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
14018     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
14019     SUB     #1,W                \ decrement count loop
14020 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
14021 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
14022 0<> WHILE                       \ ----> out of loop ----+
14023     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
14024     BEGIN                       \                       |
14025         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
14026         CMP Y,X                 \ 1                     |   cycle time out of bound ?
14027         U>= IF                  \ 2                 ^   |   yes:
14028         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
14029         GOTO BW1                \                   |   |      quit on truncated RC5 message
14030         THEN                    \                   |   |
14031         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
14032     0<> UNTIL                   \ 2                 |   |
14033 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
14034 \ ******************************\                       |
14035 \ RC5_SampleEndOf:              \ <---------------------+
14036 \ ******************************\
14037 BIC #$30,&RC5_TIM_CTL           \   stop timer
14038 \ ******************************\
14039 \ RC5_ComputeNewRC5word         \
14040 \ ******************************\
14041 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
14042 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
14043 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
14044 \ ******************************\
14045 \ RC5_ComputeC6bit              \
14046 \ ******************************\
14047 BIT     #BIT14,T                \ test /C6 bit in T
14048 0= IF   BIS #BIT6,X             \ set C6 bit in X
14049 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
14050 \ ******************************\
14051 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
14052 \ ******************************\
14053 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
14054 \ ******************************\
14055 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
14056 XOR     @RSP,T                  \ (new XOR old) Toggle bits
14057 BIT     #UF10,T                 \ repeated RC5_command ?
14058 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
14059 XOR #UF10,0(RSP)                \ 5 toggle bit memory
14060 \ ******************************\
14061 \ Display IR_RC5 code           \
14062 \ ******************************\
14063 SUB #8,PSP                      \ TOS -- x x x x TOS
14064 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
14065 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
14066 MOV #$10,&BASEADR               \                                               set hexadecimal base
14067 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
14068 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
14069 LO2HI                           \                                               switch from assembler to FORTH
14070     LCD_CLEAR                   \                                               set LCD cursor at home
14071     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
14072     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
14073     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
14074     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
14075 HI2LO                           \     --                                        switch from FORTH to assembler
14076 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
14077 MOV @PSP+,TOS                   \     -- TOS
14078 RET
14079 ENDASM
14080
14081 \ ******************************\
14082 ASM BACKGROUND                  \
14083 \ ******************************\
14084 BEGIN
14085 \     ...                         \ insert here your background task
14086 \     ...                         \
14087 \     ...                         \
14088     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
14089     BIS &LPM_MODE,SR            \
14090 \ ******************************\
14091 \ here start all interrupts     \
14092 \ ******************************\
14093 \ here return all interrupts    \
14094 \ ******************************\
14095 AGAIN                           \
14096 ENDASM                          \
14097 \ ******************************\
14098
14099 \ ------------------------------\
14100 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
14101 \ ------------------------------\
14102 \     ...                         \ init specific I/O sys as you want
14103 \     ...                         \ before executing default WARM
14104     MOV #WARM,X                 \ ['] WARM 
14105     ADD #4,X                    \ >BODY
14106     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
14107 ENDASM
14108 \ ------------------------------\
14109
14110 \ ------------------------------\
14111 CODE STOP                       \ stops multitasking, must to be used before downloading app
14112 \ ------------------------------\
14113 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
14114     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
14115     MOV X,-2(X)                 \ restore the default background: SLEEP
14116     MOV #WARM,X
14117     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
14118     BIC.B #RC5,&IR_IE           \ clear RC5_Int
14119     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
14120     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
14121     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
14122     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
14123     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
14124 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
14125 ECHO                            \
14126 ." RC5toLCD is removed,"
14127 ."  type START to restart"
14128  WARM                           \ performs reset to reset all interrupt vectors.    
14129 ;
14130 \ ------------------------------\
14131
14132 \ ------------------------------\
14133 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
14134 \ ------------------------------\
14135 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
14136 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
14137 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
14138 \                           --       \ID input divider \ 10 = /4
14139 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
14140 \                                 -  \TBCLR TimerB Clear
14141 \                                  - \TBIE
14142 \                                   -\TBIFG
14143 \ -------------------------------\
14144 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
14145 \                  --                 \CM Capture Mode
14146 \                    --               \CCIS
14147 \                       -             \SCS
14148 \                        --           \CLLD
14149 \                          -          \CAP
14150 \                            ---      \OUTMOD \ 011 = set/reset
14151 \                               -     \CCIE
14152 \                                 -   \CCI
14153 \                                  -  \OUT
14154 \                                   - \COV
14155 \                                    -\CCIFG
14156 \ -------------------------------\
14157 \ LCD_TIM_CCRx                   \
14158 \ -------------------------------\
14159 \ LCD_TIM_EX0                    \ 
14160 \ ------------------------------\
14161 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
14162 \ ------------------------------\
14163 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
14164 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
14165 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
14166     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
14167 [THEN]
14168 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
14169     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
14170 [THEN]
14171     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
14172 \ ------------------------------\
14173 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
14174 \ ------------------------------\
14175 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
14176     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
14177 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
14178 \ ------------------------------\
14179     BIS.B #LCDVo,&LCDVo_DIR     \
14180     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
14181 \ ------------------------------\
14182     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
14183     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
14184 \ ------------------------------\
14185     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
14186     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
14187 \ ******************************\
14188 \ init RC5_Int                  \
14189 \ ******************************\
14190     BIS.B #RC5,&IR_IE           \ enable RC5_Int
14191     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
14192     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
14193 \ ******************************\
14194 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
14195 \ ******************************\
14196 \              %01 0001 0100    \ TAxCTL
14197 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
14198 \                  --           \ ID        divided by 1
14199 \                    --         \ MC        MODE = up to TAxCCRn
14200 \                        -      \ TACLR     clear timer count
14201 \                         -     \ TAIE
14202 \                          -    \ TAIFG
14203 \ ------------------------------\
14204 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
14205 \ ------------------------------\
14206 \                        000    \ TAxEX0
14207 \                        ---    \ TAIDEX    pre divisor
14208 \ ------------------------------\
14209 \          %0000 0000 0000 0101 \ TAxCCR0
14210     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
14211 \ ------------------------------\
14212 \          %0000 0000 0001 0000 \ TAxCCTL0
14213 \                   -           \ CAP capture/compare mode = compare
14214 \                        -      \ CCIEn
14215 \                             - \ CCIFGn
14216     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
14217 \ ------------------------------\
14218     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
14219 \ ------------------------------\
14220 \ define LPM mode for ACCEPT    \
14221 \ ------------------------------\
14222 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
14223 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
14224 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
14225 \ ------------------------------\
14226 \ activate I/O                  \
14227 \ ------------------------------\
14228 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
14229 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
14230 \ ------------------------------\
14231 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
14232 \ ------------------------------\
14233 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
14234 \ CMP #2,Y                        \ Power_ON event
14235 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
14236 CMP #4,Y                        \
14237 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
14238 \ CMP #6,Y                        \
14239 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
14240 \ CMP #$0A,Y                      \
14241 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
14242 \ CMP #$16,Y                      \
14243 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
14244 \ ------------------------------\
14245 COLON                           \
14246 \ ------------------------------\
14247 \ Init LCD 2x20                 \
14248 \ ------------------------------\
14249     #1000 20_US                 \ 1- wait 20 ms
14250     %011 TOP_LCD                \ 2- send DB5=DB4=1
14251     #205 20_US                  \ 3- wait 4,1 ms
14252     %011 TOP_LCD                \ 4- send again DB5=DB4=1
14253     #5 20_US                    \ 5- wait 0,1 ms
14254     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
14255     #2 20_US                    \    wait 40 us = LCD cycle
14256     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
14257     #2 20_US                    \    wait 40 us = LCD cycle
14258     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
14259     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
14260     LCD_CLEAR                   \ 10- "LCD_Clear"
14261     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
14262     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
14263     LCD_CLEAR                   \ 10- "LCD_Clear"
14264     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
14265     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
14266     CR ." I love you"           \ display message on LCD
14267     ['] CR >BODY IS CR          \ CR executes its default value
14268     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
14269     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
14270     PWR_STATE ABORT             \ init DP and continues with ABORT
14271 ;                               \
14272 \ ------------------------------\
14273
14274 \ ------------------------------\
14275 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
14276 \ ------------------------------\
14277 MOV #SLEEP,X                    \ replace default background process SLEEP
14278 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
14279 MOV #WARM,X                     \ replace default WARM
14280 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
14281 MOV X,PC                        \ then execute new WARM
14282 ENDCODE 
14283 \ ------------------------------\
14284
14285 ECHO
14286             ; downloading RC5toLCD.4th is done
14287 RST_HERE    ; this app is protected against <reset>
14288
14289
14290 RST_STATE
14291
14292 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
14293
14294 [UNDEFINED] MARKER [IF]
14295 \  https://forth-standard.org/standard/core/MARKER
14296 \  MARKER
14297 \ ( "<spaces>name" -- )
14298 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
14299 \ with the execution semantics defined below.
14300
14301 \ name Execution: ( -- )
14302 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
14303 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
14304 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
14305 \ not necessarily provided. No other contextual information such as numeric base is affected
14306 \
14307 : MARKER
14308 CREATE
14309 HI2LO
14310 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
14311 SUB #2,Y            \ 1 Y = LFA
14312 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
14313 ADD #4,&DP          \ 3 add 2 cells
14314 LO2HI
14315 DOES>
14316 HI2LO
14317 MOV @RSP+,IP        \ -- PFA
14318 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
14319 MOV @TOS,&INIDP     \       set DP value for RST_STATE
14320 MOV @PSP+,TOS       \ --
14321 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
14322 ENDCODE
14323 [THEN]
14324
14325 MARKER {RC5TOLCD}
14326
14327 [UNDEFINED] @ [IF]
14328 \ https://forth-standard.org/standard/core/Fetch
14329 \ @     c-addr -- char   fetch char from memory
14330 CODE @
14331 MOV @TOS,TOS
14332 MOV @IP+,PC
14333 ENDCODE
14334 [THEN]
14335
14336 [UNDEFINED] CONSTANT [IF]
14337 \ https://forth-standard.org/standard/core/CONSTANT
14338 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
14339 : CONSTANT 
14340 CREATE
14341 HI2LO
14342 MOV TOS,-2(W)           \   PFA = n
14343 MOV @PSP+,TOS
14344 MOV @RSP+,IP
14345 MOV @IP+,PC
14346 ENDCODE
14347 [THEN]
14348
14349 [UNDEFINED] STATE [IF]
14350 \ https://forth-standard.org/standard/core/STATE
14351 \ STATE   -- a-addr       holds compiler state
14352 STATEADR CONSTANT STATE
14353 [THEN]
14354
14355 [UNDEFINED] = [IF]
14356 \ https://forth-standard.org/standard/core/Equal
14357 \ =      x1 x2 -- flag         test x1=x2
14358 CODE =
14359 SUB @PSP+,TOS   \ 2
14360 0<> IF          \ 2
14361     AND #0,TOS  \ 1
14362     MOV @IP+,PC \ 4
14363 THEN
14364 XOR #-1,TOS     \ 1 flag Z = 1
14365 MOV @IP+,PC     \ 4
14366 ENDCODE
14367 [THEN]
14368
14369 [UNDEFINED] IF [IF]
14370 \ https://forth-standard.org/standard/core/IF
14371 \ IF       -- IFadr    initialize conditional forward branch
14372 CODE IF       \ immediate
14373 SUB #2,PSP              \
14374 MOV TOS,0(PSP)          \
14375 MOV &DP,TOS             \ -- HERE
14376 ADD #4,&DP            \           compile one word, reserve one word
14377 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
14378 ADD #2,TOS              \ -- HERE+2=IFadr
14379 MOV @IP+,PC
14380 ENDCODE IMMEDIATE
14381 [THEN]
14382
14383 [UNDEFINED] THEN [IF]
14384 \ https://forth-standard.org/standard/core/THEN
14385 \ THEN     IFadr --                resolve forward branch
14386 CODE THEN               \ immediate
14387 MOV &DP,0(TOS)          \ -- IFadr
14388 MOV @PSP+,TOS           \ --
14389 MOV @IP+,PC
14390 ENDCODE IMMEDIATE
14391 [THEN]
14392
14393 [UNDEFINED] ELSE [IF]
14394 \ https://forth-standard.org/standard/core/ELSE
14395 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
14396 CODE ELSE     \ immediate
14397 ADD #4,&DP              \ make room to compile two words
14398 MOV &DP,W               \ W=HERE+4
14399 MOV #BRAN,-4(W)
14400 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
14401 SUB #2,W                \ HERE+2
14402 MOV W,TOS               \ -- ELSEadr
14403 MOV @IP+,PC
14404 ENDCODE IMMEDIATE
14405 [THEN]
14406
14407 [UNDEFINED] DEFER [IF]
14408 \ https://forth-standard.org/standard/core/DEFER
14409 \ DEFER "<spaces>name"   --
14410 \ Skip leading space delimiters. Parse name delimited by a space.
14411 \ Create a definition for name with the execution semantics defined below.
14412
14413 \ name Execution:   --
14414 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
14415 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
14416 : DEFER
14417 CREATE
14418 HI2LO
14419 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
14420 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
14421 MOV @RSP+,IP
14422 MOV @IP+,PC
14423 ENDCODE
14424 [THEN]
14425
14426 [UNDEFINED] DEFER! [IF]
14427 \ https://forth-standard.org/standard/core/DEFERStore
14428 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
14429 CODE DEFER!             \ xt2 xt1 --
14430 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
14431 MOV @PSP+,TOS           \ --
14432 MOV @IP+,PC
14433 ENDCODE
14434 [THEN]
14435
14436 [UNDEFINED] IS [IF]
14437 \ https://forth-standard.org/standard/core/IS
14438 \ IS <name>        xt --
14439 \ used as is :
14440 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
14441 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
14442 \ or in a definition : ... ['] U. IS DISPLAY ...
14443 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
14444 \
14445 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
14446 : IS
14447 STATE @
14448 IF  POSTPONE ['] POSTPONE DEFER! 
14449 ELSE ' DEFER! 
14450 THEN
14451 ; IMMEDIATE
14452 [THEN]
14453
14454 [UNDEFINED] >BODY [IF]
14455 \ https://forth-standard.org/standard/core/toBODY
14456 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
14457 CODE >BODY
14458 ADD #4,TOS
14459 MOV @IP+,PC
14460 ENDCODE
14461 [THEN]
14462
14463 \ CODE 20uS           \ n --      8MHz version
14464 \ BEGIN               \ 4 + 16 ~ loop
14465 \     MOV #39,rDOCON   \ 39
14466 \     BEGIN           \ 4 ~ loop
14467 \         NOP
14468 \         SUB #1,rDOCON
14469 \     0=  UNTIL
14470 \     SUB #1,TOS      \ 1
14471 \ 0= UNTIL
14472 \ MOV #XDOCON,rDOCON  \ 2
14473 \ MOV @PSP+,TOS
14474 \ MOV @RSP+,IP        \
14475 \ ENDCODE
14476
14477 CODE 20_US                      \ n --      n * 20 us
14478 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
14479     BEGIN
14480         BIT #1,&LCD_TIM_CTL     \ 3
14481     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
14482     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
14483     SUB #1,TOS                  \ 1
14484 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
14485 MOV @PSP+,TOS                   \ 2
14486 MOV @IP+,PC                     \ 4
14487 ENDCODE
14488
14489 CODE TOP_LCD                    \ LCD Sample
14490 \                               \ if write : %xxxx_WWWW --
14491 \                               \ if read  : -- %0000_RRRR
14492     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
14493     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
14494 0= IF                           \ write LCD bits pattern
14495     AND.B #LCD_DB,TOS           \ 
14496     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
14497     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
14498     MOV @PSP+,TOS               \
14499     MOV @IP+,PC
14500 THEN                            \ read LCD bits pattern
14501     SUB #2,PSP
14502     MOV TOS,0(PSP)
14503     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
14504     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
14505     AND.B #LCD_DB,TOS           \
14506     MOV @IP+,PC
14507 ENDCODE
14508
14509 CODE LCD_WRC                    \ char --         Write Char
14510     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
14511 BW1 SUB #2,PSP                  \
14512     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
14513     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
14514     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
14515     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
14516 COLON                           \ high level word starts here 
14517     TOP_LCD 2 20_US             \ write high nibble first
14518     TOP_LCD 2 20_US 
14519 ;
14520
14521 CODE LCD_WRF                    \ func --         Write Fonction
14522     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
14523     GOTO BW1
14524 ENDCODE
14525
14526 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
14527 : LCD_HOME $02 LCD_WRF 100 20_us ;
14528
14529 \ [UNDEFINED] OR [IF]
14530
14531 \ \ https://forth-standard.org/standard/core/OR
14532 \ \ C OR     x1 x2 -- x3           logical OR
14533 \ CODE OR
14534 \ BIS @PSP+,TOS
14535 \ MOV @IP+,PC
14536 \ ENDCODE
14537
14538 \ [THEN]
14539
14540 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
14541 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
14542 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
14543 \ : LCD_FN_SET        $20 OR LCD_WrF ;
14544 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
14545 \ : LCD_GOTO          $80 OR LCD_WrF ;
14546
14547
14548 \ CODE LCD_RDS                    \ -- status       Read Status
14549 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
14550 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
14551 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
14552 \ COLON                           \ starts a FORTH word
14553 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
14554 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
14555 \ HI2LO                           \ switch from FORTH to assembler
14556 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
14557 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
14558 \     MOV @RSP+,IP                \ restore IP saved by COLON
14559 \     MOV @IP+,PC                 \
14560 \ ENDCODE
14561
14562 \ CODE LCD_RDC                    \ -- char         Read Char
14563 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
14564 \     GOTO BW1
14565 \ ENDCODE
14566
14567
14568 \ ******************************\
14569 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
14570 \ ******************************\
14571 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
14572 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
14573 BIT.B #SW2,&SW2_IN              \ test switch S2
14574 0= IF                           \ case of switch S2 pressed
14575     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
14576     U< IF
14577         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
14578     THEN
14579 ELSE
14580     BIT.B #SW1,&SW1_IN          \ test switch S1 input
14581     0= IF                       \ case of Switch S1 pressed
14582         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
14583         U>= IF                  \
14584            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
14585         THEN                    \
14586     THEN                        \
14587 THEN                            \
14588 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
14589 RET                             \ 5
14590 ENDASM
14591
14592 \ ******************************\
14593 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
14594 \ ******************************\
14595 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
14596 \ ******************************\
14597 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
14598 \                               \       SMclock = 8|16|24 MHz
14599 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
14600 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
14601 \                               \       SR(9)=new Toggle bit memory (ADD on)
14602 \ ******************************\
14603 \ RC5_FirstStartBitHalfCycle:   \
14604 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
14605 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
14606 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
14607 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
14608 \ [THEN]
14609 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
14610     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
14611 [THEN]
14612 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
14613     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
14614 [THEN]
14615 MOV #1778,X                     \ RC5_Period * 1us
14616 MOV #14,W                       \ count of loop
14617 BEGIN                           \
14618 \ ******************************\
14619 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
14620 \ ******************************\                   |
14621 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
14622 \ RC5_Compute_3/4_Period:       \                   |
14623     RRUM    #1,X                \ X=1/2 cycle       |
14624     MOV     X,Y                 \                   ^
14625     RRUM    #1,Y                \ Y=1/4
14626     ADD     X,Y                 \ Y=3/4 cycle
14627     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
14628     U>= UNTIL                   \ 2
14629 \ ******************************\
14630 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
14631 \ ******************************\
14632     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
14633     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
14634     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
14635     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
14636     SUB     #1,W                \ decrement count loop
14637 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
14638 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
14639 0<> WHILE                       \ ----> out of loop ----+
14640     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
14641     BEGIN                       \                       |
14642         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
14643         CMP Y,X                 \ 1                     |   cycle time out of bound ?
14644         U>= IF                  \ 2                 ^   |   yes:
14645         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
14646         GOTO BW1                \                   |   |      quit on truncated RC5 message
14647         THEN                    \                   |   |
14648         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
14649     0<> UNTIL                   \ 2                 |   |
14650 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
14651 \ ******************************\                       |
14652 \ RC5_SampleEndOf:              \ <---------------------+
14653 \ ******************************\
14654 BIC #$30,&RC5_TIM_CTL           \   stop timer
14655 \ ******************************\
14656 \ RC5_ComputeNewRC5word         \
14657 \ ******************************\
14658 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
14659 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
14660 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
14661 \ ******************************\
14662 \ RC5_ComputeC6bit              \
14663 \ ******************************\
14664 BIT     #BIT14,T                \ test /C6 bit in T
14665 0= IF   BIS #BIT6,X             \ set C6 bit in X
14666 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
14667 \ ******************************\
14668 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
14669 \ ******************************\
14670 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
14671 \ ******************************\
14672 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
14673 XOR     @RSP,T                  \ (new XOR old) Toggle bits
14674 BIT     #UF10,T                 \ repeated RC5_command ?
14675 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
14676 XOR #UF10,0(RSP)                \ 5 toggle bit memory
14677 \ ******************************\
14678 \ Display IR_RC5 code           \
14679 \ ******************************\
14680 SUB #8,PSP                      \ TOS -- x x x x TOS
14681 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
14682 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
14683 MOV #$10,&BASEADR               \                                               set hexadecimal base
14684 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
14685 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
14686 LO2HI                           \                                               switch from assembler to FORTH
14687     LCD_CLEAR                   \                                               set LCD cursor at home
14688     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
14689     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
14690     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
14691     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
14692 HI2LO                           \     --                                        switch from FORTH to assembler
14693 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
14694 MOV @PSP+,TOS                   \     -- TOS
14695 RET
14696 ENDASM
14697
14698 \ ******************************\
14699 ASM BACKGROUND                  \
14700 \ ******************************\
14701 BEGIN
14702 \     ...                         \ insert here your background task
14703 \     ...                         \
14704 \     ...                         \
14705     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
14706     BIS &LPM_MODE,SR            \
14707 \ ******************************\
14708 \ here start all interrupts     \
14709 \ ******************************\
14710 \ here return all interrupts    \
14711 \ ******************************\
14712 AGAIN                           \
14713 ENDASM                          \
14714 \ ******************************\
14715
14716 \ ------------------------------\
14717 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
14718 \ ------------------------------\
14719 \     ...                         \ init specific I/O sys as you want
14720 \     ...                         \ before executing default WARM
14721     MOV #WARM,X                 \ ['] WARM 
14722     ADD #4,X                    \ >BODY
14723     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
14724 ENDASM
14725 \ ------------------------------\
14726
14727 \ ------------------------------\
14728 CODE STOP                       \ stops multitasking, must to be used before downloading app
14729 \ ------------------------------\
14730 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
14731     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
14732     MOV X,-2(X)                 \ restore the default background: SLEEP
14733     MOV #WARM,X
14734     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
14735     BIC.B #RC5,&IR_IE           \ clear RC5_Int
14736     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
14737     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
14738     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
14739     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
14740     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
14741 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
14742 ECHO                            \
14743 ." RC5toLCD is removed,"
14744 ."  type START to restart"
14745  WARM                           \ performs reset to reset all interrupt vectors.    
14746 ;
14747 \ ------------------------------\
14748
14749 \ ------------------------------\
14750 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
14751 \ ------------------------------\
14752 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
14753 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
14754 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
14755 \                           --       \ID input divider \ 10 = /4
14756 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
14757 \                                 -  \TBCLR TimerB Clear
14758 \                                  - \TBIE
14759 \                                   -\TBIFG
14760 \ -------------------------------\
14761 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
14762 \                  --                 \CM Capture Mode
14763 \                    --               \CCIS
14764 \                       -             \SCS
14765 \                        --           \CLLD
14766 \                          -          \CAP
14767 \                            ---      \OUTMOD \ 011 = set/reset
14768 \                               -     \CCIE
14769 \                                 -   \CCI
14770 \                                  -  \OUT
14771 \                                   - \COV
14772 \                                    -\CCIFG
14773 \ -------------------------------\
14774 \ LCD_TIM_CCRx                   \
14775 \ -------------------------------\
14776 \ LCD_TIM_EX0                    \ 
14777 \ ------------------------------\
14778 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
14779 \ ------------------------------\
14780 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
14781 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
14782 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
14783     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
14784 [THEN]
14785 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
14786     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
14787 [THEN]
14788     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
14789 \ ------------------------------\
14790 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
14791 \ ------------------------------\
14792 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
14793     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
14794 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
14795 \ ------------------------------\
14796     BIS.B #LCDVo,&LCDVo_DIR     \
14797     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
14798 \ ------------------------------\
14799     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
14800     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
14801 \ ------------------------------\
14802     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
14803     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
14804 \ ******************************\
14805 \ init RC5_Int                  \
14806 \ ******************************\
14807     BIS.B #RC5,&IR_IE           \ enable RC5_Int
14808     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
14809     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
14810 \ ******************************\
14811 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
14812 \ ******************************\
14813 \              %01 0001 0100    \ TAxCTL
14814 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
14815 \                  --           \ ID        divided by 1
14816 \                    --         \ MC        MODE = up to TAxCCRn
14817 \                        -      \ TACLR     clear timer count
14818 \                         -     \ TAIE
14819 \                          -    \ TAIFG
14820 \ ------------------------------\
14821 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
14822 \ ------------------------------\
14823 \                        000    \ TAxEX0
14824 \                        ---    \ TAIDEX    pre divisor
14825 \ ------------------------------\
14826 \          %0000 0000 0000 0101 \ TAxCCR0
14827     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
14828 \ ------------------------------\
14829 \          %0000 0000 0001 0000 \ TAxCCTL0
14830 \                   -           \ CAP capture/compare mode = compare
14831 \                        -      \ CCIEn
14832 \                             - \ CCIFGn
14833     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
14834 \ ------------------------------\
14835     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
14836 \ ------------------------------\
14837 \ define LPM mode for ACCEPT    \
14838 \ ------------------------------\
14839 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
14840 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
14841 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
14842 \ ------------------------------\
14843 \ activate I/O                  \
14844 \ ------------------------------\
14845 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
14846 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
14847 \ ------------------------------\
14848 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
14849 \ ------------------------------\
14850 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
14851 \ CMP #2,Y                        \ Power_ON event
14852 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
14853 CMP #4,Y                        \
14854 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
14855 \ CMP #6,Y                        \
14856 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
14857 \ CMP #$0A,Y                      \
14858 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
14859 \ CMP #$16,Y                      \
14860 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
14861 \ ------------------------------\
14862 COLON                           \
14863 \ ------------------------------\
14864 \ Init LCD 2x20                 \
14865 \ ------------------------------\
14866     #1000 20_US                 \ 1- wait 20 ms
14867     %011 TOP_LCD                \ 2- send DB5=DB4=1
14868     #205 20_US                  \ 3- wait 4,1 ms
14869     %011 TOP_LCD                \ 4- send again DB5=DB4=1
14870     #5 20_US                    \ 5- wait 0,1 ms
14871     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
14872     #2 20_US                    \    wait 40 us = LCD cycle
14873     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
14874     #2 20_US                    \    wait 40 us = LCD cycle
14875     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
14876     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
14877     LCD_CLEAR                   \ 10- "LCD_Clear"
14878     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
14879     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
14880     LCD_CLEAR                   \ 10- "LCD_Clear"
14881     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
14882     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
14883     CR ." I love you"           \ display message on LCD
14884     ['] CR >BODY IS CR          \ CR executes its default value
14885     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
14886     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
14887     PWR_STATE ABORT             \ init DP and continues with ABORT
14888 ;                               \
14889 \ ------------------------------\
14890
14891 \ ------------------------------\
14892 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
14893 \ ------------------------------\
14894 MOV #SLEEP,X                    \ replace default background process SLEEP
14895 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
14896 MOV #WARM,X                     \ replace default WARM
14897 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
14898 MOV X,PC                        \ then execute new WARM
14899 ENDCODE 
14900 \ ------------------------------\
14901
14902 ECHO
14903             ; downloading RC5toLCD.4th is done
14904 RST_HERE    ; this app is protected against <reset>
14905
14906
14907 RST_STATE
14908
14909 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
14910
14911 [UNDEFINED] MARKER [IF]
14912 \  https://forth-standard.org/standard/core/MARKER
14913 \  MARKER
14914 \ ( "<spaces>name" -- )
14915 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
14916 \ with the execution semantics defined below.
14917
14918 \ name Execution: ( -- )
14919 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
14920 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
14921 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
14922 \ not necessarily provided. No other contextual information such as numeric base is affected
14923 \
14924 : MARKER
14925 CREATE
14926 HI2LO
14927 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
14928 SUB #2,Y            \ 1 Y = LFA
14929 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
14930 ADD #4,&DP          \ 3 add 2 cells
14931 LO2HI
14932 DOES>
14933 HI2LO
14934 MOV @RSP+,IP        \ -- PFA
14935 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
14936 MOV @TOS,&INIDP     \       set DP value for RST_STATE
14937 MOV @PSP+,TOS       \ --
14938 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
14939 ENDCODE
14940 [THEN]
14941
14942 MARKER {RC5TOLCD}
14943
14944 [UNDEFINED] @ [IF]
14945 \ https://forth-standard.org/standard/core/Fetch
14946 \ @     c-addr -- char   fetch char from memory
14947 CODE @
14948 MOV @TOS,TOS
14949 MOV @IP+,PC
14950 ENDCODE
14951 [THEN]
14952
14953 [UNDEFINED] CONSTANT [IF]
14954 \ https://forth-standard.org/standard/core/CONSTANT
14955 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
14956 : CONSTANT 
14957 CREATE
14958 HI2LO
14959 MOV TOS,-2(W)           \   PFA = n
14960 MOV @PSP+,TOS
14961 MOV @RSP+,IP
14962 MOV @IP+,PC
14963 ENDCODE
14964 [THEN]
14965
14966 [UNDEFINED] STATE [IF]
14967 \ https://forth-standard.org/standard/core/STATE
14968 \ STATE   -- a-addr       holds compiler state
14969 STATEADR CONSTANT STATE
14970 [THEN]
14971
14972 [UNDEFINED] = [IF]
14973 \ https://forth-standard.org/standard/core/Equal
14974 \ =      x1 x2 -- flag         test x1=x2
14975 CODE =
14976 SUB @PSP+,TOS   \ 2
14977 0<> IF          \ 2
14978     AND #0,TOS  \ 1
14979     MOV @IP+,PC \ 4
14980 THEN
14981 XOR #-1,TOS     \ 1 flag Z = 1
14982 MOV @IP+,PC     \ 4
14983 ENDCODE
14984 [THEN]
14985
14986 [UNDEFINED] IF [IF]
14987 \ https://forth-standard.org/standard/core/IF
14988 \ IF       -- IFadr    initialize conditional forward branch
14989 CODE IF       \ immediate
14990 SUB #2,PSP              \
14991 MOV TOS,0(PSP)          \
14992 MOV &DP,TOS             \ -- HERE
14993 ADD #4,&DP            \           compile one word, reserve one word
14994 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
14995 ADD #2,TOS              \ -- HERE+2=IFadr
14996 MOV @IP+,PC
14997 ENDCODE IMMEDIATE
14998 [THEN]
14999
15000 [UNDEFINED] THEN [IF]
15001 \ https://forth-standard.org/standard/core/THEN
15002 \ THEN     IFadr --                resolve forward branch
15003 CODE THEN               \ immediate
15004 MOV &DP,0(TOS)          \ -- IFadr
15005 MOV @PSP+,TOS           \ --
15006 MOV @IP+,PC
15007 ENDCODE IMMEDIATE
15008 [THEN]
15009
15010 [UNDEFINED] ELSE [IF]
15011 \ https://forth-standard.org/standard/core/ELSE
15012 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
15013 CODE ELSE     \ immediate
15014 ADD #4,&DP              \ make room to compile two words
15015 MOV &DP,W               \ W=HERE+4
15016 MOV #BRAN,-4(W)
15017 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
15018 SUB #2,W                \ HERE+2
15019 MOV W,TOS               \ -- ELSEadr
15020 MOV @IP+,PC
15021 ENDCODE IMMEDIATE
15022 [THEN]
15023
15024 [UNDEFINED] DEFER [IF]
15025 \ https://forth-standard.org/standard/core/DEFER
15026 \ DEFER "<spaces>name"   --
15027 \ Skip leading space delimiters. Parse name delimited by a space.
15028 \ Create a definition for name with the execution semantics defined below.
15029
15030 \ name Execution:   --
15031 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
15032 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
15033 : DEFER
15034 CREATE
15035 HI2LO
15036 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
15037 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
15038 MOV @RSP+,IP
15039 MOV @IP+,PC
15040 ENDCODE
15041 [THEN]
15042
15043 [UNDEFINED] DEFER! [IF]
15044 \ https://forth-standard.org/standard/core/DEFERStore
15045 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
15046 CODE DEFER!             \ xt2 xt1 --
15047 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
15048 MOV @PSP+,TOS           \ --
15049 MOV @IP+,PC
15050 ENDCODE
15051 [THEN]
15052
15053 [UNDEFINED] IS [IF]
15054 \ https://forth-standard.org/standard/core/IS
15055 \ IS <name>        xt --
15056 \ used as is :
15057 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
15058 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
15059 \ or in a definition : ... ['] U. IS DISPLAY ...
15060 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
15061 \
15062 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
15063 : IS
15064 STATE @
15065 IF  POSTPONE ['] POSTPONE DEFER! 
15066 ELSE ' DEFER! 
15067 THEN
15068 ; IMMEDIATE
15069 [THEN]
15070
15071 [UNDEFINED] >BODY [IF]
15072 \ https://forth-standard.org/standard/core/toBODY
15073 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
15074 CODE >BODY
15075 ADD #4,TOS
15076 MOV @IP+,PC
15077 ENDCODE
15078 [THEN]
15079
15080 \ CODE 20uS           \ n --      8MHz version
15081 \ BEGIN               \ 4 + 16 ~ loop
15082 \     MOV #39,rDOCON   \ 39
15083 \     BEGIN           \ 4 ~ loop
15084 \         NOP
15085 \         SUB #1,rDOCON
15086 \     0=  UNTIL
15087 \     SUB #1,TOS      \ 1
15088 \ 0= UNTIL
15089 \ MOV #XDOCON,rDOCON  \ 2
15090 \ MOV @PSP+,TOS
15091 \ MOV @RSP+,IP        \
15092 \ ENDCODE
15093
15094 CODE 20_US                      \ n --      n * 20 us
15095 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
15096     BEGIN
15097         BIT #1,&LCD_TIM_CTL     \ 3
15098     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
15099     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
15100     SUB #1,TOS                  \ 1
15101 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
15102 MOV @PSP+,TOS                   \ 2
15103 MOV @IP+,PC                     \ 4
15104 ENDCODE
15105
15106 CODE TOP_LCD                    \ LCD Sample
15107 \                               \ if write : %xxxx_WWWW --
15108 \                               \ if read  : -- %0000_RRRR
15109     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
15110     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
15111 0= IF                           \ write LCD bits pattern
15112     AND.B #LCD_DB,TOS           \ 
15113     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
15114     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
15115     MOV @PSP+,TOS               \
15116     MOV @IP+,PC
15117 THEN                            \ read LCD bits pattern
15118     SUB #2,PSP
15119     MOV TOS,0(PSP)
15120     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
15121     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
15122     AND.B #LCD_DB,TOS           \
15123     MOV @IP+,PC
15124 ENDCODE
15125
15126 CODE LCD_WRC                    \ char --         Write Char
15127     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
15128 BW1 SUB #2,PSP                  \
15129     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
15130     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
15131     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
15132     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
15133 COLON                           \ high level word starts here 
15134     TOP_LCD 2 20_US             \ write high nibble first
15135     TOP_LCD 2 20_US 
15136 ;
15137
15138 CODE LCD_WRF                    \ func --         Write Fonction
15139     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
15140     GOTO BW1
15141 ENDCODE
15142
15143 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
15144 : LCD_HOME $02 LCD_WRF 100 20_us ;
15145
15146 \ [UNDEFINED] OR [IF]
15147
15148 \ \ https://forth-standard.org/standard/core/OR
15149 \ \ C OR     x1 x2 -- x3           logical OR
15150 \ CODE OR
15151 \ BIS @PSP+,TOS
15152 \ MOV @IP+,PC
15153 \ ENDCODE
15154
15155 \ [THEN]
15156
15157 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
15158 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
15159 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
15160 \ : LCD_FN_SET        $20 OR LCD_WrF ;
15161 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
15162 \ : LCD_GOTO          $80 OR LCD_WrF ;
15163
15164
15165 \ CODE LCD_RDS                    \ -- status       Read Status
15166 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
15167 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
15168 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
15169 \ COLON                           \ starts a FORTH word
15170 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
15171 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
15172 \ HI2LO                           \ switch from FORTH to assembler
15173 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
15174 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
15175 \     MOV @RSP+,IP                \ restore IP saved by COLON
15176 \     MOV @IP+,PC                 \
15177 \ ENDCODE
15178
15179 \ CODE LCD_RDC                    \ -- char         Read Char
15180 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
15181 \     GOTO BW1
15182 \ ENDCODE
15183
15184
15185 \ ******************************\
15186 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
15187 \ ******************************\
15188 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
15189 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
15190 BIT.B #SW2,&SW2_IN              \ test switch S2
15191 0= IF                           \ case of switch S2 pressed
15192     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
15193     U< IF
15194         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
15195     THEN
15196 ELSE
15197     BIT.B #SW1,&SW1_IN          \ test switch S1 input
15198     0= IF                       \ case of Switch S1 pressed
15199         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
15200         U>= IF                  \
15201            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
15202         THEN                    \
15203     THEN                        \
15204 THEN                            \
15205 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
15206 RET                             \ 5
15207 ENDASM
15208
15209 \ ******************************\
15210 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
15211 \ ******************************\
15212 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
15213 \ ******************************\
15214 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
15215 \                               \       SMclock = 8|16|24 MHz
15216 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
15217 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
15218 \                               \       SR(9)=new Toggle bit memory (ADD on)
15219 \ ******************************\
15220 \ RC5_FirstStartBitHalfCycle:   \
15221 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
15222 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
15223 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
15224 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
15225 \ [THEN]
15226 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
15227     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
15228 [THEN]
15229 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
15230     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
15231 [THEN]
15232 MOV #1778,X                     \ RC5_Period * 1us
15233 MOV #14,W                       \ count of loop
15234 BEGIN                           \
15235 \ ******************************\
15236 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
15237 \ ******************************\                   |
15238 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
15239 \ RC5_Compute_3/4_Period:       \                   |
15240     RRUM    #1,X                \ X=1/2 cycle       |
15241     MOV     X,Y                 \                   ^
15242     RRUM    #1,Y                \ Y=1/4
15243     ADD     X,Y                 \ Y=3/4 cycle
15244     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
15245     U>= UNTIL                   \ 2
15246 \ ******************************\
15247 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
15248 \ ******************************\
15249     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
15250     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
15251     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
15252     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
15253     SUB     #1,W                \ decrement count loop
15254 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
15255 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
15256 0<> WHILE                       \ ----> out of loop ----+
15257     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
15258     BEGIN                       \                       |
15259         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
15260         CMP Y,X                 \ 1                     |   cycle time out of bound ?
15261         U>= IF                  \ 2                 ^   |   yes:
15262         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
15263         GOTO BW1                \                   |   |      quit on truncated RC5 message
15264         THEN                    \                   |   |
15265         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
15266     0<> UNTIL                   \ 2                 |   |
15267 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
15268 \ ******************************\                       |
15269 \ RC5_SampleEndOf:              \ <---------------------+
15270 \ ******************************\
15271 BIC #$30,&RC5_TIM_CTL           \   stop timer
15272 \ ******************************\
15273 \ RC5_ComputeNewRC5word         \
15274 \ ******************************\
15275 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
15276 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
15277 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
15278 \ ******************************\
15279 \ RC5_ComputeC6bit              \
15280 \ ******************************\
15281 BIT     #BIT14,T                \ test /C6 bit in T
15282 0= IF   BIS #BIT6,X             \ set C6 bit in X
15283 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
15284 \ ******************************\
15285 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
15286 \ ******************************\
15287 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
15288 \ ******************************\
15289 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
15290 XOR     @RSP,T                  \ (new XOR old) Toggle bits
15291 BIT     #UF10,T                 \ repeated RC5_command ?
15292 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
15293 XOR #UF10,0(RSP)                \ 5 toggle bit memory
15294 \ ******************************\
15295 \ Display IR_RC5 code           \
15296 \ ******************************\
15297 SUB #8,PSP                      \ TOS -- x x x x TOS
15298 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
15299 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
15300 MOV #$10,&BASEADR               \                                               set hexadecimal base
15301 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
15302 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
15303 LO2HI                           \                                               switch from assembler to FORTH
15304     LCD_CLEAR                   \                                               set LCD cursor at home
15305     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
15306     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
15307     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
15308     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
15309 HI2LO                           \     --                                        switch from FORTH to assembler
15310 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
15311 MOV @PSP+,TOS                   \     -- TOS
15312 RET
15313 ENDASM
15314
15315 \ ******************************\
15316 ASM BACKGROUND                  \
15317 \ ******************************\
15318 BEGIN
15319 \     ...                         \ insert here your background task
15320 \     ...                         \
15321 \     ...                         \
15322     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
15323     BIS &LPM_MODE,SR            \
15324 \ ******************************\
15325 \ here start all interrupts     \
15326 \ ******************************\
15327 \ here return all interrupts    \
15328 \ ******************************\
15329 AGAIN                           \
15330 ENDASM                          \
15331 \ ******************************\
15332
15333 \ ------------------------------\
15334 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
15335 \ ------------------------------\
15336 \     ...                         \ init specific I/O sys as you want
15337 \     ...                         \ before executing default WARM
15338     MOV #WARM,X                 \ ['] WARM 
15339     ADD #4,X                    \ >BODY
15340     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
15341 ENDASM
15342 \ ------------------------------\
15343
15344 \ ------------------------------\
15345 CODE STOP                       \ stops multitasking, must to be used before downloading app
15346 \ ------------------------------\
15347 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
15348     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
15349     MOV X,-2(X)                 \ restore the default background: SLEEP
15350     MOV #WARM,X
15351     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
15352     BIC.B #RC5,&IR_IE           \ clear RC5_Int
15353     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
15354     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
15355     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
15356     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
15357     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
15358 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
15359 ECHO                            \
15360 ." RC5toLCD is removed,"
15361 ."  type START to restart"
15362  WARM                           \ performs reset to reset all interrupt vectors.    
15363 ;
15364 \ ------------------------------\
15365
15366 \ ------------------------------\
15367 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
15368 \ ------------------------------\
15369 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
15370 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
15371 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
15372 \                           --       \ID input divider \ 10 = /4
15373 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
15374 \                                 -  \TBCLR TimerB Clear
15375 \                                  - \TBIE
15376 \                                   -\TBIFG
15377 \ -------------------------------\
15378 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
15379 \                  --                 \CM Capture Mode
15380 \                    --               \CCIS
15381 \                       -             \SCS
15382 \                        --           \CLLD
15383 \                          -          \CAP
15384 \                            ---      \OUTMOD \ 011 = set/reset
15385 \                               -     \CCIE
15386 \                                 -   \CCI
15387 \                                  -  \OUT
15388 \                                   - \COV
15389 \                                    -\CCIFG
15390 \ -------------------------------\
15391 \ LCD_TIM_CCRx                   \
15392 \ -------------------------------\
15393 \ LCD_TIM_EX0                    \ 
15394 \ ------------------------------\
15395 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
15396 \ ------------------------------\
15397 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
15398 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
15399 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
15400     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
15401 [THEN]
15402 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
15403     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
15404 [THEN]
15405     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
15406 \ ------------------------------\
15407 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
15408 \ ------------------------------\
15409 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
15410     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
15411 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
15412 \ ------------------------------\
15413     BIS.B #LCDVo,&LCDVo_DIR     \
15414     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
15415 \ ------------------------------\
15416     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
15417     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
15418 \ ------------------------------\
15419     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
15420     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
15421 \ ******************************\
15422 \ init RC5_Int                  \
15423 \ ******************************\
15424     BIS.B #RC5,&IR_IE           \ enable RC5_Int
15425     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
15426     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
15427 \ ******************************\
15428 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
15429 \ ******************************\
15430 \              %01 0001 0100    \ TAxCTL
15431 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
15432 \                  --           \ ID        divided by 1
15433 \                    --         \ MC        MODE = up to TAxCCRn
15434 \                        -      \ TACLR     clear timer count
15435 \                         -     \ TAIE
15436 \                          -    \ TAIFG
15437 \ ------------------------------\
15438 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
15439 \ ------------------------------\
15440 \                        000    \ TAxEX0
15441 \                        ---    \ TAIDEX    pre divisor
15442 \ ------------------------------\
15443 \          %0000 0000 0000 0101 \ TAxCCR0
15444     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
15445 \ ------------------------------\
15446 \          %0000 0000 0001 0000 \ TAxCCTL0
15447 \                   -           \ CAP capture/compare mode = compare
15448 \                        -      \ CCIEn
15449 \                             - \ CCIFGn
15450     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
15451 \ ------------------------------\
15452     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
15453 \ ------------------------------\
15454 \ define LPM mode for ACCEPT    \
15455 \ ------------------------------\
15456 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
15457 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
15458 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
15459 \ ------------------------------\
15460 \ activate I/O                  \
15461 \ ------------------------------\
15462 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
15463 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
15464 \ ------------------------------\
15465 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
15466 \ ------------------------------\
15467 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
15468 \ CMP #2,Y                        \ Power_ON event
15469 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
15470 CMP #4,Y                        \
15471 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
15472 \ CMP #6,Y                        \
15473 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
15474 \ CMP #$0A,Y                      \
15475 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
15476 \ CMP #$16,Y                      \
15477 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
15478 \ ------------------------------\
15479 COLON                           \
15480 \ ------------------------------\
15481 \ Init LCD 2x20                 \
15482 \ ------------------------------\
15483     #1000 20_US                 \ 1- wait 20 ms
15484     %011 TOP_LCD                \ 2- send DB5=DB4=1
15485     #205 20_US                  \ 3- wait 4,1 ms
15486     %011 TOP_LCD                \ 4- send again DB5=DB4=1
15487     #5 20_US                    \ 5- wait 0,1 ms
15488     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
15489     #2 20_US                    \    wait 40 us = LCD cycle
15490     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
15491     #2 20_US                    \    wait 40 us = LCD cycle
15492     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
15493     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
15494     LCD_CLEAR                   \ 10- "LCD_Clear"
15495     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
15496     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
15497     LCD_CLEAR                   \ 10- "LCD_Clear"
15498     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
15499     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
15500     CR ." I love you"           \ display message on LCD
15501     ['] CR >BODY IS CR          \ CR executes its default value
15502     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
15503     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
15504     PWR_STATE ABORT             \ init DP and continues with ABORT
15505 ;                               \
15506 \ ------------------------------\
15507
15508 \ ------------------------------\
15509 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
15510 \ ------------------------------\
15511 MOV #SLEEP,X                    \ replace default background process SLEEP
15512 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
15513 MOV #WARM,X                     \ replace default WARM
15514 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
15515 MOV X,PC                        \ then execute new WARM
15516 ENDCODE 
15517 \ ------------------------------\
15518
15519 ECHO
15520             ; downloading RC5toLCD.4th is done
15521 RST_HERE    ; this app is protected against <reset>
15522
15523
15524 RST_STATE
15525
15526 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
15527
15528 [UNDEFINED] MARKER [IF]
15529 \  https://forth-standard.org/standard/core/MARKER
15530 \  MARKER
15531 \ ( "<spaces>name" -- )
15532 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
15533 \ with the execution semantics defined below.
15534
15535 \ name Execution: ( -- )
15536 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
15537 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
15538 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
15539 \ not necessarily provided. No other contextual information such as numeric base is affected
15540 \
15541 : MARKER
15542 CREATE
15543 HI2LO
15544 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
15545 SUB #2,Y            \ 1 Y = LFA
15546 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
15547 ADD #4,&DP          \ 3 add 2 cells
15548 LO2HI
15549 DOES>
15550 HI2LO
15551 MOV @RSP+,IP        \ -- PFA
15552 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
15553 MOV @TOS,&INIDP     \       set DP value for RST_STATE
15554 MOV @PSP+,TOS       \ --
15555 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
15556 ENDCODE
15557 [THEN]
15558
15559 MARKER {RC5TOLCD}
15560
15561 [UNDEFINED] @ [IF]
15562 \ https://forth-standard.org/standard/core/Fetch
15563 \ @     c-addr -- char   fetch char from memory
15564 CODE @
15565 MOV @TOS,TOS
15566 MOV @IP+,PC
15567 ENDCODE
15568 [THEN]
15569
15570 [UNDEFINED] CONSTANT [IF]
15571 \ https://forth-standard.org/standard/core/CONSTANT
15572 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
15573 : CONSTANT 
15574 CREATE
15575 HI2LO
15576 MOV TOS,-2(W)           \   PFA = n
15577 MOV @PSP+,TOS
15578 MOV @RSP+,IP
15579 MOV @IP+,PC
15580 ENDCODE
15581 [THEN]
15582
15583 [UNDEFINED] STATE [IF]
15584 \ https://forth-standard.org/standard/core/STATE
15585 \ STATE   -- a-addr       holds compiler state
15586 STATEADR CONSTANT STATE
15587 [THEN]
15588
15589 [UNDEFINED] = [IF]
15590 \ https://forth-standard.org/standard/core/Equal
15591 \ =      x1 x2 -- flag         test x1=x2
15592 CODE =
15593 SUB @PSP+,TOS   \ 2
15594 0<> IF          \ 2
15595     AND #0,TOS  \ 1
15596     MOV @IP+,PC \ 4
15597 THEN
15598 XOR #-1,TOS     \ 1 flag Z = 1
15599 MOV @IP+,PC     \ 4
15600 ENDCODE
15601 [THEN]
15602
15603 [UNDEFINED] IF [IF]
15604 \ https://forth-standard.org/standard/core/IF
15605 \ IF       -- IFadr    initialize conditional forward branch
15606 CODE IF       \ immediate
15607 SUB #2,PSP              \
15608 MOV TOS,0(PSP)          \
15609 MOV &DP,TOS             \ -- HERE
15610 ADD #4,&DP            \           compile one word, reserve one word
15611 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
15612 ADD #2,TOS              \ -- HERE+2=IFadr
15613 MOV @IP+,PC
15614 ENDCODE IMMEDIATE
15615 [THEN]
15616
15617 [UNDEFINED] THEN [IF]
15618 \ https://forth-standard.org/standard/core/THEN
15619 \ THEN     IFadr --                resolve forward branch
15620 CODE THEN               \ immediate
15621 MOV &DP,0(TOS)          \ -- IFadr
15622 MOV @PSP+,TOS           \ --
15623 MOV @IP+,PC
15624 ENDCODE IMMEDIATE
15625 [THEN]
15626
15627 [UNDEFINED] ELSE [IF]
15628 \ https://forth-standard.org/standard/core/ELSE
15629 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
15630 CODE ELSE     \ immediate
15631 ADD #4,&DP              \ make room to compile two words
15632 MOV &DP,W               \ W=HERE+4
15633 MOV #BRAN,-4(W)
15634 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
15635 SUB #2,W                \ HERE+2
15636 MOV W,TOS               \ -- ELSEadr
15637 MOV @IP+,PC
15638 ENDCODE IMMEDIATE
15639 [THEN]
15640
15641 [UNDEFINED] DEFER [IF]
15642 \ https://forth-standard.org/standard/core/DEFER
15643 \ DEFER "<spaces>name"   --
15644 \ Skip leading space delimiters. Parse name delimited by a space.
15645 \ Create a definition for name with the execution semantics defined below.
15646
15647 \ name Execution:   --
15648 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
15649 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
15650 : DEFER
15651 CREATE
15652 HI2LO
15653 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
15654 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
15655 MOV @RSP+,IP
15656 MOV @IP+,PC
15657 ENDCODE
15658 [THEN]
15659
15660 [UNDEFINED] DEFER! [IF]
15661 \ https://forth-standard.org/standard/core/DEFERStore
15662 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
15663 CODE DEFER!             \ xt2 xt1 --
15664 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
15665 MOV @PSP+,TOS           \ --
15666 MOV @IP+,PC
15667 ENDCODE
15668 [THEN]
15669
15670 [UNDEFINED] IS [IF]
15671 \ https://forth-standard.org/standard/core/IS
15672 \ IS <name>        xt --
15673 \ used as is :
15674 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
15675 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
15676 \ or in a definition : ... ['] U. IS DISPLAY ...
15677 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
15678 \
15679 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
15680 : IS
15681 STATE @
15682 IF  POSTPONE ['] POSTPONE DEFER! 
15683 ELSE ' DEFER! 
15684 THEN
15685 ; IMMEDIATE
15686 [THEN]
15687
15688 [UNDEFINED] >BODY [IF]
15689 \ https://forth-standard.org/standard/core/toBODY
15690 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
15691 CODE >BODY
15692 ADD #4,TOS
15693 MOV @IP+,PC
15694 ENDCODE
15695 [THEN]
15696
15697 \ CODE 20uS           \ n --      8MHz version
15698 \ BEGIN               \ 4 + 16 ~ loop
15699 \     MOV #39,rDOCON   \ 39
15700 \     BEGIN           \ 4 ~ loop
15701 \         NOP
15702 \         SUB #1,rDOCON
15703 \     0=  UNTIL
15704 \     SUB #1,TOS      \ 1
15705 \ 0= UNTIL
15706 \ MOV #XDOCON,rDOCON  \ 2
15707 \ MOV @PSP+,TOS
15708 \ MOV @RSP+,IP        \
15709 \ ENDCODE
15710
15711 CODE 20_US                      \ n --      n * 20 us
15712 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
15713     BEGIN
15714         BIT #1,&LCD_TIM_CTL     \ 3
15715     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
15716     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
15717     SUB #1,TOS                  \ 1
15718 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
15719 MOV @PSP+,TOS                   \ 2
15720 MOV @IP+,PC                     \ 4
15721 ENDCODE
15722
15723 CODE TOP_LCD                    \ LCD Sample
15724 \                               \ if write : %xxxx_WWWW --
15725 \                               \ if read  : -- %0000_RRRR
15726     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
15727     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
15728 0= IF                           \ write LCD bits pattern
15729     AND.B #LCD_DB,TOS           \ 
15730     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
15731     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
15732     MOV @PSP+,TOS               \
15733     MOV @IP+,PC
15734 THEN                            \ read LCD bits pattern
15735     SUB #2,PSP
15736     MOV TOS,0(PSP)
15737     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
15738     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
15739     AND.B #LCD_DB,TOS           \
15740     MOV @IP+,PC
15741 ENDCODE
15742
15743 CODE LCD_WRC                    \ char --         Write Char
15744     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
15745 BW1 SUB #2,PSP                  \
15746     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
15747     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
15748     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
15749     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
15750 COLON                           \ high level word starts here 
15751     TOP_LCD 2 20_US             \ write high nibble first
15752     TOP_LCD 2 20_US 
15753 ;
15754
15755 CODE LCD_WRF                    \ func --         Write Fonction
15756     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
15757     GOTO BW1
15758 ENDCODE
15759
15760 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
15761 : LCD_HOME $02 LCD_WRF 100 20_us ;
15762
15763 \ [UNDEFINED] OR [IF]
15764
15765 \ \ https://forth-standard.org/standard/core/OR
15766 \ \ C OR     x1 x2 -- x3           logical OR
15767 \ CODE OR
15768 \ BIS @PSP+,TOS
15769 \ MOV @IP+,PC
15770 \ ENDCODE
15771
15772 \ [THEN]
15773
15774 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
15775 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
15776 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
15777 \ : LCD_FN_SET        $20 OR LCD_WrF ;
15778 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
15779 \ : LCD_GOTO          $80 OR LCD_WrF ;
15780
15781
15782 \ CODE LCD_RDS                    \ -- status       Read Status
15783 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
15784 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
15785 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
15786 \ COLON                           \ starts a FORTH word
15787 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
15788 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
15789 \ HI2LO                           \ switch from FORTH to assembler
15790 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
15791 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
15792 \     MOV @RSP+,IP                \ restore IP saved by COLON
15793 \     MOV @IP+,PC                 \
15794 \ ENDCODE
15795
15796 \ CODE LCD_RDC                    \ -- char         Read Char
15797 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
15798 \     GOTO BW1
15799 \ ENDCODE
15800
15801
15802 \ ******************************\
15803 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
15804 \ ******************************\
15805 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
15806 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
15807 BIT.B #SW2,&SW2_IN              \ test switch S2
15808 0= IF                           \ case of switch S2 pressed
15809     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
15810     U< IF
15811         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
15812     THEN
15813 ELSE
15814     BIT.B #SW1,&SW1_IN          \ test switch S1 input
15815     0= IF                       \ case of Switch S1 pressed
15816         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
15817         U>= IF                  \
15818            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
15819         THEN                    \
15820     THEN                        \
15821 THEN                            \
15822 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
15823 RET                             \ 5
15824 ENDASM
15825
15826 \ ******************************\
15827 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
15828 \ ******************************\
15829 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
15830 \ ******************************\
15831 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
15832 \                               \       SMclock = 8|16|24 MHz
15833 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
15834 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
15835 \                               \       SR(9)=new Toggle bit memory (ADD on)
15836 \ ******************************\
15837 \ RC5_FirstStartBitHalfCycle:   \
15838 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
15839 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
15840 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
15841 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
15842 \ [THEN]
15843 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
15844     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
15845 [THEN]
15846 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
15847     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
15848 [THEN]
15849 MOV #1778,X                     \ RC5_Period * 1us
15850 MOV #14,W                       \ count of loop
15851 BEGIN                           \
15852 \ ******************************\
15853 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
15854 \ ******************************\                   |
15855 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
15856 \ RC5_Compute_3/4_Period:       \                   |
15857     RRUM    #1,X                \ X=1/2 cycle       |
15858     MOV     X,Y                 \                   ^
15859     RRUM    #1,Y                \ Y=1/4
15860     ADD     X,Y                 \ Y=3/4 cycle
15861     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
15862     U>= UNTIL                   \ 2
15863 \ ******************************\
15864 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
15865 \ ******************************\
15866     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
15867     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
15868     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
15869     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
15870     SUB     #1,W                \ decrement count loop
15871 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
15872 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
15873 0<> WHILE                       \ ----> out of loop ----+
15874     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
15875     BEGIN                       \                       |
15876         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
15877         CMP Y,X                 \ 1                     |   cycle time out of bound ?
15878         U>= IF                  \ 2                 ^   |   yes:
15879         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
15880         GOTO BW1                \                   |   |      quit on truncated RC5 message
15881         THEN                    \                   |   |
15882         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
15883     0<> UNTIL                   \ 2                 |   |
15884 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
15885 \ ******************************\                       |
15886 \ RC5_SampleEndOf:              \ <---------------------+
15887 \ ******************************\
15888 BIC #$30,&RC5_TIM_CTL           \   stop timer
15889 \ ******************************\
15890 \ RC5_ComputeNewRC5word         \
15891 \ ******************************\
15892 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
15893 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
15894 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
15895 \ ******************************\
15896 \ RC5_ComputeC6bit              \
15897 \ ******************************\
15898 BIT     #BIT14,T                \ test /C6 bit in T
15899 0= IF   BIS #BIT6,X             \ set C6 bit in X
15900 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
15901 \ ******************************\
15902 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
15903 \ ******************************\
15904 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
15905 \ ******************************\
15906 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
15907 XOR     @RSP,T                  \ (new XOR old) Toggle bits
15908 BIT     #UF10,T                 \ repeated RC5_command ?
15909 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
15910 XOR #UF10,0(RSP)                \ 5 toggle bit memory
15911 \ ******************************\
15912 \ Display IR_RC5 code           \
15913 \ ******************************\
15914 SUB #8,PSP                      \ TOS -- x x x x TOS
15915 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
15916 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
15917 MOV #$10,&BASEADR               \                                               set hexadecimal base
15918 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
15919 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
15920 LO2HI                           \                                               switch from assembler to FORTH
15921     LCD_CLEAR                   \                                               set LCD cursor at home
15922     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
15923     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
15924     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
15925     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
15926 HI2LO                           \     --                                        switch from FORTH to assembler
15927 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
15928 MOV @PSP+,TOS                   \     -- TOS
15929 RET
15930 ENDASM
15931
15932 \ ******************************\
15933 ASM BACKGROUND                  \
15934 \ ******************************\
15935 BEGIN
15936 \     ...                         \ insert here your background task
15937 \     ...                         \
15938 \     ...                         \
15939     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
15940     BIS &LPM_MODE,SR            \
15941 \ ******************************\
15942 \ here start all interrupts     \
15943 \ ******************************\
15944 \ here return all interrupts    \
15945 \ ******************************\
15946 AGAIN                           \
15947 ENDASM                          \
15948 \ ******************************\
15949
15950 \ ------------------------------\
15951 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
15952 \ ------------------------------\
15953 \     ...                         \ init specific I/O sys as you want
15954 \     ...                         \ before executing default WARM
15955     MOV #WARM,X                 \ ['] WARM 
15956     ADD #4,X                    \ >BODY
15957     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
15958 ENDASM
15959 \ ------------------------------\
15960
15961 \ ------------------------------\
15962 CODE STOP                       \ stops multitasking, must to be used before downloading app
15963 \ ------------------------------\
15964 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
15965     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
15966     MOV X,-2(X)                 \ restore the default background: SLEEP
15967     MOV #WARM,X
15968     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
15969     BIC.B #RC5,&IR_IE           \ clear RC5_Int
15970     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
15971     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
15972     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
15973     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
15974     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
15975 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
15976 ECHO                            \
15977 ." RC5toLCD is removed,"
15978 ."  type START to restart"
15979  WARM                           \ performs reset to reset all interrupt vectors.    
15980 ;
15981 \ ------------------------------\
15982
15983 \ ------------------------------\
15984 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
15985 \ ------------------------------\
15986 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
15987 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
15988 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
15989 \                           --       \ID input divider \ 10 = /4
15990 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
15991 \                                 -  \TBCLR TimerB Clear
15992 \                                  - \TBIE
15993 \                                   -\TBIFG
15994 \ -------------------------------\
15995 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
15996 \                  --                 \CM Capture Mode
15997 \                    --               \CCIS
15998 \                       -             \SCS
15999 \                        --           \CLLD
16000 \                          -          \CAP
16001 \                            ---      \OUTMOD \ 011 = set/reset
16002 \                               -     \CCIE
16003 \                                 -   \CCI
16004 \                                  -  \OUT
16005 \                                   - \COV
16006 \                                    -\CCIFG
16007 \ -------------------------------\
16008 \ LCD_TIM_CCRx                   \
16009 \ -------------------------------\
16010 \ LCD_TIM_EX0                    \ 
16011 \ ------------------------------\
16012 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
16013 \ ------------------------------\
16014 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
16015 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
16016 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
16017     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
16018 [THEN]
16019 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
16020     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
16021 [THEN]
16022     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
16023 \ ------------------------------\
16024 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
16025 \ ------------------------------\
16026 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
16027     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
16028 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
16029 \ ------------------------------\
16030     BIS.B #LCDVo,&LCDVo_DIR     \
16031     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
16032 \ ------------------------------\
16033     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
16034     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
16035 \ ------------------------------\
16036     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
16037     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
16038 \ ******************************\
16039 \ init RC5_Int                  \
16040 \ ******************************\
16041     BIS.B #RC5,&IR_IE           \ enable RC5_Int
16042     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
16043     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
16044 \ ******************************\
16045 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
16046 \ ******************************\
16047 \              %01 0001 0100    \ TAxCTL
16048 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
16049 \                  --           \ ID        divided by 1
16050 \                    --         \ MC        MODE = up to TAxCCRn
16051 \                        -      \ TACLR     clear timer count
16052 \                         -     \ TAIE
16053 \                          -    \ TAIFG
16054 \ ------------------------------\
16055 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
16056 \ ------------------------------\
16057 \                        000    \ TAxEX0
16058 \                        ---    \ TAIDEX    pre divisor
16059 \ ------------------------------\
16060 \          %0000 0000 0000 0101 \ TAxCCR0
16061     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
16062 \ ------------------------------\
16063 \          %0000 0000 0001 0000 \ TAxCCTL0
16064 \                   -           \ CAP capture/compare mode = compare
16065 \                        -      \ CCIEn
16066 \                             - \ CCIFGn
16067     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
16068 \ ------------------------------\
16069     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
16070 \ ------------------------------\
16071 \ define LPM mode for ACCEPT    \
16072 \ ------------------------------\
16073 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
16074 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
16075 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
16076 \ ------------------------------\
16077 \ activate I/O                  \
16078 \ ------------------------------\
16079 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
16080 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
16081 \ ------------------------------\
16082 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
16083 \ ------------------------------\
16084 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
16085 \ CMP #2,Y                        \ Power_ON event
16086 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
16087 CMP #4,Y                        \
16088 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
16089 \ CMP #6,Y                        \
16090 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
16091 \ CMP #$0A,Y                      \
16092 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
16093 \ CMP #$16,Y                      \
16094 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
16095 \ ------------------------------\
16096 COLON                           \
16097 \ ------------------------------\
16098 \ Init LCD 2x20                 \
16099 \ ------------------------------\
16100     #1000 20_US                 \ 1- wait 20 ms
16101     %011 TOP_LCD                \ 2- send DB5=DB4=1
16102     #205 20_US                  \ 3- wait 4,1 ms
16103     %011 TOP_LCD                \ 4- send again DB5=DB4=1
16104     #5 20_US                    \ 5- wait 0,1 ms
16105     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
16106     #2 20_US                    \    wait 40 us = LCD cycle
16107     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
16108     #2 20_US                    \    wait 40 us = LCD cycle
16109     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
16110     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
16111     LCD_CLEAR                   \ 10- "LCD_Clear"
16112     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
16113     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
16114     LCD_CLEAR                   \ 10- "LCD_Clear"
16115     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
16116     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
16117     CR ." I love you"           \ display message on LCD
16118     ['] CR >BODY IS CR          \ CR executes its default value
16119     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
16120     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
16121     PWR_STATE ABORT             \ init DP and continues with ABORT
16122 ;                               \
16123 \ ------------------------------\
16124
16125 \ ------------------------------\
16126 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
16127 \ ------------------------------\
16128 MOV #SLEEP,X                    \ replace default background process SLEEP
16129 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
16130 MOV #WARM,X                     \ replace default WARM
16131 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
16132 MOV X,PC                        \ then execute new WARM
16133 ENDCODE 
16134 \ ------------------------------\
16135
16136 ECHO
16137             ; downloading RC5toLCD.4th is done
16138 RST_HERE    ; this app is protected against <reset>
16139
16140
16141 RST_STATE
16142
16143 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
16144
16145 [UNDEFINED] MARKER [IF]
16146 \  https://forth-standard.org/standard/core/MARKER
16147 \  MARKER
16148 \ ( "<spaces>name" -- )
16149 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
16150 \ with the execution semantics defined below.
16151
16152 \ name Execution: ( -- )
16153 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
16154 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
16155 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
16156 \ not necessarily provided. No other contextual information such as numeric base is affected
16157 \
16158 : MARKER
16159 CREATE
16160 HI2LO
16161 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
16162 SUB #2,Y            \ 1 Y = LFA
16163 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
16164 ADD #4,&DP          \ 3 add 2 cells
16165 LO2HI
16166 DOES>
16167 HI2LO
16168 MOV @RSP+,IP        \ -- PFA
16169 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
16170 MOV @TOS,&INIDP     \       set DP value for RST_STATE
16171 MOV @PSP+,TOS       \ --
16172 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
16173 ENDCODE
16174 [THEN]
16175
16176 MARKER {RC5TOLCD}
16177
16178 [UNDEFINED] @ [IF]
16179 \ https://forth-standard.org/standard/core/Fetch
16180 \ @     c-addr -- char   fetch char from memory
16181 CODE @
16182 MOV @TOS,TOS
16183 MOV @IP+,PC
16184 ENDCODE
16185 [THEN]
16186
16187 [UNDEFINED] CONSTANT [IF]
16188 \ https://forth-standard.org/standard/core/CONSTANT
16189 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
16190 : CONSTANT 
16191 CREATE
16192 HI2LO
16193 MOV TOS,-2(W)           \   PFA = n
16194 MOV @PSP+,TOS
16195 MOV @RSP+,IP
16196 MOV @IP+,PC
16197 ENDCODE
16198 [THEN]
16199
16200 [UNDEFINED] STATE [IF]
16201 \ https://forth-standard.org/standard/core/STATE
16202 \ STATE   -- a-addr       holds compiler state
16203 STATEADR CONSTANT STATE
16204 [THEN]
16205
16206 [UNDEFINED] = [IF]
16207 \ https://forth-standard.org/standard/core/Equal
16208 \ =      x1 x2 -- flag         test x1=x2
16209 CODE =
16210 SUB @PSP+,TOS   \ 2
16211 0<> IF          \ 2
16212     AND #0,TOS  \ 1
16213     MOV @IP+,PC \ 4
16214 THEN
16215 XOR #-1,TOS     \ 1 flag Z = 1
16216 MOV @IP+,PC     \ 4
16217 ENDCODE
16218 [THEN]
16219
16220 [UNDEFINED] IF [IF]
16221 \ https://forth-standard.org/standard/core/IF
16222 \ IF       -- IFadr    initialize conditional forward branch
16223 CODE IF       \ immediate
16224 SUB #2,PSP              \
16225 MOV TOS,0(PSP)          \
16226 MOV &DP,TOS             \ -- HERE
16227 ADD #4,&DP            \           compile one word, reserve one word
16228 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
16229 ADD #2,TOS              \ -- HERE+2=IFadr
16230 MOV @IP+,PC
16231 ENDCODE IMMEDIATE
16232 [THEN]
16233
16234 [UNDEFINED] THEN [IF]
16235 \ https://forth-standard.org/standard/core/THEN
16236 \ THEN     IFadr --                resolve forward branch
16237 CODE THEN               \ immediate
16238 MOV &DP,0(TOS)          \ -- IFadr
16239 MOV @PSP+,TOS           \ --
16240 MOV @IP+,PC
16241 ENDCODE IMMEDIATE
16242 [THEN]
16243
16244 [UNDEFINED] ELSE [IF]
16245 \ https://forth-standard.org/standard/core/ELSE
16246 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
16247 CODE ELSE     \ immediate
16248 ADD #4,&DP              \ make room to compile two words
16249 MOV &DP,W               \ W=HERE+4
16250 MOV #BRAN,-4(W)
16251 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
16252 SUB #2,W                \ HERE+2
16253 MOV W,TOS               \ -- ELSEadr
16254 MOV @IP+,PC
16255 ENDCODE IMMEDIATE
16256 [THEN]
16257
16258 [UNDEFINED] DEFER [IF]
16259 \ https://forth-standard.org/standard/core/DEFER
16260 \ DEFER "<spaces>name"   --
16261 \ Skip leading space delimiters. Parse name delimited by a space.
16262 \ Create a definition for name with the execution semantics defined below.
16263
16264 \ name Execution:   --
16265 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
16266 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
16267 : DEFER
16268 CREATE
16269 HI2LO
16270 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
16271 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
16272 MOV @RSP+,IP
16273 MOV @IP+,PC
16274 ENDCODE
16275 [THEN]
16276
16277 [UNDEFINED] DEFER! [IF]
16278 \ https://forth-standard.org/standard/core/DEFERStore
16279 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
16280 CODE DEFER!             \ xt2 xt1 --
16281 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
16282 MOV @PSP+,TOS           \ --
16283 MOV @IP+,PC
16284 ENDCODE
16285 [THEN]
16286
16287 [UNDEFINED] IS [IF]
16288 \ https://forth-standard.org/standard/core/IS
16289 \ IS <name>        xt --
16290 \ used as is :
16291 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
16292 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
16293 \ or in a definition : ... ['] U. IS DISPLAY ...
16294 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
16295 \
16296 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
16297 : IS
16298 STATE @
16299 IF  POSTPONE ['] POSTPONE DEFER! 
16300 ELSE ' DEFER! 
16301 THEN
16302 ; IMMEDIATE
16303 [THEN]
16304
16305 [UNDEFINED] >BODY [IF]
16306 \ https://forth-standard.org/standard/core/toBODY
16307 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
16308 CODE >BODY
16309 ADD #4,TOS
16310 MOV @IP+,PC
16311 ENDCODE
16312 [THEN]
16313
16314 \ CODE 20uS           \ n --      8MHz version
16315 \ BEGIN               \ 4 + 16 ~ loop
16316 \     MOV #39,rDOCON   \ 39
16317 \     BEGIN           \ 4 ~ loop
16318 \         NOP
16319 \         SUB #1,rDOCON
16320 \     0=  UNTIL
16321 \     SUB #1,TOS      \ 1
16322 \ 0= UNTIL
16323 \ MOV #XDOCON,rDOCON  \ 2
16324 \ MOV @PSP+,TOS
16325 \ MOV @RSP+,IP        \
16326 \ ENDCODE
16327
16328 CODE 20_US                      \ n --      n * 20 us
16329 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
16330     BEGIN
16331         BIT #1,&LCD_TIM_CTL     \ 3
16332     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
16333     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
16334     SUB #1,TOS                  \ 1
16335 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
16336 MOV @PSP+,TOS                   \ 2
16337 MOV @IP+,PC                     \ 4
16338 ENDCODE
16339
16340 CODE TOP_LCD                    \ LCD Sample
16341 \                               \ if write : %xxxx_WWWW --
16342 \                               \ if read  : -- %0000_RRRR
16343     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
16344     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
16345 0= IF                           \ write LCD bits pattern
16346     AND.B #LCD_DB,TOS           \ 
16347     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
16348     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
16349     MOV @PSP+,TOS               \
16350     MOV @IP+,PC
16351 THEN                            \ read LCD bits pattern
16352     SUB #2,PSP
16353     MOV TOS,0(PSP)
16354     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
16355     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
16356     AND.B #LCD_DB,TOS           \
16357     MOV @IP+,PC
16358 ENDCODE
16359
16360 CODE LCD_WRC                    \ char --         Write Char
16361     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
16362 BW1 SUB #2,PSP                  \
16363     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
16364     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
16365     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
16366     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
16367 COLON                           \ high level word starts here 
16368     TOP_LCD 2 20_US             \ write high nibble first
16369     TOP_LCD 2 20_US 
16370 ;
16371
16372 CODE LCD_WRF                    \ func --         Write Fonction
16373     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
16374     GOTO BW1
16375 ENDCODE
16376
16377 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
16378 : LCD_HOME $02 LCD_WRF 100 20_us ;
16379
16380 \ [UNDEFINED] OR [IF]
16381
16382 \ \ https://forth-standard.org/standard/core/OR
16383 \ \ C OR     x1 x2 -- x3           logical OR
16384 \ CODE OR
16385 \ BIS @PSP+,TOS
16386 \ MOV @IP+,PC
16387 \ ENDCODE
16388
16389 \ [THEN]
16390
16391 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
16392 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
16393 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
16394 \ : LCD_FN_SET        $20 OR LCD_WrF ;
16395 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
16396 \ : LCD_GOTO          $80 OR LCD_WrF ;
16397
16398
16399 \ CODE LCD_RDS                    \ -- status       Read Status
16400 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
16401 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
16402 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
16403 \ COLON                           \ starts a FORTH word
16404 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
16405 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
16406 \ HI2LO                           \ switch from FORTH to assembler
16407 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
16408 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
16409 \     MOV @RSP+,IP                \ restore IP saved by COLON
16410 \     MOV @IP+,PC                 \
16411 \ ENDCODE
16412
16413 \ CODE LCD_RDC                    \ -- char         Read Char
16414 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
16415 \     GOTO BW1
16416 \ ENDCODE
16417
16418
16419 \ ******************************\
16420 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
16421 \ ******************************\
16422 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
16423 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
16424 BIT.B #SW2,&SW2_IN              \ test switch S2
16425 0= IF                           \ case of switch S2 pressed
16426     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
16427     U< IF
16428         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
16429     THEN
16430 ELSE
16431     BIT.B #SW1,&SW1_IN          \ test switch S1 input
16432     0= IF                       \ case of Switch S1 pressed
16433         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
16434         U>= IF                  \
16435            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
16436         THEN                    \
16437     THEN                        \
16438 THEN                            \
16439 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
16440 RET                             \ 5
16441 ENDASM
16442
16443 \ ******************************\
16444 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
16445 \ ******************************\
16446 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
16447 \ ******************************\
16448 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
16449 \                               \       SMclock = 8|16|24 MHz
16450 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
16451 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
16452 \                               \       SR(9)=new Toggle bit memory (ADD on)
16453 \ ******************************\
16454 \ RC5_FirstStartBitHalfCycle:   \
16455 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
16456 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
16457 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
16458 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
16459 \ [THEN]
16460 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
16461     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
16462 [THEN]
16463 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
16464     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
16465 [THEN]
16466 MOV #1778,X                     \ RC5_Period * 1us
16467 MOV #14,W                       \ count of loop
16468 BEGIN                           \
16469 \ ******************************\
16470 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
16471 \ ******************************\                   |
16472 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
16473 \ RC5_Compute_3/4_Period:       \                   |
16474     RRUM    #1,X                \ X=1/2 cycle       |
16475     MOV     X,Y                 \                   ^
16476     RRUM    #1,Y                \ Y=1/4
16477     ADD     X,Y                 \ Y=3/4 cycle
16478     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
16479     U>= UNTIL                   \ 2
16480 \ ******************************\
16481 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
16482 \ ******************************\
16483     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
16484     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
16485     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
16486     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
16487     SUB     #1,W                \ decrement count loop
16488 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
16489 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
16490 0<> WHILE                       \ ----> out of loop ----+
16491     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
16492     BEGIN                       \                       |
16493         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
16494         CMP Y,X                 \ 1                     |   cycle time out of bound ?
16495         U>= IF                  \ 2                 ^   |   yes:
16496         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
16497         GOTO BW1                \                   |   |      quit on truncated RC5 message
16498         THEN                    \                   |   |
16499         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
16500     0<> UNTIL                   \ 2                 |   |
16501 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
16502 \ ******************************\                       |
16503 \ RC5_SampleEndOf:              \ <---------------------+
16504 \ ******************************\
16505 BIC #$30,&RC5_TIM_CTL           \   stop timer
16506 \ ******************************\
16507 \ RC5_ComputeNewRC5word         \
16508 \ ******************************\
16509 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
16510 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
16511 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
16512 \ ******************************\
16513 \ RC5_ComputeC6bit              \
16514 \ ******************************\
16515 BIT     #BIT14,T                \ test /C6 bit in T
16516 0= IF   BIS #BIT6,X             \ set C6 bit in X
16517 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
16518 \ ******************************\
16519 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
16520 \ ******************************\
16521 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
16522 \ ******************************\
16523 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
16524 XOR     @RSP,T                  \ (new XOR old) Toggle bits
16525 BIT     #UF10,T                 \ repeated RC5_command ?
16526 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
16527 XOR #UF10,0(RSP)                \ 5 toggle bit memory
16528 \ ******************************\
16529 \ Display IR_RC5 code           \
16530 \ ******************************\
16531 SUB #8,PSP                      \ TOS -- x x x x TOS
16532 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
16533 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
16534 MOV #$10,&BASEADR               \                                               set hexadecimal base
16535 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
16536 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
16537 LO2HI                           \                                               switch from assembler to FORTH
16538     LCD_CLEAR                   \                                               set LCD cursor at home
16539     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
16540     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
16541     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
16542     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
16543 HI2LO                           \     --                                        switch from FORTH to assembler
16544 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
16545 MOV @PSP+,TOS                   \     -- TOS
16546 RET
16547 ENDASM
16548
16549 \ ******************************\
16550 ASM BACKGROUND                  \
16551 \ ******************************\
16552 BEGIN
16553 \     ...                         \ insert here your background task
16554 \     ...                         \
16555 \     ...                         \
16556     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
16557     BIS &LPM_MODE,SR            \
16558 \ ******************************\
16559 \ here start all interrupts     \
16560 \ ******************************\
16561 \ here return all interrupts    \
16562 \ ******************************\
16563 AGAIN                           \
16564 ENDASM                          \
16565 \ ******************************\
16566
16567 \ ------------------------------\
16568 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
16569 \ ------------------------------\
16570 \     ...                         \ init specific I/O sys as you want
16571 \     ...                         \ before executing default WARM
16572     MOV #WARM,X                 \ ['] WARM 
16573     ADD #4,X                    \ >BODY
16574     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
16575 ENDASM
16576 \ ------------------------------\
16577
16578 \ ------------------------------\
16579 CODE STOP                       \ stops multitasking, must to be used before downloading app
16580 \ ------------------------------\
16581 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
16582     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
16583     MOV X,-2(X)                 \ restore the default background: SLEEP
16584     MOV #WARM,X
16585     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
16586     BIC.B #RC5,&IR_IE           \ clear RC5_Int
16587     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
16588     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
16589     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
16590     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
16591     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
16592 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
16593 ECHO                            \
16594 ." RC5toLCD is removed,"
16595 ."  type START to restart"
16596  WARM                           \ performs reset to reset all interrupt vectors.    
16597 ;
16598 \ ------------------------------\
16599
16600 \ ------------------------------\
16601 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
16602 \ ------------------------------\
16603 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
16604 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
16605 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
16606 \                           --       \ID input divider \ 10 = /4
16607 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
16608 \                                 -  \TBCLR TimerB Clear
16609 \                                  - \TBIE
16610 \                                   -\TBIFG
16611 \ -------------------------------\
16612 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
16613 \                  --                 \CM Capture Mode
16614 \                    --               \CCIS
16615 \                       -             \SCS
16616 \                        --           \CLLD
16617 \                          -          \CAP
16618 \                            ---      \OUTMOD \ 011 = set/reset
16619 \                               -     \CCIE
16620 \                                 -   \CCI
16621 \                                  -  \OUT
16622 \                                   - \COV
16623 \                                    -\CCIFG
16624 \ -------------------------------\
16625 \ LCD_TIM_CCRx                   \
16626 \ -------------------------------\
16627 \ LCD_TIM_EX0                    \ 
16628 \ ------------------------------\
16629 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
16630 \ ------------------------------\
16631 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
16632 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
16633 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
16634     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
16635 [THEN]
16636 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
16637     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
16638 [THEN]
16639     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
16640 \ ------------------------------\
16641 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
16642 \ ------------------------------\
16643 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
16644     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
16645 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
16646 \ ------------------------------\
16647     BIS.B #LCDVo,&LCDVo_DIR     \
16648     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
16649 \ ------------------------------\
16650     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
16651     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
16652 \ ------------------------------\
16653     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
16654     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
16655 \ ******************************\
16656 \ init RC5_Int                  \
16657 \ ******************************\
16658     BIS.B #RC5,&IR_IE           \ enable RC5_Int
16659     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
16660     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
16661 \ ******************************\
16662 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
16663 \ ******************************\
16664 \              %01 0001 0100    \ TAxCTL
16665 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
16666 \                  --           \ ID        divided by 1
16667 \                    --         \ MC        MODE = up to TAxCCRn
16668 \                        -      \ TACLR     clear timer count
16669 \                         -     \ TAIE
16670 \                          -    \ TAIFG
16671 \ ------------------------------\
16672 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
16673 \ ------------------------------\
16674 \                        000    \ TAxEX0
16675 \                        ---    \ TAIDEX    pre divisor
16676 \ ------------------------------\
16677 \          %0000 0000 0000 0101 \ TAxCCR0
16678     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
16679 \ ------------------------------\
16680 \          %0000 0000 0001 0000 \ TAxCCTL0
16681 \                   -           \ CAP capture/compare mode = compare
16682 \                        -      \ CCIEn
16683 \                             - \ CCIFGn
16684     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
16685 \ ------------------------------\
16686     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
16687 \ ------------------------------\
16688 \ define LPM mode for ACCEPT    \
16689 \ ------------------------------\
16690 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
16691 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
16692 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
16693 \ ------------------------------\
16694 \ activate I/O                  \
16695 \ ------------------------------\
16696 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
16697 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
16698 \ ------------------------------\
16699 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
16700 \ ------------------------------\
16701 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
16702 \ CMP #2,Y                        \ Power_ON event
16703 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
16704 CMP #4,Y                        \
16705 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
16706 \ CMP #6,Y                        \
16707 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
16708 \ CMP #$0A,Y                      \
16709 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
16710 \ CMP #$16,Y                      \
16711 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
16712 \ ------------------------------\
16713 COLON                           \
16714 \ ------------------------------\
16715 \ Init LCD 2x20                 \
16716 \ ------------------------------\
16717     #1000 20_US                 \ 1- wait 20 ms
16718     %011 TOP_LCD                \ 2- send DB5=DB4=1
16719     #205 20_US                  \ 3- wait 4,1 ms
16720     %011 TOP_LCD                \ 4- send again DB5=DB4=1
16721     #5 20_US                    \ 5- wait 0,1 ms
16722     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
16723     #2 20_US                    \    wait 40 us = LCD cycle
16724     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
16725     #2 20_US                    \    wait 40 us = LCD cycle
16726     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
16727     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
16728     LCD_CLEAR                   \ 10- "LCD_Clear"
16729     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
16730     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
16731     LCD_CLEAR                   \ 10- "LCD_Clear"
16732     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
16733     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
16734     CR ." I love you"           \ display message on LCD
16735     ['] CR >BODY IS CR          \ CR executes its default value
16736     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
16737     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
16738     PWR_STATE ABORT             \ init DP and continues with ABORT
16739 ;                               \
16740 \ ------------------------------\
16741
16742 \ ------------------------------\
16743 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
16744 \ ------------------------------\
16745 MOV #SLEEP,X                    \ replace default background process SLEEP
16746 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
16747 MOV #WARM,X                     \ replace default WARM
16748 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
16749 MOV X,PC                        \ then execute new WARM
16750 ENDCODE 
16751 \ ------------------------------\
16752
16753 ECHO
16754             ; downloading RC5toLCD.4th is done
16755 RST_HERE    ; this app is protected against <reset>
16756
16757
16758 RST_STATE
16759
16760 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
16761
16762 [UNDEFINED] MARKER [IF]
16763 \  https://forth-standard.org/standard/core/MARKER
16764 \  MARKER
16765 \ ( "<spaces>name" -- )
16766 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
16767 \ with the execution semantics defined below.
16768
16769 \ name Execution: ( -- )
16770 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
16771 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
16772 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
16773 \ not necessarily provided. No other contextual information such as numeric base is affected
16774 \
16775 : MARKER
16776 CREATE
16777 HI2LO
16778 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
16779 SUB #2,Y            \ 1 Y = LFA
16780 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
16781 ADD #4,&DP          \ 3 add 2 cells
16782 LO2HI
16783 DOES>
16784 HI2LO
16785 MOV @RSP+,IP        \ -- PFA
16786 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
16787 MOV @TOS,&INIDP     \       set DP value for RST_STATE
16788 MOV @PSP+,TOS       \ --
16789 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
16790 ENDCODE
16791 [THEN]
16792
16793 MARKER {RC5TOLCD}
16794
16795 [UNDEFINED] @ [IF]
16796 \ https://forth-standard.org/standard/core/Fetch
16797 \ @     c-addr -- char   fetch char from memory
16798 CODE @
16799 MOV @TOS,TOS
16800 MOV @IP+,PC
16801 ENDCODE
16802 [THEN]
16803
16804 [UNDEFINED] CONSTANT [IF]
16805 \ https://forth-standard.org/standard/core/CONSTANT
16806 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
16807 : CONSTANT 
16808 CREATE
16809 HI2LO
16810 MOV TOS,-2(W)           \   PFA = n
16811 MOV @PSP+,TOS
16812 MOV @RSP+,IP
16813 MOV @IP+,PC
16814 ENDCODE
16815 [THEN]
16816
16817 [UNDEFINED] STATE [IF]
16818 \ https://forth-standard.org/standard/core/STATE
16819 \ STATE   -- a-addr       holds compiler state
16820 STATEADR CONSTANT STATE
16821 [THEN]
16822
16823 [UNDEFINED] = [IF]
16824 \ https://forth-standard.org/standard/core/Equal
16825 \ =      x1 x2 -- flag         test x1=x2
16826 CODE =
16827 SUB @PSP+,TOS   \ 2
16828 0<> IF          \ 2
16829     AND #0,TOS  \ 1
16830     MOV @IP+,PC \ 4
16831 THEN
16832 XOR #-1,TOS     \ 1 flag Z = 1
16833 MOV @IP+,PC     \ 4
16834 ENDCODE
16835 [THEN]
16836
16837 [UNDEFINED] IF [IF]
16838 \ https://forth-standard.org/standard/core/IF
16839 \ IF       -- IFadr    initialize conditional forward branch
16840 CODE IF       \ immediate
16841 SUB #2,PSP              \
16842 MOV TOS,0(PSP)          \
16843 MOV &DP,TOS             \ -- HERE
16844 ADD #4,&DP            \           compile one word, reserve one word
16845 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
16846 ADD #2,TOS              \ -- HERE+2=IFadr
16847 MOV @IP+,PC
16848 ENDCODE IMMEDIATE
16849 [THEN]
16850
16851 [UNDEFINED] THEN [IF]
16852 \ https://forth-standard.org/standard/core/THEN
16853 \ THEN     IFadr --                resolve forward branch
16854 CODE THEN               \ immediate
16855 MOV &DP,0(TOS)          \ -- IFadr
16856 MOV @PSP+,TOS           \ --
16857 MOV @IP+,PC
16858 ENDCODE IMMEDIATE
16859 [THEN]
16860
16861 [UNDEFINED] ELSE [IF]
16862 \ https://forth-standard.org/standard/core/ELSE
16863 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
16864 CODE ELSE     \ immediate
16865 ADD #4,&DP              \ make room to compile two words
16866 MOV &DP,W               \ W=HERE+4
16867 MOV #BRAN,-4(W)
16868 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
16869 SUB #2,W                \ HERE+2
16870 MOV W,TOS               \ -- ELSEadr
16871 MOV @IP+,PC
16872 ENDCODE IMMEDIATE
16873 [THEN]
16874
16875 [UNDEFINED] DEFER [IF]
16876 \ https://forth-standard.org/standard/core/DEFER
16877 \ DEFER "<spaces>name"   --
16878 \ Skip leading space delimiters. Parse name delimited by a space.
16879 \ Create a definition for name with the execution semantics defined below.
16880
16881 \ name Execution:   --
16882 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
16883 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
16884 : DEFER
16885 CREATE
16886 HI2LO
16887 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
16888 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
16889 MOV @RSP+,IP
16890 MOV @IP+,PC
16891 ENDCODE
16892 [THEN]
16893
16894 [UNDEFINED] DEFER! [IF]
16895 \ https://forth-standard.org/standard/core/DEFERStore
16896 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
16897 CODE DEFER!             \ xt2 xt1 --
16898 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
16899 MOV @PSP+,TOS           \ --
16900 MOV @IP+,PC
16901 ENDCODE
16902 [THEN]
16903
16904 [UNDEFINED] IS [IF]
16905 \ https://forth-standard.org/standard/core/IS
16906 \ IS <name>        xt --
16907 \ used as is :
16908 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
16909 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
16910 \ or in a definition : ... ['] U. IS DISPLAY ...
16911 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
16912 \
16913 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
16914 : IS
16915 STATE @
16916 IF  POSTPONE ['] POSTPONE DEFER! 
16917 ELSE ' DEFER! 
16918 THEN
16919 ; IMMEDIATE
16920 [THEN]
16921
16922 [UNDEFINED] >BODY [IF]
16923 \ https://forth-standard.org/standard/core/toBODY
16924 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
16925 CODE >BODY
16926 ADD #4,TOS
16927 MOV @IP+,PC
16928 ENDCODE
16929 [THEN]
16930
16931 \ CODE 20uS           \ n --      8MHz version
16932 \ BEGIN               \ 4 + 16 ~ loop
16933 \     MOV #39,rDOCON   \ 39
16934 \     BEGIN           \ 4 ~ loop
16935 \         NOP
16936 \         SUB #1,rDOCON
16937 \     0=  UNTIL
16938 \     SUB #1,TOS      \ 1
16939 \ 0= UNTIL
16940 \ MOV #XDOCON,rDOCON  \ 2
16941 \ MOV @PSP+,TOS
16942 \ MOV @RSP+,IP        \
16943 \ ENDCODE
16944
16945 CODE 20_US                      \ n --      n * 20 us
16946 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
16947     BEGIN
16948         BIT #1,&LCD_TIM_CTL     \ 3
16949     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
16950     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
16951     SUB #1,TOS                  \ 1
16952 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
16953 MOV @PSP+,TOS                   \ 2
16954 MOV @IP+,PC                     \ 4
16955 ENDCODE
16956
16957 CODE TOP_LCD                    \ LCD Sample
16958 \                               \ if write : %xxxx_WWWW --
16959 \                               \ if read  : -- %0000_RRRR
16960     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
16961     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
16962 0= IF                           \ write LCD bits pattern
16963     AND.B #LCD_DB,TOS           \ 
16964     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
16965     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
16966     MOV @PSP+,TOS               \
16967     MOV @IP+,PC
16968 THEN                            \ read LCD bits pattern
16969     SUB #2,PSP
16970     MOV TOS,0(PSP)
16971     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
16972     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
16973     AND.B #LCD_DB,TOS           \
16974     MOV @IP+,PC
16975 ENDCODE
16976
16977 CODE LCD_WRC                    \ char --         Write Char
16978     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
16979 BW1 SUB #2,PSP                  \
16980     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
16981     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
16982     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
16983     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
16984 COLON                           \ high level word starts here 
16985     TOP_LCD 2 20_US             \ write high nibble first
16986     TOP_LCD 2 20_US 
16987 ;
16988
16989 CODE LCD_WRF                    \ func --         Write Fonction
16990     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
16991     GOTO BW1
16992 ENDCODE
16993
16994 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
16995 : LCD_HOME $02 LCD_WRF 100 20_us ;
16996
16997 \ [UNDEFINED] OR [IF]
16998
16999 \ \ https://forth-standard.org/standard/core/OR
17000 \ \ C OR     x1 x2 -- x3           logical OR
17001 \ CODE OR
17002 \ BIS @PSP+,TOS
17003 \ MOV @IP+,PC
17004 \ ENDCODE
17005
17006 \ [THEN]
17007
17008 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
17009 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
17010 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
17011 \ : LCD_FN_SET        $20 OR LCD_WrF ;
17012 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
17013 \ : LCD_GOTO          $80 OR LCD_WrF ;
17014
17015
17016 \ CODE LCD_RDS                    \ -- status       Read Status
17017 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
17018 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
17019 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
17020 \ COLON                           \ starts a FORTH word
17021 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
17022 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
17023 \ HI2LO                           \ switch from FORTH to assembler
17024 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
17025 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
17026 \     MOV @RSP+,IP                \ restore IP saved by COLON
17027 \     MOV @IP+,PC                 \
17028 \ ENDCODE
17029
17030 \ CODE LCD_RDC                    \ -- char         Read Char
17031 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
17032 \     GOTO BW1
17033 \ ENDCODE
17034
17035
17036 \ ******************************\
17037 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
17038 \ ******************************\
17039 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
17040 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
17041 BIT.B #SW2,&SW2_IN              \ test switch S2
17042 0= IF                           \ case of switch S2 pressed
17043     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
17044     U< IF
17045         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
17046     THEN
17047 ELSE
17048     BIT.B #SW1,&SW1_IN          \ test switch S1 input
17049     0= IF                       \ case of Switch S1 pressed
17050         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
17051         U>= IF                  \
17052            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
17053         THEN                    \
17054     THEN                        \
17055 THEN                            \
17056 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
17057 RET                             \ 5
17058 ENDASM
17059
17060 \ ******************************\
17061 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
17062 \ ******************************\
17063 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
17064 \ ******************************\
17065 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
17066 \                               \       SMclock = 8|16|24 MHz
17067 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
17068 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
17069 \                               \       SR(9)=new Toggle bit memory (ADD on)
17070 \ ******************************\
17071 \ RC5_FirstStartBitHalfCycle:   \
17072 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
17073 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
17074 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
17075 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
17076 \ [THEN]
17077 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
17078     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
17079 [THEN]
17080 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
17081     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
17082 [THEN]
17083 MOV #1778,X                     \ RC5_Period * 1us
17084 MOV #14,W                       \ count of loop
17085 BEGIN                           \
17086 \ ******************************\
17087 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
17088 \ ******************************\                   |
17089 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
17090 \ RC5_Compute_3/4_Period:       \                   |
17091     RRUM    #1,X                \ X=1/2 cycle       |
17092     MOV     X,Y                 \                   ^
17093     RRUM    #1,Y                \ Y=1/4
17094     ADD     X,Y                 \ Y=3/4 cycle
17095     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
17096     U>= UNTIL                   \ 2
17097 \ ******************************\
17098 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
17099 \ ******************************\
17100     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
17101     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
17102     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
17103     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
17104     SUB     #1,W                \ decrement count loop
17105 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
17106 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
17107 0<> WHILE                       \ ----> out of loop ----+
17108     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
17109     BEGIN                       \                       |
17110         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
17111         CMP Y,X                 \ 1                     |   cycle time out of bound ?
17112         U>= IF                  \ 2                 ^   |   yes:
17113         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
17114         GOTO BW1                \                   |   |      quit on truncated RC5 message
17115         THEN                    \                   |   |
17116         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
17117     0<> UNTIL                   \ 2                 |   |
17118 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
17119 \ ******************************\                       |
17120 \ RC5_SampleEndOf:              \ <---------------------+
17121 \ ******************************\
17122 BIC #$30,&RC5_TIM_CTL           \   stop timer
17123 \ ******************************\
17124 \ RC5_ComputeNewRC5word         \
17125 \ ******************************\
17126 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
17127 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
17128 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
17129 \ ******************************\
17130 \ RC5_ComputeC6bit              \
17131 \ ******************************\
17132 BIT     #BIT14,T                \ test /C6 bit in T
17133 0= IF   BIS #BIT6,X             \ set C6 bit in X
17134 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
17135 \ ******************************\
17136 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
17137 \ ******************************\
17138 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
17139 \ ******************************\
17140 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
17141 XOR     @RSP,T                  \ (new XOR old) Toggle bits
17142 BIT     #UF10,T                 \ repeated RC5_command ?
17143 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
17144 XOR #UF10,0(RSP)                \ 5 toggle bit memory
17145 \ ******************************\
17146 \ Display IR_RC5 code           \
17147 \ ******************************\
17148 SUB #8,PSP                      \ TOS -- x x x x TOS
17149 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
17150 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
17151 MOV #$10,&BASEADR               \                                               set hexadecimal base
17152 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
17153 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
17154 LO2HI                           \                                               switch from assembler to FORTH
17155     LCD_CLEAR                   \                                               set LCD cursor at home
17156     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
17157     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
17158     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
17159     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
17160 HI2LO                           \     --                                        switch from FORTH to assembler
17161 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
17162 MOV @PSP+,TOS                   \     -- TOS
17163 RET
17164 ENDASM
17165
17166 \ ******************************\
17167 ASM BACKGROUND                  \
17168 \ ******************************\
17169 BEGIN
17170 \     ...                         \ insert here your background task
17171 \     ...                         \
17172 \     ...                         \
17173     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
17174     BIS &LPM_MODE,SR            \
17175 \ ******************************\
17176 \ here start all interrupts     \
17177 \ ******************************\
17178 \ here return all interrupts    \
17179 \ ******************************\
17180 AGAIN                           \
17181 ENDASM                          \
17182 \ ******************************\
17183
17184 \ ------------------------------\
17185 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
17186 \ ------------------------------\
17187 \     ...                         \ init specific I/O sys as you want
17188 \     ...                         \ before executing default WARM
17189     MOV #WARM,X                 \ ['] WARM 
17190     ADD #4,X                    \ >BODY
17191     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
17192 ENDASM
17193 \ ------------------------------\
17194
17195 \ ------------------------------\
17196 CODE STOP                       \ stops multitasking, must to be used before downloading app
17197 \ ------------------------------\
17198 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
17199     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
17200     MOV X,-2(X)                 \ restore the default background: SLEEP
17201     MOV #WARM,X
17202     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
17203     BIC.B #RC5,&IR_IE           \ clear RC5_Int
17204     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
17205     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
17206     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
17207     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
17208     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
17209 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
17210 ECHO                            \
17211 ." RC5toLCD is removed,"
17212 ."  type START to restart"
17213  WARM                           \ performs reset to reset all interrupt vectors.    
17214 ;
17215 \ ------------------------------\
17216
17217 \ ------------------------------\
17218 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
17219 \ ------------------------------\
17220 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
17221 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
17222 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
17223 \                           --       \ID input divider \ 10 = /4
17224 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
17225 \                                 -  \TBCLR TimerB Clear
17226 \                                  - \TBIE
17227 \                                   -\TBIFG
17228 \ -------------------------------\
17229 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
17230 \                  --                 \CM Capture Mode
17231 \                    --               \CCIS
17232 \                       -             \SCS
17233 \                        --           \CLLD
17234 \                          -          \CAP
17235 \                            ---      \OUTMOD \ 011 = set/reset
17236 \                               -     \CCIE
17237 \                                 -   \CCI
17238 \                                  -  \OUT
17239 \                                   - \COV
17240 \                                    -\CCIFG
17241 \ -------------------------------\
17242 \ LCD_TIM_CCRx                   \
17243 \ -------------------------------\
17244 \ LCD_TIM_EX0                    \ 
17245 \ ------------------------------\
17246 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
17247 \ ------------------------------\
17248 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
17249 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
17250 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
17251     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
17252 [THEN]
17253 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
17254     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
17255 [THEN]
17256     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
17257 \ ------------------------------\
17258 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
17259 \ ------------------------------\
17260 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
17261     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
17262 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
17263 \ ------------------------------\
17264     BIS.B #LCDVo,&LCDVo_DIR     \
17265     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
17266 \ ------------------------------\
17267     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
17268     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
17269 \ ------------------------------\
17270     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
17271     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
17272 \ ******************************\
17273 \ init RC5_Int                  \
17274 \ ******************************\
17275     BIS.B #RC5,&IR_IE           \ enable RC5_Int
17276     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
17277     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
17278 \ ******************************\
17279 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
17280 \ ******************************\
17281 \              %01 0001 0100    \ TAxCTL
17282 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
17283 \                  --           \ ID        divided by 1
17284 \                    --         \ MC        MODE = up to TAxCCRn
17285 \                        -      \ TACLR     clear timer count
17286 \                         -     \ TAIE
17287 \                          -    \ TAIFG
17288 \ ------------------------------\
17289 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
17290 \ ------------------------------\
17291 \                        000    \ TAxEX0
17292 \                        ---    \ TAIDEX    pre divisor
17293 \ ------------------------------\
17294 \          %0000 0000 0000 0101 \ TAxCCR0
17295     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
17296 \ ------------------------------\
17297 \          %0000 0000 0001 0000 \ TAxCCTL0
17298 \                   -           \ CAP capture/compare mode = compare
17299 \                        -      \ CCIEn
17300 \                             - \ CCIFGn
17301     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
17302 \ ------------------------------\
17303     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
17304 \ ------------------------------\
17305 \ define LPM mode for ACCEPT    \
17306 \ ------------------------------\
17307 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
17308 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
17309 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
17310 \ ------------------------------\
17311 \ activate I/O                  \
17312 \ ------------------------------\
17313 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
17314 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
17315 \ ------------------------------\
17316 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
17317 \ ------------------------------\
17318 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
17319 \ CMP #2,Y                        \ Power_ON event
17320 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
17321 CMP #4,Y                        \
17322 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
17323 \ CMP #6,Y                        \
17324 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
17325 \ CMP #$0A,Y                      \
17326 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
17327 \ CMP #$16,Y                      \
17328 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
17329 \ ------------------------------\
17330 COLON                           \
17331 \ ------------------------------\
17332 \ Init LCD 2x20                 \
17333 \ ------------------------------\
17334     #1000 20_US                 \ 1- wait 20 ms
17335     %011 TOP_LCD                \ 2- send DB5=DB4=1
17336     #205 20_US                  \ 3- wait 4,1 ms
17337     %011 TOP_LCD                \ 4- send again DB5=DB4=1
17338     #5 20_US                    \ 5- wait 0,1 ms
17339     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
17340     #2 20_US                    \    wait 40 us = LCD cycle
17341     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
17342     #2 20_US                    \    wait 40 us = LCD cycle
17343     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
17344     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
17345     LCD_CLEAR                   \ 10- "LCD_Clear"
17346     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
17347     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
17348     LCD_CLEAR                   \ 10- "LCD_Clear"
17349     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
17350     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
17351     CR ." I love you"           \ display message on LCD
17352     ['] CR >BODY IS CR          \ CR executes its default value
17353     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
17354     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
17355     PWR_STATE ABORT             \ init DP and continues with ABORT
17356 ;                               \
17357 \ ------------------------------\
17358
17359 \ ------------------------------\
17360 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
17361 \ ------------------------------\
17362 MOV #SLEEP,X                    \ replace default background process SLEEP
17363 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
17364 MOV #WARM,X                     \ replace default WARM
17365 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
17366 MOV X,PC                        \ then execute new WARM
17367 ENDCODE 
17368 \ ------------------------------\
17369
17370 ECHO
17371             ; downloading RC5toLCD.4th is done
17372 RST_HERE    ; this app is protected against <reset>
17373
17374
17375 RST_STATE
17376
17377 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
17378
17379 [UNDEFINED] MARKER [IF]
17380 \  https://forth-standard.org/standard/core/MARKER
17381 \  MARKER
17382 \ ( "<spaces>name" -- )
17383 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
17384 \ with the execution semantics defined below.
17385
17386 \ name Execution: ( -- )
17387 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
17388 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
17389 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
17390 \ not necessarily provided. No other contextual information such as numeric base is affected
17391 \
17392 : MARKER
17393 CREATE
17394 HI2LO
17395 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
17396 SUB #2,Y            \ 1 Y = LFA
17397 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
17398 ADD #4,&DP          \ 3 add 2 cells
17399 LO2HI
17400 DOES>
17401 HI2LO
17402 MOV @RSP+,IP        \ -- PFA
17403 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
17404 MOV @TOS,&INIDP     \       set DP value for RST_STATE
17405 MOV @PSP+,TOS       \ --
17406 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
17407 ENDCODE
17408 [THEN]
17409
17410 MARKER {RC5TOLCD}
17411
17412 [UNDEFINED] @ [IF]
17413 \ https://forth-standard.org/standard/core/Fetch
17414 \ @     c-addr -- char   fetch char from memory
17415 CODE @
17416 MOV @TOS,TOS
17417 MOV @IP+,PC
17418 ENDCODE
17419 [THEN]
17420
17421 [UNDEFINED] CONSTANT [IF]
17422 \ https://forth-standard.org/standard/core/CONSTANT
17423 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
17424 : CONSTANT 
17425 CREATE
17426 HI2LO
17427 MOV TOS,-2(W)           \   PFA = n
17428 MOV @PSP+,TOS
17429 MOV @RSP+,IP
17430 MOV @IP+,PC
17431 ENDCODE
17432 [THEN]
17433
17434 [UNDEFINED] STATE [IF]
17435 \ https://forth-standard.org/standard/core/STATE
17436 \ STATE   -- a-addr       holds compiler state
17437 STATEADR CONSTANT STATE
17438 [THEN]
17439
17440 [UNDEFINED] = [IF]
17441 \ https://forth-standard.org/standard/core/Equal
17442 \ =      x1 x2 -- flag         test x1=x2
17443 CODE =
17444 SUB @PSP+,TOS   \ 2
17445 0<> IF          \ 2
17446     AND #0,TOS  \ 1
17447     MOV @IP+,PC \ 4
17448 THEN
17449 XOR #-1,TOS     \ 1 flag Z = 1
17450 MOV @IP+,PC     \ 4
17451 ENDCODE
17452 [THEN]
17453
17454 [UNDEFINED] IF [IF]
17455 \ https://forth-standard.org/standard/core/IF
17456 \ IF       -- IFadr    initialize conditional forward branch
17457 CODE IF       \ immediate
17458 SUB #2,PSP              \
17459 MOV TOS,0(PSP)          \
17460 MOV &DP,TOS             \ -- HERE
17461 ADD #4,&DP            \           compile one word, reserve one word
17462 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
17463 ADD #2,TOS              \ -- HERE+2=IFadr
17464 MOV @IP+,PC
17465 ENDCODE IMMEDIATE
17466 [THEN]
17467
17468 [UNDEFINED] THEN [IF]
17469 \ https://forth-standard.org/standard/core/THEN
17470 \ THEN     IFadr --                resolve forward branch
17471 CODE THEN               \ immediate
17472 MOV &DP,0(TOS)          \ -- IFadr
17473 MOV @PSP+,TOS           \ --
17474 MOV @IP+,PC
17475 ENDCODE IMMEDIATE
17476 [THEN]
17477
17478 [UNDEFINED] ELSE [IF]
17479 \ https://forth-standard.org/standard/core/ELSE
17480 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
17481 CODE ELSE     \ immediate
17482 ADD #4,&DP              \ make room to compile two words
17483 MOV &DP,W               \ W=HERE+4
17484 MOV #BRAN,-4(W)
17485 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
17486 SUB #2,W                \ HERE+2
17487 MOV W,TOS               \ -- ELSEadr
17488 MOV @IP+,PC
17489 ENDCODE IMMEDIATE
17490 [THEN]
17491
17492 [UNDEFINED] DEFER [IF]
17493 \ https://forth-standard.org/standard/core/DEFER
17494 \ DEFER "<spaces>name"   --
17495 \ Skip leading space delimiters. Parse name delimited by a space.
17496 \ Create a definition for name with the execution semantics defined below.
17497
17498 \ name Execution:   --
17499 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
17500 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
17501 : DEFER
17502 CREATE
17503 HI2LO
17504 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
17505 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
17506 MOV @RSP+,IP
17507 MOV @IP+,PC
17508 ENDCODE
17509 [THEN]
17510
17511 [UNDEFINED] DEFER! [IF]
17512 \ https://forth-standard.org/standard/core/DEFERStore
17513 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
17514 CODE DEFER!             \ xt2 xt1 --
17515 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
17516 MOV @PSP+,TOS           \ --
17517 MOV @IP+,PC
17518 ENDCODE
17519 [THEN]
17520
17521 [UNDEFINED] IS [IF]
17522 \ https://forth-standard.org/standard/core/IS
17523 \ IS <name>        xt --
17524 \ used as is :
17525 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
17526 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
17527 \ or in a definition : ... ['] U. IS DISPLAY ...
17528 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
17529 \
17530 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
17531 : IS
17532 STATE @
17533 IF  POSTPONE ['] POSTPONE DEFER! 
17534 ELSE ' DEFER! 
17535 THEN
17536 ; IMMEDIATE
17537 [THEN]
17538
17539 [UNDEFINED] >BODY [IF]
17540 \ https://forth-standard.org/standard/core/toBODY
17541 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
17542 CODE >BODY
17543 ADD #4,TOS
17544 MOV @IP+,PC
17545 ENDCODE
17546 [THEN]
17547
17548 \ CODE 20uS           \ n --      8MHz version
17549 \ BEGIN               \ 4 + 16 ~ loop
17550 \     MOV #39,rDOCON   \ 39
17551 \     BEGIN           \ 4 ~ loop
17552 \         NOP
17553 \         SUB #1,rDOCON
17554 \     0=  UNTIL
17555 \     SUB #1,TOS      \ 1
17556 \ 0= UNTIL
17557 \ MOV #XDOCON,rDOCON  \ 2
17558 \ MOV @PSP+,TOS
17559 \ MOV @RSP+,IP        \
17560 \ ENDCODE
17561
17562 CODE 20_US                      \ n --      n * 20 us
17563 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
17564     BEGIN
17565         BIT #1,&LCD_TIM_CTL     \ 3
17566     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
17567     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
17568     SUB #1,TOS                  \ 1
17569 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
17570 MOV @PSP+,TOS                   \ 2
17571 MOV @IP+,PC                     \ 4
17572 ENDCODE
17573
17574 CODE TOP_LCD                    \ LCD Sample
17575 \                               \ if write : %xxxx_WWWW --
17576 \                               \ if read  : -- %0000_RRRR
17577     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
17578     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
17579 0= IF                           \ write LCD bits pattern
17580     AND.B #LCD_DB,TOS           \ 
17581     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
17582     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
17583     MOV @PSP+,TOS               \
17584     MOV @IP+,PC
17585 THEN                            \ read LCD bits pattern
17586     SUB #2,PSP
17587     MOV TOS,0(PSP)
17588     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
17589     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
17590     AND.B #LCD_DB,TOS           \
17591     MOV @IP+,PC
17592 ENDCODE
17593
17594 CODE LCD_WRC                    \ char --         Write Char
17595     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
17596 BW1 SUB #2,PSP                  \
17597     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
17598     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
17599     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
17600     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
17601 COLON                           \ high level word starts here 
17602     TOP_LCD 2 20_US             \ write high nibble first
17603     TOP_LCD 2 20_US 
17604 ;
17605
17606 CODE LCD_WRF                    \ func --         Write Fonction
17607     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
17608     GOTO BW1
17609 ENDCODE
17610
17611 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
17612 : LCD_HOME $02 LCD_WRF 100 20_us ;
17613
17614 \ [UNDEFINED] OR [IF]
17615
17616 \ \ https://forth-standard.org/standard/core/OR
17617 \ \ C OR     x1 x2 -- x3           logical OR
17618 \ CODE OR
17619 \ BIS @PSP+,TOS
17620 \ MOV @IP+,PC
17621 \ ENDCODE
17622
17623 \ [THEN]
17624
17625 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
17626 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
17627 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
17628 \ : LCD_FN_SET        $20 OR LCD_WrF ;
17629 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
17630 \ : LCD_GOTO          $80 OR LCD_WrF ;
17631
17632
17633 \ CODE LCD_RDS                    \ -- status       Read Status
17634 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
17635 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
17636 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
17637 \ COLON                           \ starts a FORTH word
17638 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
17639 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
17640 \ HI2LO                           \ switch from FORTH to assembler
17641 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
17642 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
17643 \     MOV @RSP+,IP                \ restore IP saved by COLON
17644 \     MOV @IP+,PC                 \
17645 \ ENDCODE
17646
17647 \ CODE LCD_RDC                    \ -- char         Read Char
17648 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
17649 \     GOTO BW1
17650 \ ENDCODE
17651
17652
17653 \ ******************************\
17654 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
17655 \ ******************************\
17656 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
17657 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
17658 BIT.B #SW2,&SW2_IN              \ test switch S2
17659 0= IF                           \ case of switch S2 pressed
17660     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
17661     U< IF
17662         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
17663     THEN
17664 ELSE
17665     BIT.B #SW1,&SW1_IN          \ test switch S1 input
17666     0= IF                       \ case of Switch S1 pressed
17667         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
17668         U>= IF                  \
17669            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
17670         THEN                    \
17671     THEN                        \
17672 THEN                            \
17673 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
17674 RET                             \ 5
17675 ENDASM
17676
17677 \ ******************************\
17678 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
17679 \ ******************************\
17680 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
17681 \ ******************************\
17682 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
17683 \                               \       SMclock = 8|16|24 MHz
17684 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
17685 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
17686 \                               \       SR(9)=new Toggle bit memory (ADD on)
17687 \ ******************************\
17688 \ RC5_FirstStartBitHalfCycle:   \
17689 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
17690 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
17691 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
17692 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
17693 \ [THEN]
17694 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
17695     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
17696 [THEN]
17697 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
17698     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
17699 [THEN]
17700 MOV #1778,X                     \ RC5_Period * 1us
17701 MOV #14,W                       \ count of loop
17702 BEGIN                           \
17703 \ ******************************\
17704 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
17705 \ ******************************\                   |
17706 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
17707 \ RC5_Compute_3/4_Period:       \                   |
17708     RRUM    #1,X                \ X=1/2 cycle       |
17709     MOV     X,Y                 \                   ^
17710     RRUM    #1,Y                \ Y=1/4
17711     ADD     X,Y                 \ Y=3/4 cycle
17712     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
17713     U>= UNTIL                   \ 2
17714 \ ******************************\
17715 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
17716 \ ******************************\
17717     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
17718     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
17719     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
17720     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
17721     SUB     #1,W                \ decrement count loop
17722 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
17723 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
17724 0<> WHILE                       \ ----> out of loop ----+
17725     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
17726     BEGIN                       \                       |
17727         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
17728         CMP Y,X                 \ 1                     |   cycle time out of bound ?
17729         U>= IF                  \ 2                 ^   |   yes:
17730         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
17731         GOTO BW1                \                   |   |      quit on truncated RC5 message
17732         THEN                    \                   |   |
17733         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
17734     0<> UNTIL                   \ 2                 |   |
17735 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
17736 \ ******************************\                       |
17737 \ RC5_SampleEndOf:              \ <---------------------+
17738 \ ******************************\
17739 BIC #$30,&RC5_TIM_CTL           \   stop timer
17740 \ ******************************\
17741 \ RC5_ComputeNewRC5word         \
17742 \ ******************************\
17743 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
17744 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
17745 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
17746 \ ******************************\
17747 \ RC5_ComputeC6bit              \
17748 \ ******************************\
17749 BIT     #BIT14,T                \ test /C6 bit in T
17750 0= IF   BIS #BIT6,X             \ set C6 bit in X
17751 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
17752 \ ******************************\
17753 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
17754 \ ******************************\
17755 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
17756 \ ******************************\
17757 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
17758 XOR     @RSP,T                  \ (new XOR old) Toggle bits
17759 BIT     #UF10,T                 \ repeated RC5_command ?
17760 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
17761 XOR #UF10,0(RSP)                \ 5 toggle bit memory
17762 \ ******************************\
17763 \ Display IR_RC5 code           \
17764 \ ******************************\
17765 SUB #8,PSP                      \ TOS -- x x x x TOS
17766 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
17767 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
17768 MOV #$10,&BASEADR               \                                               set hexadecimal base
17769 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
17770 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
17771 LO2HI                           \                                               switch from assembler to FORTH
17772     LCD_CLEAR                   \                                               set LCD cursor at home
17773     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
17774     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
17775     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
17776     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
17777 HI2LO                           \     --                                        switch from FORTH to assembler
17778 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
17779 MOV @PSP+,TOS                   \     -- TOS
17780 RET
17781 ENDASM
17782
17783 \ ******************************\
17784 ASM BACKGROUND                  \
17785 \ ******************************\
17786 BEGIN
17787 \     ...                         \ insert here your background task
17788 \     ...                         \
17789 \     ...                         \
17790     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
17791     BIS &LPM_MODE,SR            \
17792 \ ******************************\
17793 \ here start all interrupts     \
17794 \ ******************************\
17795 \ here return all interrupts    \
17796 \ ******************************\
17797 AGAIN                           \
17798 ENDASM                          \
17799 \ ******************************\
17800
17801 \ ------------------------------\
17802 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
17803 \ ------------------------------\
17804 \     ...                         \ init specific I/O sys as you want
17805 \     ...                         \ before executing default WARM
17806     MOV #WARM,X                 \ ['] WARM 
17807     ADD #4,X                    \ >BODY
17808     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
17809 ENDASM
17810 \ ------------------------------\
17811
17812 \ ------------------------------\
17813 CODE STOP                       \ stops multitasking, must to be used before downloading app
17814 \ ------------------------------\
17815 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
17816     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
17817     MOV X,-2(X)                 \ restore the default background: SLEEP
17818     MOV #WARM,X
17819     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
17820     BIC.B #RC5,&IR_IE           \ clear RC5_Int
17821     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
17822     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
17823     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
17824     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
17825     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
17826 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
17827 ECHO                            \
17828 ." RC5toLCD is removed,"
17829 ."  type START to restart"
17830  WARM                           \ performs reset to reset all interrupt vectors.    
17831 ;
17832 \ ------------------------------\
17833
17834 \ ------------------------------\
17835 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
17836 \ ------------------------------\
17837 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
17838 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
17839 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
17840 \                           --       \ID input divider \ 10 = /4
17841 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
17842 \                                 -  \TBCLR TimerB Clear
17843 \                                  - \TBIE
17844 \                                   -\TBIFG
17845 \ -------------------------------\
17846 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
17847 \                  --                 \CM Capture Mode
17848 \                    --               \CCIS
17849 \                       -             \SCS
17850 \                        --           \CLLD
17851 \                          -          \CAP
17852 \                            ---      \OUTMOD \ 011 = set/reset
17853 \                               -     \CCIE
17854 \                                 -   \CCI
17855 \                                  -  \OUT
17856 \                                   - \COV
17857 \                                    -\CCIFG
17858 \ -------------------------------\
17859 \ LCD_TIM_CCRx                   \
17860 \ -------------------------------\
17861 \ LCD_TIM_EX0                    \ 
17862 \ ------------------------------\
17863 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
17864 \ ------------------------------\
17865 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
17866 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
17867 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
17868     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
17869 [THEN]
17870 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
17871     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
17872 [THEN]
17873     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
17874 \ ------------------------------\
17875 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
17876 \ ------------------------------\
17877 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
17878     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
17879 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
17880 \ ------------------------------\
17881     BIS.B #LCDVo,&LCDVo_DIR     \
17882     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
17883 \ ------------------------------\
17884     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
17885     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
17886 \ ------------------------------\
17887     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
17888     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
17889 \ ******************************\
17890 \ init RC5_Int                  \
17891 \ ******************************\
17892     BIS.B #RC5,&IR_IE           \ enable RC5_Int
17893     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
17894     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
17895 \ ******************************\
17896 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
17897 \ ******************************\
17898 \              %01 0001 0100    \ TAxCTL
17899 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
17900 \                  --           \ ID        divided by 1
17901 \                    --         \ MC        MODE = up to TAxCCRn
17902 \                        -      \ TACLR     clear timer count
17903 \                         -     \ TAIE
17904 \                          -    \ TAIFG
17905 \ ------------------------------\
17906 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
17907 \ ------------------------------\
17908 \                        000    \ TAxEX0
17909 \                        ---    \ TAIDEX    pre divisor
17910 \ ------------------------------\
17911 \          %0000 0000 0000 0101 \ TAxCCR0
17912     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
17913 \ ------------------------------\
17914 \          %0000 0000 0001 0000 \ TAxCCTL0
17915 \                   -           \ CAP capture/compare mode = compare
17916 \                        -      \ CCIEn
17917 \                             - \ CCIFGn
17918     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
17919 \ ------------------------------\
17920     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
17921 \ ------------------------------\
17922 \ define LPM mode for ACCEPT    \
17923 \ ------------------------------\
17924 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
17925 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
17926 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
17927 \ ------------------------------\
17928 \ activate I/O                  \
17929 \ ------------------------------\
17930 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
17931 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
17932 \ ------------------------------\
17933 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
17934 \ ------------------------------\
17935 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
17936 \ CMP #2,Y                        \ Power_ON event
17937 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
17938 CMP #4,Y                        \
17939 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
17940 \ CMP #6,Y                        \
17941 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
17942 \ CMP #$0A,Y                      \
17943 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
17944 \ CMP #$16,Y                      \
17945 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
17946 \ ------------------------------\
17947 COLON                           \
17948 \ ------------------------------\
17949 \ Init LCD 2x20                 \
17950 \ ------------------------------\
17951     #1000 20_US                 \ 1- wait 20 ms
17952     %011 TOP_LCD                \ 2- send DB5=DB4=1
17953     #205 20_US                  \ 3- wait 4,1 ms
17954     %011 TOP_LCD                \ 4- send again DB5=DB4=1
17955     #5 20_US                    \ 5- wait 0,1 ms
17956     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
17957     #2 20_US                    \    wait 40 us = LCD cycle
17958     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
17959     #2 20_US                    \    wait 40 us = LCD cycle
17960     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
17961     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
17962     LCD_CLEAR                   \ 10- "LCD_Clear"
17963     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
17964     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
17965     LCD_CLEAR                   \ 10- "LCD_Clear"
17966     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
17967     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
17968     CR ." I love you"           \ display message on LCD
17969     ['] CR >BODY IS CR          \ CR executes its default value
17970     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
17971     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
17972     PWR_STATE ABORT             \ init DP and continues with ABORT
17973 ;                               \
17974 \ ------------------------------\
17975
17976 \ ------------------------------\
17977 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
17978 \ ------------------------------\
17979 MOV #SLEEP,X                    \ replace default background process SLEEP
17980 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
17981 MOV #WARM,X                     \ replace default WARM
17982 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
17983 MOV X,PC                        \ then execute new WARM
17984 ENDCODE 
17985 \ ------------------------------\
17986
17987 ECHO
17988             ; downloading RC5toLCD.4th is done
17989 RST_HERE    ; this app is protected against <reset>
17990
17991
17992 RST_STATE
17993
17994 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
17995
17996 [UNDEFINED] MARKER [IF]
17997 \  https://forth-standard.org/standard/core/MARKER
17998 \  MARKER
17999 \ ( "<spaces>name" -- )
18000 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
18001 \ with the execution semantics defined below.
18002
18003 \ name Execution: ( -- )
18004 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
18005 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
18006 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
18007 \ not necessarily provided. No other contextual information such as numeric base is affected
18008 \
18009 : MARKER
18010 CREATE
18011 HI2LO
18012 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
18013 SUB #2,Y            \ 1 Y = LFA
18014 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
18015 ADD #4,&DP          \ 3 add 2 cells
18016 LO2HI
18017 DOES>
18018 HI2LO
18019 MOV @RSP+,IP        \ -- PFA
18020 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
18021 MOV @TOS,&INIDP     \       set DP value for RST_STATE
18022 MOV @PSP+,TOS       \ --
18023 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
18024 ENDCODE
18025 [THEN]
18026
18027 MARKER {RC5TOLCD}
18028
18029 [UNDEFINED] @ [IF]
18030 \ https://forth-standard.org/standard/core/Fetch
18031 \ @     c-addr -- char   fetch char from memory
18032 CODE @
18033 MOV @TOS,TOS
18034 MOV @IP+,PC
18035 ENDCODE
18036 [THEN]
18037
18038 [UNDEFINED] CONSTANT [IF]
18039 \ https://forth-standard.org/standard/core/CONSTANT
18040 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
18041 : CONSTANT 
18042 CREATE
18043 HI2LO
18044 MOV TOS,-2(W)           \   PFA = n
18045 MOV @PSP+,TOS
18046 MOV @RSP+,IP
18047 MOV @IP+,PC
18048 ENDCODE
18049 [THEN]
18050
18051 [UNDEFINED] STATE [IF]
18052 \ https://forth-standard.org/standard/core/STATE
18053 \ STATE   -- a-addr       holds compiler state
18054 STATEADR CONSTANT STATE
18055 [THEN]
18056
18057 [UNDEFINED] = [IF]
18058 \ https://forth-standard.org/standard/core/Equal
18059 \ =      x1 x2 -- flag         test x1=x2
18060 CODE =
18061 SUB @PSP+,TOS   \ 2
18062 0<> IF          \ 2
18063     AND #0,TOS  \ 1
18064     MOV @IP+,PC \ 4
18065 THEN
18066 XOR #-1,TOS     \ 1 flag Z = 1
18067 MOV @IP+,PC     \ 4
18068 ENDCODE
18069 [THEN]
18070
18071 [UNDEFINED] IF [IF]
18072 \ https://forth-standard.org/standard/core/IF
18073 \ IF       -- IFadr    initialize conditional forward branch
18074 CODE IF       \ immediate
18075 SUB #2,PSP              \
18076 MOV TOS,0(PSP)          \
18077 MOV &DP,TOS             \ -- HERE
18078 ADD #4,&DP            \           compile one word, reserve one word
18079 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
18080 ADD #2,TOS              \ -- HERE+2=IFadr
18081 MOV @IP+,PC
18082 ENDCODE IMMEDIATE
18083 [THEN]
18084
18085 [UNDEFINED] THEN [IF]
18086 \ https://forth-standard.org/standard/core/THEN
18087 \ THEN     IFadr --                resolve forward branch
18088 CODE THEN               \ immediate
18089 MOV &DP,0(TOS)          \ -- IFadr
18090 MOV @PSP+,TOS           \ --
18091 MOV @IP+,PC
18092 ENDCODE IMMEDIATE
18093 [THEN]
18094
18095 [UNDEFINED] ELSE [IF]
18096 \ https://forth-standard.org/standard/core/ELSE
18097 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
18098 CODE ELSE     \ immediate
18099 ADD #4,&DP              \ make room to compile two words
18100 MOV &DP,W               \ W=HERE+4
18101 MOV #BRAN,-4(W)
18102 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
18103 SUB #2,W                \ HERE+2
18104 MOV W,TOS               \ -- ELSEadr
18105 MOV @IP+,PC
18106 ENDCODE IMMEDIATE
18107 [THEN]
18108
18109 [UNDEFINED] DEFER [IF]
18110 \ https://forth-standard.org/standard/core/DEFER
18111 \ DEFER "<spaces>name"   --
18112 \ Skip leading space delimiters. Parse name delimited by a space.
18113 \ Create a definition for name with the execution semantics defined below.
18114
18115 \ name Execution:   --
18116 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
18117 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
18118 : DEFER
18119 CREATE
18120 HI2LO
18121 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
18122 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
18123 MOV @RSP+,IP
18124 MOV @IP+,PC
18125 ENDCODE
18126 [THEN]
18127
18128 [UNDEFINED] DEFER! [IF]
18129 \ https://forth-standard.org/standard/core/DEFERStore
18130 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
18131 CODE DEFER!             \ xt2 xt1 --
18132 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
18133 MOV @PSP+,TOS           \ --
18134 MOV @IP+,PC
18135 ENDCODE
18136 [THEN]
18137
18138 [UNDEFINED] IS [IF]
18139 \ https://forth-standard.org/standard/core/IS
18140 \ IS <name>        xt --
18141 \ used as is :
18142 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
18143 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
18144 \ or in a definition : ... ['] U. IS DISPLAY ...
18145 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
18146 \
18147 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
18148 : IS
18149 STATE @
18150 IF  POSTPONE ['] POSTPONE DEFER! 
18151 ELSE ' DEFER! 
18152 THEN
18153 ; IMMEDIATE
18154 [THEN]
18155
18156 [UNDEFINED] >BODY [IF]
18157 \ https://forth-standard.org/standard/core/toBODY
18158 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
18159 CODE >BODY
18160 ADD #4,TOS
18161 MOV @IP+,PC
18162 ENDCODE
18163 [THEN]
18164
18165 \ CODE 20uS           \ n --      8MHz version
18166 \ BEGIN               \ 4 + 16 ~ loop
18167 \     MOV #39,rDOCON   \ 39
18168 \     BEGIN           \ 4 ~ loop
18169 \         NOP
18170 \         SUB #1,rDOCON
18171 \     0=  UNTIL
18172 \     SUB #1,TOS      \ 1
18173 \ 0= UNTIL
18174 \ MOV #XDOCON,rDOCON  \ 2
18175 \ MOV @PSP+,TOS
18176 \ MOV @RSP+,IP        \
18177 \ ENDCODE
18178
18179 CODE 20_US                      \ n --      n * 20 us
18180 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
18181     BEGIN
18182         BIT #1,&LCD_TIM_CTL     \ 3
18183     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
18184     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
18185     SUB #1,TOS                  \ 1
18186 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
18187 MOV @PSP+,TOS                   \ 2
18188 MOV @IP+,PC                     \ 4
18189 ENDCODE
18190
18191 CODE TOP_LCD                    \ LCD Sample
18192 \                               \ if write : %xxxx_WWWW --
18193 \                               \ if read  : -- %0000_RRRR
18194     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
18195     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
18196 0= IF                           \ write LCD bits pattern
18197     AND.B #LCD_DB,TOS           \ 
18198     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
18199     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
18200     MOV @PSP+,TOS               \
18201     MOV @IP+,PC
18202 THEN                            \ read LCD bits pattern
18203     SUB #2,PSP
18204     MOV TOS,0(PSP)
18205     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
18206     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
18207     AND.B #LCD_DB,TOS           \
18208     MOV @IP+,PC
18209 ENDCODE
18210
18211 CODE LCD_WRC                    \ char --         Write Char
18212     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
18213 BW1 SUB #2,PSP                  \
18214     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
18215     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
18216     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
18217     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
18218 COLON                           \ high level word starts here 
18219     TOP_LCD 2 20_US             \ write high nibble first
18220     TOP_LCD 2 20_US 
18221 ;
18222
18223 CODE LCD_WRF                    \ func --         Write Fonction
18224     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
18225     GOTO BW1
18226 ENDCODE
18227
18228 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
18229 : LCD_HOME $02 LCD_WRF 100 20_us ;
18230
18231 \ [UNDEFINED] OR [IF]
18232
18233 \ \ https://forth-standard.org/standard/core/OR
18234 \ \ C OR     x1 x2 -- x3           logical OR
18235 \ CODE OR
18236 \ BIS @PSP+,TOS
18237 \ MOV @IP+,PC
18238 \ ENDCODE
18239
18240 \ [THEN]
18241
18242 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
18243 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
18244 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
18245 \ : LCD_FN_SET        $20 OR LCD_WrF ;
18246 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
18247 \ : LCD_GOTO          $80 OR LCD_WrF ;
18248
18249
18250 \ CODE LCD_RDS                    \ -- status       Read Status
18251 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
18252 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
18253 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
18254 \ COLON                           \ starts a FORTH word
18255 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
18256 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
18257 \ HI2LO                           \ switch from FORTH to assembler
18258 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
18259 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
18260 \     MOV @RSP+,IP                \ restore IP saved by COLON
18261 \     MOV @IP+,PC                 \
18262 \ ENDCODE
18263
18264 \ CODE LCD_RDC                    \ -- char         Read Char
18265 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
18266 \     GOTO BW1
18267 \ ENDCODE
18268
18269
18270 \ ******************************\
18271 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
18272 \ ******************************\
18273 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
18274 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
18275 BIT.B #SW2,&SW2_IN              \ test switch S2
18276 0= IF                           \ case of switch S2 pressed
18277     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
18278     U< IF
18279         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
18280     THEN
18281 ELSE
18282     BIT.B #SW1,&SW1_IN          \ test switch S1 input
18283     0= IF                       \ case of Switch S1 pressed
18284         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
18285         U>= IF                  \
18286            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
18287         THEN                    \
18288     THEN                        \
18289 THEN                            \
18290 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
18291 RET                             \ 5
18292 ENDASM
18293
18294 \ ******************************\
18295 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
18296 \ ******************************\
18297 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
18298 \ ******************************\
18299 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
18300 \                               \       SMclock = 8|16|24 MHz
18301 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
18302 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
18303 \                               \       SR(9)=new Toggle bit memory (ADD on)
18304 \ ******************************\
18305 \ RC5_FirstStartBitHalfCycle:   \
18306 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
18307 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
18308 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
18309 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
18310 \ [THEN]
18311 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
18312     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
18313 [THEN]
18314 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
18315     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
18316 [THEN]
18317 MOV #1778,X                     \ RC5_Period * 1us
18318 MOV #14,W                       \ count of loop
18319 BEGIN                           \
18320 \ ******************************\
18321 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
18322 \ ******************************\                   |
18323 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
18324 \ RC5_Compute_3/4_Period:       \                   |
18325     RRUM    #1,X                \ X=1/2 cycle       |
18326     MOV     X,Y                 \                   ^
18327     RRUM    #1,Y                \ Y=1/4
18328     ADD     X,Y                 \ Y=3/4 cycle
18329     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
18330     U>= UNTIL                   \ 2
18331 \ ******************************\
18332 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
18333 \ ******************************\
18334     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
18335     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
18336     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
18337     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
18338     SUB     #1,W                \ decrement count loop
18339 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
18340 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
18341 0<> WHILE                       \ ----> out of loop ----+
18342     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
18343     BEGIN                       \                       |
18344         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
18345         CMP Y,X                 \ 1                     |   cycle time out of bound ?
18346         U>= IF                  \ 2                 ^   |   yes:
18347         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
18348         GOTO BW1                \                   |   |      quit on truncated RC5 message
18349         THEN                    \                   |   |
18350         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
18351     0<> UNTIL                   \ 2                 |   |
18352 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
18353 \ ******************************\                       |
18354 \ RC5_SampleEndOf:              \ <---------------------+
18355 \ ******************************\
18356 BIC #$30,&RC5_TIM_CTL           \   stop timer
18357 \ ******************************\
18358 \ RC5_ComputeNewRC5word         \
18359 \ ******************************\
18360 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
18361 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
18362 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
18363 \ ******************************\
18364 \ RC5_ComputeC6bit              \
18365 \ ******************************\
18366 BIT     #BIT14,T                \ test /C6 bit in T
18367 0= IF   BIS #BIT6,X             \ set C6 bit in X
18368 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
18369 \ ******************************\
18370 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
18371 \ ******************************\
18372 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
18373 \ ******************************\
18374 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
18375 XOR     @RSP,T                  \ (new XOR old) Toggle bits
18376 BIT     #UF10,T                 \ repeated RC5_command ?
18377 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
18378 XOR #UF10,0(RSP)                \ 5 toggle bit memory
18379 \ ******************************\
18380 \ Display IR_RC5 code           \
18381 \ ******************************\
18382 SUB #8,PSP                      \ TOS -- x x x x TOS
18383 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
18384 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
18385 MOV #$10,&BASEADR               \                                               set hexadecimal base
18386 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
18387 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
18388 LO2HI                           \                                               switch from assembler to FORTH
18389     LCD_CLEAR                   \                                               set LCD cursor at home
18390     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
18391     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
18392     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
18393     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
18394 HI2LO                           \     --                                        switch from FORTH to assembler
18395 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
18396 MOV @PSP+,TOS                   \     -- TOS
18397 RET
18398 ENDASM
18399
18400 \ ******************************\
18401 ASM BACKGROUND                  \
18402 \ ******************************\
18403 BEGIN
18404 \     ...                         \ insert here your background task
18405 \     ...                         \
18406 \     ...                         \
18407     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
18408     BIS &LPM_MODE,SR            \
18409 \ ******************************\
18410 \ here start all interrupts     \
18411 \ ******************************\
18412 \ here return all interrupts    \
18413 \ ******************************\
18414 AGAIN                           \
18415 ENDASM                          \
18416 \ ******************************\
18417
18418 \ ------------------------------\
18419 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
18420 \ ------------------------------\
18421 \     ...                         \ init specific I/O sys as you want
18422 \     ...                         \ before executing default WARM
18423     MOV #WARM,X                 \ ['] WARM 
18424     ADD #4,X                    \ >BODY
18425     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
18426 ENDASM
18427 \ ------------------------------\
18428
18429 \ ------------------------------\
18430 CODE STOP                       \ stops multitasking, must to be used before downloading app
18431 \ ------------------------------\
18432 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
18433     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
18434     MOV X,-2(X)                 \ restore the default background: SLEEP
18435     MOV #WARM,X
18436     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
18437     BIC.B #RC5,&IR_IE           \ clear RC5_Int
18438     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
18439     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
18440     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
18441     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
18442     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
18443 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
18444 ECHO                            \
18445 ." RC5toLCD is removed,"
18446 ."  type START to restart"
18447  WARM                           \ performs reset to reset all interrupt vectors.    
18448 ;
18449 \ ------------------------------\
18450
18451 \ ------------------------------\
18452 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
18453 \ ------------------------------\
18454 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
18455 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
18456 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
18457 \                           --       \ID input divider \ 10 = /4
18458 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
18459 \                                 -  \TBCLR TimerB Clear
18460 \                                  - \TBIE
18461 \                                   -\TBIFG
18462 \ -------------------------------\
18463 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
18464 \                  --                 \CM Capture Mode
18465 \                    --               \CCIS
18466 \                       -             \SCS
18467 \                        --           \CLLD
18468 \                          -          \CAP
18469 \                            ---      \OUTMOD \ 011 = set/reset
18470 \                               -     \CCIE
18471 \                                 -   \CCI
18472 \                                  -  \OUT
18473 \                                   - \COV
18474 \                                    -\CCIFG
18475 \ -------------------------------\
18476 \ LCD_TIM_CCRx                   \
18477 \ -------------------------------\
18478 \ LCD_TIM_EX0                    \ 
18479 \ ------------------------------\
18480 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
18481 \ ------------------------------\
18482 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
18483 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
18484 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
18485     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
18486 [THEN]
18487 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
18488     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
18489 [THEN]
18490     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
18491 \ ------------------------------\
18492 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
18493 \ ------------------------------\
18494 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
18495     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
18496 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
18497 \ ------------------------------\
18498     BIS.B #LCDVo,&LCDVo_DIR     \
18499     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
18500 \ ------------------------------\
18501     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
18502     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
18503 \ ------------------------------\
18504     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
18505     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
18506 \ ******************************\
18507 \ init RC5_Int                  \
18508 \ ******************************\
18509     BIS.B #RC5,&IR_IE           \ enable RC5_Int
18510     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
18511     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
18512 \ ******************************\
18513 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
18514 \ ******************************\
18515 \              %01 0001 0100    \ TAxCTL
18516 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
18517 \                  --           \ ID        divided by 1
18518 \                    --         \ MC        MODE = up to TAxCCRn
18519 \                        -      \ TACLR     clear timer count
18520 \                         -     \ TAIE
18521 \                          -    \ TAIFG
18522 \ ------------------------------\
18523 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
18524 \ ------------------------------\
18525 \                        000    \ TAxEX0
18526 \                        ---    \ TAIDEX    pre divisor
18527 \ ------------------------------\
18528 \          %0000 0000 0000 0101 \ TAxCCR0
18529     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
18530 \ ------------------------------\
18531 \          %0000 0000 0001 0000 \ TAxCCTL0
18532 \                   -           \ CAP capture/compare mode = compare
18533 \                        -      \ CCIEn
18534 \                             - \ CCIFGn
18535     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
18536 \ ------------------------------\
18537     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
18538 \ ------------------------------\
18539 \ define LPM mode for ACCEPT    \
18540 \ ------------------------------\
18541 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
18542 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
18543 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
18544 \ ------------------------------\
18545 \ activate I/O                  \
18546 \ ------------------------------\
18547 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
18548 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
18549 \ ------------------------------\
18550 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
18551 \ ------------------------------\
18552 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
18553 \ CMP #2,Y                        \ Power_ON event
18554 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
18555 CMP #4,Y                        \
18556 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
18557 \ CMP #6,Y                        \
18558 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
18559 \ CMP #$0A,Y                      \
18560 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
18561 \ CMP #$16,Y                      \
18562 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
18563 \ ------------------------------\
18564 COLON                           \
18565 \ ------------------------------\
18566 \ Init LCD 2x20                 \
18567 \ ------------------------------\
18568     #1000 20_US                 \ 1- wait 20 ms
18569     %011 TOP_LCD                \ 2- send DB5=DB4=1
18570     #205 20_US                  \ 3- wait 4,1 ms
18571     %011 TOP_LCD                \ 4- send again DB5=DB4=1
18572     #5 20_US                    \ 5- wait 0,1 ms
18573     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
18574     #2 20_US                    \    wait 40 us = LCD cycle
18575     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
18576     #2 20_US                    \    wait 40 us = LCD cycle
18577     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
18578     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
18579     LCD_CLEAR                   \ 10- "LCD_Clear"
18580     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
18581     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
18582     LCD_CLEAR                   \ 10- "LCD_Clear"
18583     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
18584     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
18585     CR ." I love you"           \ display message on LCD
18586     ['] CR >BODY IS CR          \ CR executes its default value
18587     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
18588     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
18589     PWR_STATE ABORT             \ init DP and continues with ABORT
18590 ;                               \
18591 \ ------------------------------\
18592
18593 \ ------------------------------\
18594 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
18595 \ ------------------------------\
18596 MOV #SLEEP,X                    \ replace default background process SLEEP
18597 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
18598 MOV #WARM,X                     \ replace default WARM
18599 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
18600 MOV X,PC                        \ then execute new WARM
18601 ENDCODE 
18602 \ ------------------------------\
18603
18604 ECHO
18605             ; downloading RC5toLCD.4th is done
18606 RST_HERE    ; this app is protected against <reset>
18607
18608
18609 RST_STATE
18610
18611 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
18612
18613 [UNDEFINED] MARKER [IF]
18614 \  https://forth-standard.org/standard/core/MARKER
18615 \  MARKER
18616 \ ( "<spaces>name" -- )
18617 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
18618 \ with the execution semantics defined below.
18619
18620 \ name Execution: ( -- )
18621 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
18622 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
18623 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
18624 \ not necessarily provided. No other contextual information such as numeric base is affected
18625 \
18626 : MARKER
18627 CREATE
18628 HI2LO
18629 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
18630 SUB #2,Y            \ 1 Y = LFA
18631 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
18632 ADD #4,&DP          \ 3 add 2 cells
18633 LO2HI
18634 DOES>
18635 HI2LO
18636 MOV @RSP+,IP        \ -- PFA
18637 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
18638 MOV @TOS,&INIDP     \       set DP value for RST_STATE
18639 MOV @PSP+,TOS       \ --
18640 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
18641 ENDCODE
18642 [THEN]
18643
18644 MARKER {RC5TOLCD}
18645
18646 [UNDEFINED] @ [IF]
18647 \ https://forth-standard.org/standard/core/Fetch
18648 \ @     c-addr -- char   fetch char from memory
18649 CODE @
18650 MOV @TOS,TOS
18651 MOV @IP+,PC
18652 ENDCODE
18653 [THEN]
18654
18655 [UNDEFINED] CONSTANT [IF]
18656 \ https://forth-standard.org/standard/core/CONSTANT
18657 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
18658 : CONSTANT 
18659 CREATE
18660 HI2LO
18661 MOV TOS,-2(W)           \   PFA = n
18662 MOV @PSP+,TOS
18663 MOV @RSP+,IP
18664 MOV @IP+,PC
18665 ENDCODE
18666 [THEN]
18667
18668 [UNDEFINED] STATE [IF]
18669 \ https://forth-standard.org/standard/core/STATE
18670 \ STATE   -- a-addr       holds compiler state
18671 STATEADR CONSTANT STATE
18672 [THEN]
18673
18674 [UNDEFINED] = [IF]
18675 \ https://forth-standard.org/standard/core/Equal
18676 \ =      x1 x2 -- flag         test x1=x2
18677 CODE =
18678 SUB @PSP+,TOS   \ 2
18679 0<> IF          \ 2
18680     AND #0,TOS  \ 1
18681     MOV @IP+,PC \ 4
18682 THEN
18683 XOR #-1,TOS     \ 1 flag Z = 1
18684 MOV @IP+,PC     \ 4
18685 ENDCODE
18686 [THEN]
18687
18688 [UNDEFINED] IF [IF]
18689 \ https://forth-standard.org/standard/core/IF
18690 \ IF       -- IFadr    initialize conditional forward branch
18691 CODE IF       \ immediate
18692 SUB #2,PSP              \
18693 MOV TOS,0(PSP)          \
18694 MOV &DP,TOS             \ -- HERE
18695 ADD #4,&DP            \           compile one word, reserve one word
18696 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
18697 ADD #2,TOS              \ -- HERE+2=IFadr
18698 MOV @IP+,PC
18699 ENDCODE IMMEDIATE
18700 [THEN]
18701
18702 [UNDEFINED] THEN [IF]
18703 \ https://forth-standard.org/standard/core/THEN
18704 \ THEN     IFadr --                resolve forward branch
18705 CODE THEN               \ immediate
18706 MOV &DP,0(TOS)          \ -- IFadr
18707 MOV @PSP+,TOS           \ --
18708 MOV @IP+,PC
18709 ENDCODE IMMEDIATE
18710 [THEN]
18711
18712 [UNDEFINED] ELSE [IF]
18713 \ https://forth-standard.org/standard/core/ELSE
18714 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
18715 CODE ELSE     \ immediate
18716 ADD #4,&DP              \ make room to compile two words
18717 MOV &DP,W               \ W=HERE+4
18718 MOV #BRAN,-4(W)
18719 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
18720 SUB #2,W                \ HERE+2
18721 MOV W,TOS               \ -- ELSEadr
18722 MOV @IP+,PC
18723 ENDCODE IMMEDIATE
18724 [THEN]
18725
18726 [UNDEFINED] DEFER [IF]
18727 \ https://forth-standard.org/standard/core/DEFER
18728 \ DEFER "<spaces>name"   --
18729 \ Skip leading space delimiters. Parse name delimited by a space.
18730 \ Create a definition for name with the execution semantics defined below.
18731
18732 \ name Execution:   --
18733 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
18734 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
18735 : DEFER
18736 CREATE
18737 HI2LO
18738 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
18739 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
18740 MOV @RSP+,IP
18741 MOV @IP+,PC
18742 ENDCODE
18743 [THEN]
18744
18745 [UNDEFINED] DEFER! [IF]
18746 \ https://forth-standard.org/standard/core/DEFERStore
18747 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
18748 CODE DEFER!             \ xt2 xt1 --
18749 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
18750 MOV @PSP+,TOS           \ --
18751 MOV @IP+,PC
18752 ENDCODE
18753 [THEN]
18754
18755 [UNDEFINED] IS [IF]
18756 \ https://forth-standard.org/standard/core/IS
18757 \ IS <name>        xt --
18758 \ used as is :
18759 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
18760 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
18761 \ or in a definition : ... ['] U. IS DISPLAY ...
18762 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
18763 \
18764 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
18765 : IS
18766 STATE @
18767 IF  POSTPONE ['] POSTPONE DEFER! 
18768 ELSE ' DEFER! 
18769 THEN
18770 ; IMMEDIATE
18771 [THEN]
18772
18773 [UNDEFINED] >BODY [IF]
18774 \ https://forth-standard.org/standard/core/toBODY
18775 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
18776 CODE >BODY
18777 ADD #4,TOS
18778 MOV @IP+,PC
18779 ENDCODE
18780 [THEN]
18781
18782 \ CODE 20uS           \ n --      8MHz version
18783 \ BEGIN               \ 4 + 16 ~ loop
18784 \     MOV #39,rDOCON   \ 39
18785 \     BEGIN           \ 4 ~ loop
18786 \         NOP
18787 \         SUB #1,rDOCON
18788 \     0=  UNTIL
18789 \     SUB #1,TOS      \ 1
18790 \ 0= UNTIL
18791 \ MOV #XDOCON,rDOCON  \ 2
18792 \ MOV @PSP+,TOS
18793 \ MOV @RSP+,IP        \
18794 \ ENDCODE
18795
18796 CODE 20_US                      \ n --      n * 20 us
18797 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
18798     BEGIN
18799         BIT #1,&LCD_TIM_CTL     \ 3
18800     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
18801     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
18802     SUB #1,TOS                  \ 1
18803 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
18804 MOV @PSP+,TOS                   \ 2
18805 MOV @IP+,PC                     \ 4
18806 ENDCODE
18807
18808 CODE TOP_LCD                    \ LCD Sample
18809 \                               \ if write : %xxxx_WWWW --
18810 \                               \ if read  : -- %0000_RRRR
18811     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
18812     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
18813 0= IF                           \ write LCD bits pattern
18814     AND.B #LCD_DB,TOS           \ 
18815     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
18816     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
18817     MOV @PSP+,TOS               \
18818     MOV @IP+,PC
18819 THEN                            \ read LCD bits pattern
18820     SUB #2,PSP
18821     MOV TOS,0(PSP)
18822     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
18823     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
18824     AND.B #LCD_DB,TOS           \
18825     MOV @IP+,PC
18826 ENDCODE
18827
18828 CODE LCD_WRC                    \ char --         Write Char
18829     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
18830 BW1 SUB #2,PSP                  \
18831     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
18832     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
18833     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
18834     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
18835 COLON                           \ high level word starts here 
18836     TOP_LCD 2 20_US             \ write high nibble first
18837     TOP_LCD 2 20_US 
18838 ;
18839
18840 CODE LCD_WRF                    \ func --         Write Fonction
18841     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
18842     GOTO BW1
18843 ENDCODE
18844
18845 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
18846 : LCD_HOME $02 LCD_WRF 100 20_us ;
18847
18848 \ [UNDEFINED] OR [IF]
18849
18850 \ \ https://forth-standard.org/standard/core/OR
18851 \ \ C OR     x1 x2 -- x3           logical OR
18852 \ CODE OR
18853 \ BIS @PSP+,TOS
18854 \ MOV @IP+,PC
18855 \ ENDCODE
18856
18857 \ [THEN]
18858
18859 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
18860 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
18861 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
18862 \ : LCD_FN_SET        $20 OR LCD_WrF ;
18863 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
18864 \ : LCD_GOTO          $80 OR LCD_WrF ;
18865
18866
18867 \ CODE LCD_RDS                    \ -- status       Read Status
18868 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
18869 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
18870 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
18871 \ COLON                           \ starts a FORTH word
18872 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
18873 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
18874 \ HI2LO                           \ switch from FORTH to assembler
18875 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
18876 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
18877 \     MOV @RSP+,IP                \ restore IP saved by COLON
18878 \     MOV @IP+,PC                 \
18879 \ ENDCODE
18880
18881 \ CODE LCD_RDC                    \ -- char         Read Char
18882 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
18883 \     GOTO BW1
18884 \ ENDCODE
18885
18886
18887 \ ******************************\
18888 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
18889 \ ******************************\
18890 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
18891 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
18892 BIT.B #SW2,&SW2_IN              \ test switch S2
18893 0= IF                           \ case of switch S2 pressed
18894     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
18895     U< IF
18896         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
18897     THEN
18898 ELSE
18899     BIT.B #SW1,&SW1_IN          \ test switch S1 input
18900     0= IF                       \ case of Switch S1 pressed
18901         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
18902         U>= IF                  \
18903            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
18904         THEN                    \
18905     THEN                        \
18906 THEN                            \
18907 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
18908 RET                             \ 5
18909 ENDASM
18910
18911 \ ******************************\
18912 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
18913 \ ******************************\
18914 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
18915 \ ******************************\
18916 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
18917 \                               \       SMclock = 8|16|24 MHz
18918 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
18919 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
18920 \                               \       SR(9)=new Toggle bit memory (ADD on)
18921 \ ******************************\
18922 \ RC5_FirstStartBitHalfCycle:   \
18923 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
18924 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
18925 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
18926 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
18927 \ [THEN]
18928 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
18929     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
18930 [THEN]
18931 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
18932     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
18933 [THEN]
18934 MOV #1778,X                     \ RC5_Period * 1us
18935 MOV #14,W                       \ count of loop
18936 BEGIN                           \
18937 \ ******************************\
18938 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
18939 \ ******************************\                   |
18940 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
18941 \ RC5_Compute_3/4_Period:       \                   |
18942     RRUM    #1,X                \ X=1/2 cycle       |
18943     MOV     X,Y                 \                   ^
18944     RRUM    #1,Y                \ Y=1/4
18945     ADD     X,Y                 \ Y=3/4 cycle
18946     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
18947     U>= UNTIL                   \ 2
18948 \ ******************************\
18949 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
18950 \ ******************************\
18951     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
18952     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
18953     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
18954     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
18955     SUB     #1,W                \ decrement count loop
18956 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
18957 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
18958 0<> WHILE                       \ ----> out of loop ----+
18959     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
18960     BEGIN                       \                       |
18961         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
18962         CMP Y,X                 \ 1                     |   cycle time out of bound ?
18963         U>= IF                  \ 2                 ^   |   yes:
18964         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
18965         GOTO BW1                \                   |   |      quit on truncated RC5 message
18966         THEN                    \                   |   |
18967         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
18968     0<> UNTIL                   \ 2                 |   |
18969 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
18970 \ ******************************\                       |
18971 \ RC5_SampleEndOf:              \ <---------------------+
18972 \ ******************************\
18973 BIC #$30,&RC5_TIM_CTL           \   stop timer
18974 \ ******************************\
18975 \ RC5_ComputeNewRC5word         \
18976 \ ******************************\
18977 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
18978 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
18979 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
18980 \ ******************************\
18981 \ RC5_ComputeC6bit              \
18982 \ ******************************\
18983 BIT     #BIT14,T                \ test /C6 bit in T
18984 0= IF   BIS #BIT6,X             \ set C6 bit in X
18985 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
18986 \ ******************************\
18987 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
18988 \ ******************************\
18989 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
18990 \ ******************************\
18991 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
18992 XOR     @RSP,T                  \ (new XOR old) Toggle bits
18993 BIT     #UF10,T                 \ repeated RC5_command ?
18994 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
18995 XOR #UF10,0(RSP)                \ 5 toggle bit memory
18996 \ ******************************\
18997 \ Display IR_RC5 code           \
18998 \ ******************************\
18999 SUB #8,PSP                      \ TOS -- x x x x TOS
19000 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
19001 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
19002 MOV #$10,&BASEADR               \                                               set hexadecimal base
19003 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
19004 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
19005 LO2HI                           \                                               switch from assembler to FORTH
19006     LCD_CLEAR                   \                                               set LCD cursor at home
19007     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
19008     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
19009     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
19010     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
19011 HI2LO                           \     --                                        switch from FORTH to assembler
19012 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
19013 MOV @PSP+,TOS                   \     -- TOS
19014 RET
19015 ENDASM
19016
19017 \ ******************************\
19018 ASM BACKGROUND                  \
19019 \ ******************************\
19020 BEGIN
19021 \     ...                         \ insert here your background task
19022 \     ...                         \
19023 \     ...                         \
19024     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
19025     BIS &LPM_MODE,SR            \
19026 \ ******************************\
19027 \ here start all interrupts     \
19028 \ ******************************\
19029 \ here return all interrupts    \
19030 \ ******************************\
19031 AGAIN                           \
19032 ENDASM                          \
19033 \ ******************************\
19034
19035 \ ------------------------------\
19036 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
19037 \ ------------------------------\
19038 \     ...                         \ init specific I/O sys as you want
19039 \     ...                         \ before executing default WARM
19040     MOV #WARM,X                 \ ['] WARM 
19041     ADD #4,X                    \ >BODY
19042     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
19043 ENDASM
19044 \ ------------------------------\
19045
19046 \ ------------------------------\
19047 CODE STOP                       \ stops multitasking, must to be used before downloading app
19048 \ ------------------------------\
19049 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
19050     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
19051     MOV X,-2(X)                 \ restore the default background: SLEEP
19052     MOV #WARM,X
19053     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
19054     BIC.B #RC5,&IR_IE           \ clear RC5_Int
19055     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
19056     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
19057     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
19058     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
19059     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
19060 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
19061 ECHO                            \
19062 ." RC5toLCD is removed,"
19063 ."  type START to restart"
19064  WARM                           \ performs reset to reset all interrupt vectors.    
19065 ;
19066 \ ------------------------------\
19067
19068 \ ------------------------------\
19069 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
19070 \ ------------------------------\
19071 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
19072 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
19073 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
19074 \                           --       \ID input divider \ 10 = /4
19075 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
19076 \                                 -  \TBCLR TimerB Clear
19077 \                                  - \TBIE
19078 \                                   -\TBIFG
19079 \ -------------------------------\
19080 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
19081 \                  --                 \CM Capture Mode
19082 \                    --               \CCIS
19083 \                       -             \SCS
19084 \                        --           \CLLD
19085 \                          -          \CAP
19086 \                            ---      \OUTMOD \ 011 = set/reset
19087 \                               -     \CCIE
19088 \                                 -   \CCI
19089 \                                  -  \OUT
19090 \                                   - \COV
19091 \                                    -\CCIFG
19092 \ -------------------------------\
19093 \ LCD_TIM_CCRx                   \
19094 \ -------------------------------\
19095 \ LCD_TIM_EX0                    \ 
19096 \ ------------------------------\
19097 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
19098 \ ------------------------------\
19099 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
19100 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
19101 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
19102     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
19103 [THEN]
19104 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
19105     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
19106 [THEN]
19107     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
19108 \ ------------------------------\
19109 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
19110 \ ------------------------------\
19111 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
19112     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
19113 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
19114 \ ------------------------------\
19115     BIS.B #LCDVo,&LCDVo_DIR     \
19116     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
19117 \ ------------------------------\
19118     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
19119     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
19120 \ ------------------------------\
19121     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
19122     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
19123 \ ******************************\
19124 \ init RC5_Int                  \
19125 \ ******************************\
19126     BIS.B #RC5,&IR_IE           \ enable RC5_Int
19127     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
19128     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
19129 \ ******************************\
19130 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
19131 \ ******************************\
19132 \              %01 0001 0100    \ TAxCTL
19133 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
19134 \                  --           \ ID        divided by 1
19135 \                    --         \ MC        MODE = up to TAxCCRn
19136 \                        -      \ TACLR     clear timer count
19137 \                         -     \ TAIE
19138 \                          -    \ TAIFG
19139 \ ------------------------------\
19140 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
19141 \ ------------------------------\
19142 \                        000    \ TAxEX0
19143 \                        ---    \ TAIDEX    pre divisor
19144 \ ------------------------------\
19145 \          %0000 0000 0000 0101 \ TAxCCR0
19146     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
19147 \ ------------------------------\
19148 \          %0000 0000 0001 0000 \ TAxCCTL0
19149 \                   -           \ CAP capture/compare mode = compare
19150 \                        -      \ CCIEn
19151 \                             - \ CCIFGn
19152     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
19153 \ ------------------------------\
19154     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
19155 \ ------------------------------\
19156 \ define LPM mode for ACCEPT    \
19157 \ ------------------------------\
19158 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
19159 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
19160 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
19161 \ ------------------------------\
19162 \ activate I/O                  \
19163 \ ------------------------------\
19164 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
19165 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
19166 \ ------------------------------\
19167 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
19168 \ ------------------------------\
19169 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
19170 \ CMP #2,Y                        \ Power_ON event
19171 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
19172 CMP #4,Y                        \
19173 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
19174 \ CMP #6,Y                        \
19175 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
19176 \ CMP #$0A,Y                      \
19177 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
19178 \ CMP #$16,Y                      \
19179 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
19180 \ ------------------------------\
19181 COLON                           \
19182 \ ------------------------------\
19183 \ Init LCD 2x20                 \
19184 \ ------------------------------\
19185     #1000 20_US                 \ 1- wait 20 ms
19186     %011 TOP_LCD                \ 2- send DB5=DB4=1
19187     #205 20_US                  \ 3- wait 4,1 ms
19188     %011 TOP_LCD                \ 4- send again DB5=DB4=1
19189     #5 20_US                    \ 5- wait 0,1 ms
19190     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
19191     #2 20_US                    \    wait 40 us = LCD cycle
19192     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
19193     #2 20_US                    \    wait 40 us = LCD cycle
19194     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
19195     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
19196     LCD_CLEAR                   \ 10- "LCD_Clear"
19197     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
19198     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
19199     LCD_CLEAR                   \ 10- "LCD_Clear"
19200     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
19201     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
19202     CR ." I love you"           \ display message on LCD
19203     ['] CR >BODY IS CR          \ CR executes its default value
19204     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
19205     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
19206     PWR_STATE ABORT             \ init DP and continues with ABORT
19207 ;                               \
19208 \ ------------------------------\
19209
19210 \ ------------------------------\
19211 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
19212 \ ------------------------------\
19213 MOV #SLEEP,X                    \ replace default background process SLEEP
19214 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
19215 MOV #WARM,X                     \ replace default WARM
19216 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
19217 MOV X,PC                        \ then execute new WARM
19218 ENDCODE 
19219 \ ------------------------------\
19220
19221 ECHO
19222             ; downloading RC5toLCD.4th is done
19223 RST_HERE    ; this app is protected against <reset>
19224
19225
19226 RST_STATE
19227
19228 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
19229
19230 [UNDEFINED] MARKER [IF]
19231 \  https://forth-standard.org/standard/core/MARKER
19232 \  MARKER
19233 \ ( "<spaces>name" -- )
19234 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
19235 \ with the execution semantics defined below.
19236
19237 \ name Execution: ( -- )
19238 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
19239 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
19240 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
19241 \ not necessarily provided. No other contextual information such as numeric base is affected
19242 \
19243 : MARKER
19244 CREATE
19245 HI2LO
19246 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
19247 SUB #2,Y            \ 1 Y = LFA
19248 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
19249 ADD #4,&DP          \ 3 add 2 cells
19250 LO2HI
19251 DOES>
19252 HI2LO
19253 MOV @RSP+,IP        \ -- PFA
19254 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
19255 MOV @TOS,&INIDP     \       set DP value for RST_STATE
19256 MOV @PSP+,TOS       \ --
19257 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
19258 ENDCODE
19259 [THEN]
19260
19261 MARKER {RC5TOLCD}
19262
19263 [UNDEFINED] @ [IF]
19264 \ https://forth-standard.org/standard/core/Fetch
19265 \ @     c-addr -- char   fetch char from memory
19266 CODE @
19267 MOV @TOS,TOS
19268 MOV @IP+,PC
19269 ENDCODE
19270 [THEN]
19271
19272 [UNDEFINED] CONSTANT [IF]
19273 \ https://forth-standard.org/standard/core/CONSTANT
19274 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
19275 : CONSTANT 
19276 CREATE
19277 HI2LO
19278 MOV TOS,-2(W)           \   PFA = n
19279 MOV @PSP+,TOS
19280 MOV @RSP+,IP
19281 MOV @IP+,PC
19282 ENDCODE
19283 [THEN]
19284
19285 [UNDEFINED] STATE [IF]
19286 \ https://forth-standard.org/standard/core/STATE
19287 \ STATE   -- a-addr       holds compiler state
19288 STATEADR CONSTANT STATE
19289 [THEN]
19290
19291 [UNDEFINED] = [IF]
19292 \ https://forth-standard.org/standard/core/Equal
19293 \ =      x1 x2 -- flag         test x1=x2
19294 CODE =
19295 SUB @PSP+,TOS   \ 2
19296 0<> IF          \ 2
19297     AND #0,TOS  \ 1
19298     MOV @IP+,PC \ 4
19299 THEN
19300 XOR #-1,TOS     \ 1 flag Z = 1
19301 MOV @IP+,PC     \ 4
19302 ENDCODE
19303 [THEN]
19304
19305 [UNDEFINED] IF [IF]
19306 \ https://forth-standard.org/standard/core/IF
19307 \ IF       -- IFadr    initialize conditional forward branch
19308 CODE IF       \ immediate
19309 SUB #2,PSP              \
19310 MOV TOS,0(PSP)          \
19311 MOV &DP,TOS             \ -- HERE
19312 ADD #4,&DP            \           compile one word, reserve one word
19313 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
19314 ADD #2,TOS              \ -- HERE+2=IFadr
19315 MOV @IP+,PC
19316 ENDCODE IMMEDIATE
19317 [THEN]
19318
19319 [UNDEFINED] THEN [IF]
19320 \ https://forth-standard.org/standard/core/THEN
19321 \ THEN     IFadr --                resolve forward branch
19322 CODE THEN               \ immediate
19323 MOV &DP,0(TOS)          \ -- IFadr
19324 MOV @PSP+,TOS           \ --
19325 MOV @IP+,PC
19326 ENDCODE IMMEDIATE
19327 [THEN]
19328
19329 [UNDEFINED] ELSE [IF]
19330 \ https://forth-standard.org/standard/core/ELSE
19331 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
19332 CODE ELSE     \ immediate
19333 ADD #4,&DP              \ make room to compile two words
19334 MOV &DP,W               \ W=HERE+4
19335 MOV #BRAN,-4(W)
19336 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
19337 SUB #2,W                \ HERE+2
19338 MOV W,TOS               \ -- ELSEadr
19339 MOV @IP+,PC
19340 ENDCODE IMMEDIATE
19341 [THEN]
19342
19343 [UNDEFINED] DEFER [IF]
19344 \ https://forth-standard.org/standard/core/DEFER
19345 \ DEFER "<spaces>name"   --
19346 \ Skip leading space delimiters. Parse name delimited by a space.
19347 \ Create a definition for name with the execution semantics defined below.
19348
19349 \ name Execution:   --
19350 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
19351 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
19352 : DEFER
19353 CREATE
19354 HI2LO
19355 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
19356 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
19357 MOV @RSP+,IP
19358 MOV @IP+,PC
19359 ENDCODE
19360 [THEN]
19361
19362 [UNDEFINED] DEFER! [IF]
19363 \ https://forth-standard.org/standard/core/DEFERStore
19364 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
19365 CODE DEFER!             \ xt2 xt1 --
19366 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
19367 MOV @PSP+,TOS           \ --
19368 MOV @IP+,PC
19369 ENDCODE
19370 [THEN]
19371
19372 [UNDEFINED] IS [IF]
19373 \ https://forth-standard.org/standard/core/IS
19374 \ IS <name>        xt --
19375 \ used as is :
19376 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
19377 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
19378 \ or in a definition : ... ['] U. IS DISPLAY ...
19379 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
19380 \
19381 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
19382 : IS
19383 STATE @
19384 IF  POSTPONE ['] POSTPONE DEFER! 
19385 ELSE ' DEFER! 
19386 THEN
19387 ; IMMEDIATE
19388 [THEN]
19389
19390 [UNDEFINED] >BODY [IF]
19391 \ https://forth-standard.org/standard/core/toBODY
19392 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
19393 CODE >BODY
19394 ADD #4,TOS
19395 MOV @IP+,PC
19396 ENDCODE
19397 [THEN]
19398
19399 \ CODE 20uS           \ n --      8MHz version
19400 \ BEGIN               \ 4 + 16 ~ loop
19401 \     MOV #39,rDOCON   \ 39
19402 \     BEGIN           \ 4 ~ loop
19403 \         NOP
19404 \         SUB #1,rDOCON
19405 \     0=  UNTIL
19406 \     SUB #1,TOS      \ 1
19407 \ 0= UNTIL
19408 \ MOV #XDOCON,rDOCON  \ 2
19409 \ MOV @PSP+,TOS
19410 \ MOV @RSP+,IP        \
19411 \ ENDCODE
19412
19413 CODE 20_US                      \ n --      n * 20 us
19414 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
19415     BEGIN
19416         BIT #1,&LCD_TIM_CTL     \ 3
19417     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
19418     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
19419     SUB #1,TOS                  \ 1
19420 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
19421 MOV @PSP+,TOS                   \ 2
19422 MOV @IP+,PC                     \ 4
19423 ENDCODE
19424
19425 CODE TOP_LCD                    \ LCD Sample
19426 \                               \ if write : %xxxx_WWWW --
19427 \                               \ if read  : -- %0000_RRRR
19428     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
19429     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
19430 0= IF                           \ write LCD bits pattern
19431     AND.B #LCD_DB,TOS           \ 
19432     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
19433     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
19434     MOV @PSP+,TOS               \
19435     MOV @IP+,PC
19436 THEN                            \ read LCD bits pattern
19437     SUB #2,PSP
19438     MOV TOS,0(PSP)
19439     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
19440     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
19441     AND.B #LCD_DB,TOS           \
19442     MOV @IP+,PC
19443 ENDCODE
19444
19445 CODE LCD_WRC                    \ char --         Write Char
19446     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
19447 BW1 SUB #2,PSP                  \
19448     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
19449     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
19450     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
19451     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
19452 COLON                           \ high level word starts here 
19453     TOP_LCD 2 20_US             \ write high nibble first
19454     TOP_LCD 2 20_US 
19455 ;
19456
19457 CODE LCD_WRF                    \ func --         Write Fonction
19458     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
19459     GOTO BW1
19460 ENDCODE
19461
19462 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
19463 : LCD_HOME $02 LCD_WRF 100 20_us ;
19464
19465 \ [UNDEFINED] OR [IF]
19466
19467 \ \ https://forth-standard.org/standard/core/OR
19468 \ \ C OR     x1 x2 -- x3           logical OR
19469 \ CODE OR
19470 \ BIS @PSP+,TOS
19471 \ MOV @IP+,PC
19472 \ ENDCODE
19473
19474 \ [THEN]
19475
19476 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
19477 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
19478 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
19479 \ : LCD_FN_SET        $20 OR LCD_WrF ;
19480 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
19481 \ : LCD_GOTO          $80 OR LCD_WrF ;
19482
19483
19484 \ CODE LCD_RDS                    \ -- status       Read Status
19485 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
19486 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
19487 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
19488 \ COLON                           \ starts a FORTH word
19489 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
19490 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
19491 \ HI2LO                           \ switch from FORTH to assembler
19492 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
19493 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
19494 \     MOV @RSP+,IP                \ restore IP saved by COLON
19495 \     MOV @IP+,PC                 \
19496 \ ENDCODE
19497
19498 \ CODE LCD_RDC                    \ -- char         Read Char
19499 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
19500 \     GOTO BW1
19501 \ ENDCODE
19502
19503
19504 \ ******************************\
19505 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
19506 \ ******************************\
19507 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
19508 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
19509 BIT.B #SW2,&SW2_IN              \ test switch S2
19510 0= IF                           \ case of switch S2 pressed
19511     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
19512     U< IF
19513         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
19514     THEN
19515 ELSE
19516     BIT.B #SW1,&SW1_IN          \ test switch S1 input
19517     0= IF                       \ case of Switch S1 pressed
19518         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
19519         U>= IF                  \
19520            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
19521         THEN                    \
19522     THEN                        \
19523 THEN                            \
19524 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
19525 RET                             \ 5
19526 ENDASM
19527
19528 \ ******************************\
19529 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
19530 \ ******************************\
19531 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
19532 \ ******************************\
19533 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
19534 \                               \       SMclock = 8|16|24 MHz
19535 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
19536 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
19537 \                               \       SR(9)=new Toggle bit memory (ADD on)
19538 \ ******************************\
19539 \ RC5_FirstStartBitHalfCycle:   \
19540 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
19541 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
19542 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
19543 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
19544 \ [THEN]
19545 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
19546     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
19547 [THEN]
19548 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
19549     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
19550 [THEN]
19551 MOV #1778,X                     \ RC5_Period * 1us
19552 MOV #14,W                       \ count of loop
19553 BEGIN                           \
19554 \ ******************************\
19555 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
19556 \ ******************************\                   |
19557 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
19558 \ RC5_Compute_3/4_Period:       \                   |
19559     RRUM    #1,X                \ X=1/2 cycle       |
19560     MOV     X,Y                 \                   ^
19561     RRUM    #1,Y                \ Y=1/4
19562     ADD     X,Y                 \ Y=3/4 cycle
19563     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
19564     U>= UNTIL                   \ 2
19565 \ ******************************\
19566 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
19567 \ ******************************\
19568     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
19569     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
19570     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
19571     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
19572     SUB     #1,W                \ decrement count loop
19573 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
19574 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
19575 0<> WHILE                       \ ----> out of loop ----+
19576     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
19577     BEGIN                       \                       |
19578         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
19579         CMP Y,X                 \ 1                     |   cycle time out of bound ?
19580         U>= IF                  \ 2                 ^   |   yes:
19581         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
19582         GOTO BW1                \                   |   |      quit on truncated RC5 message
19583         THEN                    \                   |   |
19584         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
19585     0<> UNTIL                   \ 2                 |   |
19586 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
19587 \ ******************************\                       |
19588 \ RC5_SampleEndOf:              \ <---------------------+
19589 \ ******************************\
19590 BIC #$30,&RC5_TIM_CTL           \   stop timer
19591 \ ******************************\
19592 \ RC5_ComputeNewRC5word         \
19593 \ ******************************\
19594 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
19595 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
19596 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
19597 \ ******************************\
19598 \ RC5_ComputeC6bit              \
19599 \ ******************************\
19600 BIT     #BIT14,T                \ test /C6 bit in T
19601 0= IF   BIS #BIT6,X             \ set C6 bit in X
19602 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
19603 \ ******************************\
19604 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
19605 \ ******************************\
19606 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
19607 \ ******************************\
19608 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
19609 XOR     @RSP,T                  \ (new XOR old) Toggle bits
19610 BIT     #UF10,T                 \ repeated RC5_command ?
19611 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
19612 XOR #UF10,0(RSP)                \ 5 toggle bit memory
19613 \ ******************************\
19614 \ Display IR_RC5 code           \
19615 \ ******************************\
19616 SUB #8,PSP                      \ TOS -- x x x x TOS
19617 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
19618 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
19619 MOV #$10,&BASEADR               \                                               set hexadecimal base
19620 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
19621 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
19622 LO2HI                           \                                               switch from assembler to FORTH
19623     LCD_CLEAR                   \                                               set LCD cursor at home
19624     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
19625     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
19626     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
19627     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
19628 HI2LO                           \     --                                        switch from FORTH to assembler
19629 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
19630 MOV @PSP+,TOS                   \     -- TOS
19631 RET
19632 ENDASM
19633
19634 \ ******************************\
19635 ASM BACKGROUND                  \
19636 \ ******************************\
19637 BEGIN
19638 \     ...                         \ insert here your background task
19639 \     ...                         \
19640 \     ...                         \
19641     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
19642     BIS &LPM_MODE,SR            \
19643 \ ******************************\
19644 \ here start all interrupts     \
19645 \ ******************************\
19646 \ here return all interrupts    \
19647 \ ******************************\
19648 AGAIN                           \
19649 ENDASM                          \
19650 \ ******************************\
19651
19652 \ ------------------------------\
19653 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
19654 \ ------------------------------\
19655 \     ...                         \ init specific I/O sys as you want
19656 \     ...                         \ before executing default WARM
19657     MOV #WARM,X                 \ ['] WARM 
19658     ADD #4,X                    \ >BODY
19659     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
19660 ENDASM
19661 \ ------------------------------\
19662
19663 \ ------------------------------\
19664 CODE STOP                       \ stops multitasking, must to be used before downloading app
19665 \ ------------------------------\
19666 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
19667     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
19668     MOV X,-2(X)                 \ restore the default background: SLEEP
19669     MOV #WARM,X
19670     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
19671     BIC.B #RC5,&IR_IE           \ clear RC5_Int
19672     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
19673     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
19674     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
19675     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
19676     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
19677 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
19678 ECHO                            \
19679 ." RC5toLCD is removed,"
19680 ."  type START to restart"
19681  WARM                           \ performs reset to reset all interrupt vectors.    
19682 ;
19683 \ ------------------------------\
19684
19685 \ ------------------------------\
19686 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
19687 \ ------------------------------\
19688 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
19689 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
19690 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
19691 \                           --       \ID input divider \ 10 = /4
19692 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
19693 \                                 -  \TBCLR TimerB Clear
19694 \                                  - \TBIE
19695 \                                   -\TBIFG
19696 \ -------------------------------\
19697 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
19698 \                  --                 \CM Capture Mode
19699 \                    --               \CCIS
19700 \                       -             \SCS
19701 \                        --           \CLLD
19702 \                          -          \CAP
19703 \                            ---      \OUTMOD \ 011 = set/reset
19704 \                               -     \CCIE
19705 \                                 -   \CCI
19706 \                                  -  \OUT
19707 \                                   - \COV
19708 \                                    -\CCIFG
19709 \ -------------------------------\
19710 \ LCD_TIM_CCRx                   \
19711 \ -------------------------------\
19712 \ LCD_TIM_EX0                    \ 
19713 \ ------------------------------\
19714 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
19715 \ ------------------------------\
19716 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
19717 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
19718 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
19719     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
19720 [THEN]
19721 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
19722     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
19723 [THEN]
19724     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
19725 \ ------------------------------\
19726 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
19727 \ ------------------------------\
19728 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
19729     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
19730 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
19731 \ ------------------------------\
19732     BIS.B #LCDVo,&LCDVo_DIR     \
19733     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
19734 \ ------------------------------\
19735     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
19736     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
19737 \ ------------------------------\
19738     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
19739     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
19740 \ ******************************\
19741 \ init RC5_Int                  \
19742 \ ******************************\
19743     BIS.B #RC5,&IR_IE           \ enable RC5_Int
19744     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
19745     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
19746 \ ******************************\
19747 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
19748 \ ******************************\
19749 \              %01 0001 0100    \ TAxCTL
19750 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
19751 \                  --           \ ID        divided by 1
19752 \                    --         \ MC        MODE = up to TAxCCRn
19753 \                        -      \ TACLR     clear timer count
19754 \                         -     \ TAIE
19755 \                          -    \ TAIFG
19756 \ ------------------------------\
19757 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
19758 \ ------------------------------\
19759 \                        000    \ TAxEX0
19760 \                        ---    \ TAIDEX    pre divisor
19761 \ ------------------------------\
19762 \          %0000 0000 0000 0101 \ TAxCCR0
19763     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
19764 \ ------------------------------\
19765 \          %0000 0000 0001 0000 \ TAxCCTL0
19766 \                   -           \ CAP capture/compare mode = compare
19767 \                        -      \ CCIEn
19768 \                             - \ CCIFGn
19769     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
19770 \ ------------------------------\
19771     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
19772 \ ------------------------------\
19773 \ define LPM mode for ACCEPT    \
19774 \ ------------------------------\
19775 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
19776 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
19777 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
19778 \ ------------------------------\
19779 \ activate I/O                  \
19780 \ ------------------------------\
19781 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
19782 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
19783 \ ------------------------------\
19784 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
19785 \ ------------------------------\
19786 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
19787 \ CMP #2,Y                        \ Power_ON event
19788 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
19789 CMP #4,Y                        \
19790 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
19791 \ CMP #6,Y                        \
19792 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
19793 \ CMP #$0A,Y                      \
19794 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
19795 \ CMP #$16,Y                      \
19796 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
19797 \ ------------------------------\
19798 COLON                           \
19799 \ ------------------------------\
19800 \ Init LCD 2x20                 \
19801 \ ------------------------------\
19802     #1000 20_US                 \ 1- wait 20 ms
19803     %011 TOP_LCD                \ 2- send DB5=DB4=1
19804     #205 20_US                  \ 3- wait 4,1 ms
19805     %011 TOP_LCD                \ 4- send again DB5=DB4=1
19806     #5 20_US                    \ 5- wait 0,1 ms
19807     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
19808     #2 20_US                    \    wait 40 us = LCD cycle
19809     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
19810     #2 20_US                    \    wait 40 us = LCD cycle
19811     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
19812     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
19813     LCD_CLEAR                   \ 10- "LCD_Clear"
19814     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
19815     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
19816     LCD_CLEAR                   \ 10- "LCD_Clear"
19817     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
19818     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
19819     CR ." I love you"           \ display message on LCD
19820     ['] CR >BODY IS CR          \ CR executes its default value
19821     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
19822     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
19823     PWR_STATE ABORT             \ init DP and continues with ABORT
19824 ;                               \
19825 \ ------------------------------\
19826
19827 \ ------------------------------\
19828 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
19829 \ ------------------------------\
19830 MOV #SLEEP,X                    \ replace default background process SLEEP
19831 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
19832 MOV #WARM,X                     \ replace default WARM
19833 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
19834 MOV X,PC                        \ then execute new WARM
19835 ENDCODE 
19836 \ ------------------------------\
19837
19838 ECHO
19839             ; downloading RC5toLCD.4th is done
19840 RST_HERE    ; this app is protected against <reset>
19841
19842
19843 RST_STATE
19844
19845 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
19846
19847 [UNDEFINED] MARKER [IF]
19848 \  https://forth-standard.org/standard/core/MARKER
19849 \  MARKER
19850 \ ( "<spaces>name" -- )
19851 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
19852 \ with the execution semantics defined below.
19853
19854 \ name Execution: ( -- )
19855 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
19856 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
19857 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
19858 \ not necessarily provided. No other contextual information such as numeric base is affected
19859 \
19860 : MARKER
19861 CREATE
19862 HI2LO
19863 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
19864 SUB #2,Y            \ 1 Y = LFA
19865 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
19866 ADD #4,&DP          \ 3 add 2 cells
19867 LO2HI
19868 DOES>
19869 HI2LO
19870 MOV @RSP+,IP        \ -- PFA
19871 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
19872 MOV @TOS,&INIDP     \       set DP value for RST_STATE
19873 MOV @PSP+,TOS       \ --
19874 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
19875 ENDCODE
19876 [THEN]
19877
19878 MARKER {RC5TOLCD}
19879
19880 [UNDEFINED] @ [IF]
19881 \ https://forth-standard.org/standard/core/Fetch
19882 \ @     c-addr -- char   fetch char from memory
19883 CODE @
19884 MOV @TOS,TOS
19885 MOV @IP+,PC
19886 ENDCODE
19887 [THEN]
19888
19889 [UNDEFINED] CONSTANT [IF]
19890 \ https://forth-standard.org/standard/core/CONSTANT
19891 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
19892 : CONSTANT 
19893 CREATE
19894 HI2LO
19895 MOV TOS,-2(W)           \   PFA = n
19896 MOV @PSP+,TOS
19897 MOV @RSP+,IP
19898 MOV @IP+,PC
19899 ENDCODE
19900 [THEN]
19901
19902 [UNDEFINED] STATE [IF]
19903 \ https://forth-standard.org/standard/core/STATE
19904 \ STATE   -- a-addr       holds compiler state
19905 STATEADR CONSTANT STATE
19906 [THEN]
19907
19908 [UNDEFINED] = [IF]
19909 \ https://forth-standard.org/standard/core/Equal
19910 \ =      x1 x2 -- flag         test x1=x2
19911 CODE =
19912 SUB @PSP+,TOS   \ 2
19913 0<> IF          \ 2
19914     AND #0,TOS  \ 1
19915     MOV @IP+,PC \ 4
19916 THEN
19917 XOR #-1,TOS     \ 1 flag Z = 1
19918 MOV @IP+,PC     \ 4
19919 ENDCODE
19920 [THEN]
19921
19922 [UNDEFINED] IF [IF]
19923 \ https://forth-standard.org/standard/core/IF
19924 \ IF       -- IFadr    initialize conditional forward branch
19925 CODE IF       \ immediate
19926 SUB #2,PSP              \
19927 MOV TOS,0(PSP)          \
19928 MOV &DP,TOS             \ -- HERE
19929 ADD #4,&DP            \           compile one word, reserve one word
19930 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
19931 ADD #2,TOS              \ -- HERE+2=IFadr
19932 MOV @IP+,PC
19933 ENDCODE IMMEDIATE
19934 [THEN]
19935
19936 [UNDEFINED] THEN [IF]
19937 \ https://forth-standard.org/standard/core/THEN
19938 \ THEN     IFadr --                resolve forward branch
19939 CODE THEN               \ immediate
19940 MOV &DP,0(TOS)          \ -- IFadr
19941 MOV @PSP+,TOS           \ --
19942 MOV @IP+,PC
19943 ENDCODE IMMEDIATE
19944 [THEN]
19945
19946 [UNDEFINED] ELSE [IF]
19947 \ https://forth-standard.org/standard/core/ELSE
19948 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
19949 CODE ELSE     \ immediate
19950 ADD #4,&DP              \ make room to compile two words
19951 MOV &DP,W               \ W=HERE+4
19952 MOV #BRAN,-4(W)
19953 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
19954 SUB #2,W                \ HERE+2
19955 MOV W,TOS               \ -- ELSEadr
19956 MOV @IP+,PC
19957 ENDCODE IMMEDIATE
19958 [THEN]
19959
19960 [UNDEFINED] DEFER [IF]
19961 \ https://forth-standard.org/standard/core/DEFER
19962 \ DEFER "<spaces>name"   --
19963 \ Skip leading space delimiters. Parse name delimited by a space.
19964 \ Create a definition for name with the execution semantics defined below.
19965
19966 \ name Execution:   --
19967 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
19968 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
19969 : DEFER
19970 CREATE
19971 HI2LO
19972 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
19973 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
19974 MOV @RSP+,IP
19975 MOV @IP+,PC
19976 ENDCODE
19977 [THEN]
19978
19979 [UNDEFINED] DEFER! [IF]
19980 \ https://forth-standard.org/standard/core/DEFERStore
19981 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
19982 CODE DEFER!             \ xt2 xt1 --
19983 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
19984 MOV @PSP+,TOS           \ --
19985 MOV @IP+,PC
19986 ENDCODE
19987 [THEN]
19988
19989 [UNDEFINED] IS [IF]
19990 \ https://forth-standard.org/standard/core/IS
19991 \ IS <name>        xt --
19992 \ used as is :
19993 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
19994 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
19995 \ or in a definition : ... ['] U. IS DISPLAY ...
19996 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
19997 \
19998 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
19999 : IS
20000 STATE @
20001 IF  POSTPONE ['] POSTPONE DEFER! 
20002 ELSE ' DEFER! 
20003 THEN
20004 ; IMMEDIATE
20005 [THEN]
20006
20007 [UNDEFINED] >BODY [IF]
20008 \ https://forth-standard.org/standard/core/toBODY
20009 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
20010 CODE >BODY
20011 ADD #4,TOS
20012 MOV @IP+,PC
20013 ENDCODE
20014 [THEN]
20015
20016 \ CODE 20uS           \ n --      8MHz version
20017 \ BEGIN               \ 4 + 16 ~ loop
20018 \     MOV #39,rDOCON   \ 39
20019 \     BEGIN           \ 4 ~ loop
20020 \         NOP
20021 \         SUB #1,rDOCON
20022 \     0=  UNTIL
20023 \     SUB #1,TOS      \ 1
20024 \ 0= UNTIL
20025 \ MOV #XDOCON,rDOCON  \ 2
20026 \ MOV @PSP+,TOS
20027 \ MOV @RSP+,IP        \
20028 \ ENDCODE
20029
20030 CODE 20_US                      \ n --      n * 20 us
20031 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
20032     BEGIN
20033         BIT #1,&LCD_TIM_CTL     \ 3
20034     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
20035     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
20036     SUB #1,TOS                  \ 1
20037 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
20038 MOV @PSP+,TOS                   \ 2
20039 MOV @IP+,PC                     \ 4
20040 ENDCODE
20041
20042 CODE TOP_LCD                    \ LCD Sample
20043 \                               \ if write : %xxxx_WWWW --
20044 \                               \ if read  : -- %0000_RRRR
20045     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
20046     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
20047 0= IF                           \ write LCD bits pattern
20048     AND.B #LCD_DB,TOS           \ 
20049     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
20050     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
20051     MOV @PSP+,TOS               \
20052     MOV @IP+,PC
20053 THEN                            \ read LCD bits pattern
20054     SUB #2,PSP
20055     MOV TOS,0(PSP)
20056     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
20057     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
20058     AND.B #LCD_DB,TOS           \
20059     MOV @IP+,PC
20060 ENDCODE
20061
20062 CODE LCD_WRC                    \ char --         Write Char
20063     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
20064 BW1 SUB #2,PSP                  \
20065     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
20066     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
20067     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
20068     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
20069 COLON                           \ high level word starts here 
20070     TOP_LCD 2 20_US             \ write high nibble first
20071     TOP_LCD 2 20_US 
20072 ;
20073
20074 CODE LCD_WRF                    \ func --         Write Fonction
20075     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
20076     GOTO BW1
20077 ENDCODE
20078
20079 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
20080 : LCD_HOME $02 LCD_WRF 100 20_us ;
20081
20082 \ [UNDEFINED] OR [IF]
20083
20084 \ \ https://forth-standard.org/standard/core/OR
20085 \ \ C OR     x1 x2 -- x3           logical OR
20086 \ CODE OR
20087 \ BIS @PSP+,TOS
20088 \ MOV @IP+,PC
20089 \ ENDCODE
20090
20091 \ [THEN]
20092
20093 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
20094 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
20095 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
20096 \ : LCD_FN_SET        $20 OR LCD_WrF ;
20097 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
20098 \ : LCD_GOTO          $80 OR LCD_WrF ;
20099
20100
20101 \ CODE LCD_RDS                    \ -- status       Read Status
20102 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
20103 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
20104 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
20105 \ COLON                           \ starts a FORTH word
20106 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
20107 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
20108 \ HI2LO                           \ switch from FORTH to assembler
20109 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
20110 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
20111 \     MOV @RSP+,IP                \ restore IP saved by COLON
20112 \     MOV @IP+,PC                 \
20113 \ ENDCODE
20114
20115 \ CODE LCD_RDC                    \ -- char         Read Char
20116 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
20117 \     GOTO BW1
20118 \ ENDCODE
20119
20120
20121 \ ******************************\
20122 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
20123 \ ******************************\
20124 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
20125 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
20126 BIT.B #SW2,&SW2_IN              \ test switch S2
20127 0= IF                           \ case of switch S2 pressed
20128     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
20129     U< IF
20130         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
20131     THEN
20132 ELSE
20133     BIT.B #SW1,&SW1_IN          \ test switch S1 input
20134     0= IF                       \ case of Switch S1 pressed
20135         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
20136         U>= IF                  \
20137            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
20138         THEN                    \
20139     THEN                        \
20140 THEN                            \
20141 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
20142 RET                             \ 5
20143 ENDASM
20144
20145 \ ******************************\
20146 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
20147 \ ******************************\
20148 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
20149 \ ******************************\
20150 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
20151 \                               \       SMclock = 8|16|24 MHz
20152 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
20153 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
20154 \                               \       SR(9)=new Toggle bit memory (ADD on)
20155 \ ******************************\
20156 \ RC5_FirstStartBitHalfCycle:   \
20157 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
20158 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
20159 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
20160 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
20161 \ [THEN]
20162 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
20163     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
20164 [THEN]
20165 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
20166     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
20167 [THEN]
20168 MOV #1778,X                     \ RC5_Period * 1us
20169 MOV #14,W                       \ count of loop
20170 BEGIN                           \
20171 \ ******************************\
20172 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
20173 \ ******************************\                   |
20174 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
20175 \ RC5_Compute_3/4_Period:       \                   |
20176     RRUM    #1,X                \ X=1/2 cycle       |
20177     MOV     X,Y                 \                   ^
20178     RRUM    #1,Y                \ Y=1/4
20179     ADD     X,Y                 \ Y=3/4 cycle
20180     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
20181     U>= UNTIL                   \ 2
20182 \ ******************************\
20183 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
20184 \ ******************************\
20185     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
20186     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
20187     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
20188     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
20189     SUB     #1,W                \ decrement count loop
20190 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
20191 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
20192 0<> WHILE                       \ ----> out of loop ----+
20193     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
20194     BEGIN                       \                       |
20195         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
20196         CMP Y,X                 \ 1                     |   cycle time out of bound ?
20197         U>= IF                  \ 2                 ^   |   yes:
20198         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
20199         GOTO BW1                \                   |   |      quit on truncated RC5 message
20200         THEN                    \                   |   |
20201         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
20202     0<> UNTIL                   \ 2                 |   |
20203 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
20204 \ ******************************\                       |
20205 \ RC5_SampleEndOf:              \ <---------------------+
20206 \ ******************************\
20207 BIC #$30,&RC5_TIM_CTL           \   stop timer
20208 \ ******************************\
20209 \ RC5_ComputeNewRC5word         \
20210 \ ******************************\
20211 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
20212 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
20213 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
20214 \ ******************************\
20215 \ RC5_ComputeC6bit              \
20216 \ ******************************\
20217 BIT     #BIT14,T                \ test /C6 bit in T
20218 0= IF   BIS #BIT6,X             \ set C6 bit in X
20219 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
20220 \ ******************************\
20221 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
20222 \ ******************************\
20223 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
20224 \ ******************************\
20225 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
20226 XOR     @RSP,T                  \ (new XOR old) Toggle bits
20227 BIT     #UF10,T                 \ repeated RC5_command ?
20228 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
20229 XOR #UF10,0(RSP)                \ 5 toggle bit memory
20230 \ ******************************\
20231 \ Display IR_RC5 code           \
20232 \ ******************************\
20233 SUB #8,PSP                      \ TOS -- x x x x TOS
20234 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
20235 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
20236 MOV #$10,&BASEADR               \                                               set hexadecimal base
20237 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
20238 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
20239 LO2HI                           \                                               switch from assembler to FORTH
20240     LCD_CLEAR                   \                                               set LCD cursor at home
20241     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
20242     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
20243     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
20244     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
20245 HI2LO                           \     --                                        switch from FORTH to assembler
20246 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
20247 MOV @PSP+,TOS                   \     -- TOS
20248 RET
20249 ENDASM
20250
20251 \ ******************************\
20252 ASM BACKGROUND                  \
20253 \ ******************************\
20254 BEGIN
20255 \     ...                         \ insert here your background task
20256 \     ...                         \
20257 \     ...                         \
20258     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
20259     BIS &LPM_MODE,SR            \
20260 \ ******************************\
20261 \ here start all interrupts     \
20262 \ ******************************\
20263 \ here return all interrupts    \
20264 \ ******************************\
20265 AGAIN                           \
20266 ENDASM                          \
20267 \ ******************************\
20268
20269 \ ------------------------------\
20270 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
20271 \ ------------------------------\
20272 \     ...                         \ init specific I/O sys as you want
20273 \     ...                         \ before executing default WARM
20274     MOV #WARM,X                 \ ['] WARM 
20275     ADD #4,X                    \ >BODY
20276     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
20277 ENDASM
20278 \ ------------------------------\
20279
20280 \ ------------------------------\
20281 CODE STOP                       \ stops multitasking, must to be used before downloading app
20282 \ ------------------------------\
20283 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
20284     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
20285     MOV X,-2(X)                 \ restore the default background: SLEEP
20286     MOV #WARM,X
20287     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
20288     BIC.B #RC5,&IR_IE           \ clear RC5_Int
20289     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
20290     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
20291     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
20292     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
20293     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
20294 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
20295 ECHO                            \
20296 ." RC5toLCD is removed,"
20297 ."  type START to restart"
20298  WARM                           \ performs reset to reset all interrupt vectors.    
20299 ;
20300 \ ------------------------------\
20301
20302 \ ------------------------------\
20303 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
20304 \ ------------------------------\
20305 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
20306 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
20307 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
20308 \                           --       \ID input divider \ 10 = /4
20309 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
20310 \                                 -  \TBCLR TimerB Clear
20311 \                                  - \TBIE
20312 \                                   -\TBIFG
20313 \ -------------------------------\
20314 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
20315 \                  --                 \CM Capture Mode
20316 \                    --               \CCIS
20317 \                       -             \SCS
20318 \                        --           \CLLD
20319 \                          -          \CAP
20320 \                            ---      \OUTMOD \ 011 = set/reset
20321 \                               -     \CCIE
20322 \                                 -   \CCI
20323 \                                  -  \OUT
20324 \                                   - \COV
20325 \                                    -\CCIFG
20326 \ -------------------------------\
20327 \ LCD_TIM_CCRx                   \
20328 \ -------------------------------\
20329 \ LCD_TIM_EX0                    \ 
20330 \ ------------------------------\
20331 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
20332 \ ------------------------------\
20333 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
20334 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
20335 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
20336     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
20337 [THEN]
20338 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
20339     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
20340 [THEN]
20341     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
20342 \ ------------------------------\
20343 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
20344 \ ------------------------------\
20345 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
20346     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
20347 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
20348 \ ------------------------------\
20349     BIS.B #LCDVo,&LCDVo_DIR     \
20350     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
20351 \ ------------------------------\
20352     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
20353     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
20354 \ ------------------------------\
20355     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
20356     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
20357 \ ******************************\
20358 \ init RC5_Int                  \
20359 \ ******************************\
20360     BIS.B #RC5,&IR_IE           \ enable RC5_Int
20361     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
20362     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
20363 \ ******************************\
20364 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
20365 \ ******************************\
20366 \              %01 0001 0100    \ TAxCTL
20367 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
20368 \                  --           \ ID        divided by 1
20369 \                    --         \ MC        MODE = up to TAxCCRn
20370 \                        -      \ TACLR     clear timer count
20371 \                         -     \ TAIE
20372 \                          -    \ TAIFG
20373 \ ------------------------------\
20374 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
20375 \ ------------------------------\
20376 \                        000    \ TAxEX0
20377 \                        ---    \ TAIDEX    pre divisor
20378 \ ------------------------------\
20379 \          %0000 0000 0000 0101 \ TAxCCR0
20380     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
20381 \ ------------------------------\
20382 \          %0000 0000 0001 0000 \ TAxCCTL0
20383 \                   -           \ CAP capture/compare mode = compare
20384 \                        -      \ CCIEn
20385 \                             - \ CCIFGn
20386     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
20387 \ ------------------------------\
20388     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
20389 \ ------------------------------\
20390 \ define LPM mode for ACCEPT    \
20391 \ ------------------------------\
20392 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
20393 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
20394 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
20395 \ ------------------------------\
20396 \ activate I/O                  \
20397 \ ------------------------------\
20398 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
20399 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
20400 \ ------------------------------\
20401 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
20402 \ ------------------------------\
20403 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
20404 \ CMP #2,Y                        \ Power_ON event
20405 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
20406 CMP #4,Y                        \
20407 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
20408 \ CMP #6,Y                        \
20409 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
20410 \ CMP #$0A,Y                      \
20411 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
20412 \ CMP #$16,Y                      \
20413 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
20414 \ ------------------------------\
20415 COLON                           \
20416 \ ------------------------------\
20417 \ Init LCD 2x20                 \
20418 \ ------------------------------\
20419     #1000 20_US                 \ 1- wait 20 ms
20420     %011 TOP_LCD                \ 2- send DB5=DB4=1
20421     #205 20_US                  \ 3- wait 4,1 ms
20422     %011 TOP_LCD                \ 4- send again DB5=DB4=1
20423     #5 20_US                    \ 5- wait 0,1 ms
20424     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
20425     #2 20_US                    \    wait 40 us = LCD cycle
20426     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
20427     #2 20_US                    \    wait 40 us = LCD cycle
20428     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
20429     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
20430     LCD_CLEAR                   \ 10- "LCD_Clear"
20431     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
20432     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
20433     LCD_CLEAR                   \ 10- "LCD_Clear"
20434     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
20435     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
20436     CR ." I love you"           \ display message on LCD
20437     ['] CR >BODY IS CR          \ CR executes its default value
20438     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
20439     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
20440     PWR_STATE ABORT             \ init DP and continues with ABORT
20441 ;                               \
20442 \ ------------------------------\
20443
20444 \ ------------------------------\
20445 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
20446 \ ------------------------------\
20447 MOV #SLEEP,X                    \ replace default background process SLEEP
20448 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
20449 MOV #WARM,X                     \ replace default WARM
20450 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
20451 MOV X,PC                        \ then execute new WARM
20452 ENDCODE 
20453 \ ------------------------------\
20454
20455 ECHO
20456             ; downloading RC5toLCD.4th is done
20457 RST_HERE    ; this app is protected against <reset>
20458
20459
20460 RST_STATE
20461
20462 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
20463
20464 [UNDEFINED] MARKER [IF]
20465 \  https://forth-standard.org/standard/core/MARKER
20466 \  MARKER
20467 \ ( "<spaces>name" -- )
20468 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
20469 \ with the execution semantics defined below.
20470
20471 \ name Execution: ( -- )
20472 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
20473 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
20474 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
20475 \ not necessarily provided. No other contextual information such as numeric base is affected
20476 \
20477 : MARKER
20478 CREATE
20479 HI2LO
20480 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
20481 SUB #2,Y            \ 1 Y = LFA
20482 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
20483 ADD #4,&DP          \ 3 add 2 cells
20484 LO2HI
20485 DOES>
20486 HI2LO
20487 MOV @RSP+,IP        \ -- PFA
20488 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
20489 MOV @TOS,&INIDP     \       set DP value for RST_STATE
20490 MOV @PSP+,TOS       \ --
20491 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
20492 ENDCODE
20493 [THEN]
20494
20495 MARKER {RC5TOLCD}
20496
20497 [UNDEFINED] @ [IF]
20498 \ https://forth-standard.org/standard/core/Fetch
20499 \ @     c-addr -- char   fetch char from memory
20500 CODE @
20501 MOV @TOS,TOS
20502 MOV @IP+,PC
20503 ENDCODE
20504 [THEN]
20505
20506 [UNDEFINED] CONSTANT [IF]
20507 \ https://forth-standard.org/standard/core/CONSTANT
20508 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
20509 : CONSTANT 
20510 CREATE
20511 HI2LO
20512 MOV TOS,-2(W)           \   PFA = n
20513 MOV @PSP+,TOS
20514 MOV @RSP+,IP
20515 MOV @IP+,PC
20516 ENDCODE
20517 [THEN]
20518
20519 [UNDEFINED] STATE [IF]
20520 \ https://forth-standard.org/standard/core/STATE
20521 \ STATE   -- a-addr       holds compiler state
20522 STATEADR CONSTANT STATE
20523 [THEN]
20524
20525 [UNDEFINED] = [IF]
20526 \ https://forth-standard.org/standard/core/Equal
20527 \ =      x1 x2 -- flag         test x1=x2
20528 CODE =
20529 SUB @PSP+,TOS   \ 2
20530 0<> IF          \ 2
20531     AND #0,TOS  \ 1
20532     MOV @IP+,PC \ 4
20533 THEN
20534 XOR #-1,TOS     \ 1 flag Z = 1
20535 MOV @IP+,PC     \ 4
20536 ENDCODE
20537 [THEN]
20538
20539 [UNDEFINED] IF [IF]
20540 \ https://forth-standard.org/standard/core/IF
20541 \ IF       -- IFadr    initialize conditional forward branch
20542 CODE IF       \ immediate
20543 SUB #2,PSP              \
20544 MOV TOS,0(PSP)          \
20545 MOV &DP,TOS             \ -- HERE
20546 ADD #4,&DP            \           compile one word, reserve one word
20547 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
20548 ADD #2,TOS              \ -- HERE+2=IFadr
20549 MOV @IP+,PC
20550 ENDCODE IMMEDIATE
20551 [THEN]
20552
20553 [UNDEFINED] THEN [IF]
20554 \ https://forth-standard.org/standard/core/THEN
20555 \ THEN     IFadr --                resolve forward branch
20556 CODE THEN               \ immediate
20557 MOV &DP,0(TOS)          \ -- IFadr
20558 MOV @PSP+,TOS           \ --
20559 MOV @IP+,PC
20560 ENDCODE IMMEDIATE
20561 [THEN]
20562
20563 [UNDEFINED] ELSE [IF]
20564 \ https://forth-standard.org/standard/core/ELSE
20565 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
20566 CODE ELSE     \ immediate
20567 ADD #4,&DP              \ make room to compile two words
20568 MOV &DP,W               \ W=HERE+4
20569 MOV #BRAN,-4(W)
20570 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
20571 SUB #2,W                \ HERE+2
20572 MOV W,TOS               \ -- ELSEadr
20573 MOV @IP+,PC
20574 ENDCODE IMMEDIATE
20575 [THEN]
20576
20577 [UNDEFINED] DEFER [IF]
20578 \ https://forth-standard.org/standard/core/DEFER
20579 \ DEFER "<spaces>name"   --
20580 \ Skip leading space delimiters. Parse name delimited by a space.
20581 \ Create a definition for name with the execution semantics defined below.
20582
20583 \ name Execution:   --
20584 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
20585 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
20586 : DEFER
20587 CREATE
20588 HI2LO
20589 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
20590 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
20591 MOV @RSP+,IP
20592 MOV @IP+,PC
20593 ENDCODE
20594 [THEN]
20595
20596 [UNDEFINED] DEFER! [IF]
20597 \ https://forth-standard.org/standard/core/DEFERStore
20598 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
20599 CODE DEFER!             \ xt2 xt1 --
20600 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
20601 MOV @PSP+,TOS           \ --
20602 MOV @IP+,PC
20603 ENDCODE
20604 [THEN]
20605
20606 [UNDEFINED] IS [IF]
20607 \ https://forth-standard.org/standard/core/IS
20608 \ IS <name>        xt --
20609 \ used as is :
20610 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
20611 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
20612 \ or in a definition : ... ['] U. IS DISPLAY ...
20613 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
20614 \
20615 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
20616 : IS
20617 STATE @
20618 IF  POSTPONE ['] POSTPONE DEFER! 
20619 ELSE ' DEFER! 
20620 THEN
20621 ; IMMEDIATE
20622 [THEN]
20623
20624 [UNDEFINED] >BODY [IF]
20625 \ https://forth-standard.org/standard/core/toBODY
20626 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
20627 CODE >BODY
20628 ADD #4,TOS
20629 MOV @IP+,PC
20630 ENDCODE
20631 [THEN]
20632
20633 \ CODE 20uS           \ n --      8MHz version
20634 \ BEGIN               \ 4 + 16 ~ loop
20635 \     MOV #39,rDOCON   \ 39
20636 \     BEGIN           \ 4 ~ loop
20637 \         NOP
20638 \         SUB #1,rDOCON
20639 \     0=  UNTIL
20640 \     SUB #1,TOS      \ 1
20641 \ 0= UNTIL
20642 \ MOV #XDOCON,rDOCON  \ 2
20643 \ MOV @PSP+,TOS
20644 \ MOV @RSP+,IP        \
20645 \ ENDCODE
20646
20647 CODE 20_US                      \ n --      n * 20 us
20648 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
20649     BEGIN
20650         BIT #1,&LCD_TIM_CTL     \ 3
20651     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
20652     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
20653     SUB #1,TOS                  \ 1
20654 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
20655 MOV @PSP+,TOS                   \ 2
20656 MOV @IP+,PC                     \ 4
20657 ENDCODE
20658
20659 CODE TOP_LCD                    \ LCD Sample
20660 \                               \ if write : %xxxx_WWWW --
20661 \                               \ if read  : -- %0000_RRRR
20662     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
20663     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
20664 0= IF                           \ write LCD bits pattern
20665     AND.B #LCD_DB,TOS           \ 
20666     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
20667     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
20668     MOV @PSP+,TOS               \
20669     MOV @IP+,PC
20670 THEN                            \ read LCD bits pattern
20671     SUB #2,PSP
20672     MOV TOS,0(PSP)
20673     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
20674     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
20675     AND.B #LCD_DB,TOS           \
20676     MOV @IP+,PC
20677 ENDCODE
20678
20679 CODE LCD_WRC                    \ char --         Write Char
20680     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
20681 BW1 SUB #2,PSP                  \
20682     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
20683     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
20684     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
20685     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
20686 COLON                           \ high level word starts here 
20687     TOP_LCD 2 20_US             \ write high nibble first
20688     TOP_LCD 2 20_US 
20689 ;
20690
20691 CODE LCD_WRF                    \ func --         Write Fonction
20692     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
20693     GOTO BW1
20694 ENDCODE
20695
20696 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
20697 : LCD_HOME $02 LCD_WRF 100 20_us ;
20698
20699 \ [UNDEFINED] OR [IF]
20700
20701 \ \ https://forth-standard.org/standard/core/OR
20702 \ \ C OR     x1 x2 -- x3           logical OR
20703 \ CODE OR
20704 \ BIS @PSP+,TOS
20705 \ MOV @IP+,PC
20706 \ ENDCODE
20707
20708 \ [THEN]
20709
20710 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
20711 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
20712 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
20713 \ : LCD_FN_SET        $20 OR LCD_WrF ;
20714 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
20715 \ : LCD_GOTO          $80 OR LCD_WrF ;
20716
20717
20718 \ CODE LCD_RDS                    \ -- status       Read Status
20719 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
20720 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
20721 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
20722 \ COLON                           \ starts a FORTH word
20723 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
20724 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
20725 \ HI2LO                           \ switch from FORTH to assembler
20726 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
20727 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
20728 \     MOV @RSP+,IP                \ restore IP saved by COLON
20729 \     MOV @IP+,PC                 \
20730 \ ENDCODE
20731
20732 \ CODE LCD_RDC                    \ -- char         Read Char
20733 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
20734 \     GOTO BW1
20735 \ ENDCODE
20736
20737
20738 \ ******************************\
20739 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
20740 \ ******************************\
20741 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
20742 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
20743 BIT.B #SW2,&SW2_IN              \ test switch S2
20744 0= IF                           \ case of switch S2 pressed
20745     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
20746     U< IF
20747         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
20748     THEN
20749 ELSE
20750     BIT.B #SW1,&SW1_IN          \ test switch S1 input
20751     0= IF                       \ case of Switch S1 pressed
20752         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
20753         U>= IF                  \
20754            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
20755         THEN                    \
20756     THEN                        \
20757 THEN                            \
20758 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
20759 RET                             \ 5
20760 ENDASM
20761
20762 \ ******************************\
20763 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
20764 \ ******************************\
20765 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
20766 \ ******************************\
20767 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
20768 \                               \       SMclock = 8|16|24 MHz
20769 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
20770 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
20771 \                               \       SR(9)=new Toggle bit memory (ADD on)
20772 \ ******************************\
20773 \ RC5_FirstStartBitHalfCycle:   \
20774 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
20775 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
20776 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
20777 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
20778 \ [THEN]
20779 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
20780     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
20781 [THEN]
20782 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
20783     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
20784 [THEN]
20785 MOV #1778,X                     \ RC5_Period * 1us
20786 MOV #14,W                       \ count of loop
20787 BEGIN                           \
20788 \ ******************************\
20789 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
20790 \ ******************************\                   |
20791 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
20792 \ RC5_Compute_3/4_Period:       \                   |
20793     RRUM    #1,X                \ X=1/2 cycle       |
20794     MOV     X,Y                 \                   ^
20795     RRUM    #1,Y                \ Y=1/4
20796     ADD     X,Y                 \ Y=3/4 cycle
20797     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
20798     U>= UNTIL                   \ 2
20799 \ ******************************\
20800 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
20801 \ ******************************\
20802     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
20803     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
20804     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
20805     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
20806     SUB     #1,W                \ decrement count loop
20807 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
20808 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
20809 0<> WHILE                       \ ----> out of loop ----+
20810     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
20811     BEGIN                       \                       |
20812         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
20813         CMP Y,X                 \ 1                     |   cycle time out of bound ?
20814         U>= IF                  \ 2                 ^   |   yes:
20815         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
20816         GOTO BW1                \                   |   |      quit on truncated RC5 message
20817         THEN                    \                   |   |
20818         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
20819     0<> UNTIL                   \ 2                 |   |
20820 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
20821 \ ******************************\                       |
20822 \ RC5_SampleEndOf:              \ <---------------------+
20823 \ ******************************\
20824 BIC #$30,&RC5_TIM_CTL           \   stop timer
20825 \ ******************************\
20826 \ RC5_ComputeNewRC5word         \
20827 \ ******************************\
20828 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
20829 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
20830 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
20831 \ ******************************\
20832 \ RC5_ComputeC6bit              \
20833 \ ******************************\
20834 BIT     #BIT14,T                \ test /C6 bit in T
20835 0= IF   BIS #BIT6,X             \ set C6 bit in X
20836 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
20837 \ ******************************\
20838 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
20839 \ ******************************\
20840 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
20841 \ ******************************\
20842 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
20843 XOR     @RSP,T                  \ (new XOR old) Toggle bits
20844 BIT     #UF10,T                 \ repeated RC5_command ?
20845 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
20846 XOR #UF10,0(RSP)                \ 5 toggle bit memory
20847 \ ******************************\
20848 \ Display IR_RC5 code           \
20849 \ ******************************\
20850 SUB #8,PSP                      \ TOS -- x x x x TOS
20851 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
20852 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
20853 MOV #$10,&BASEADR               \                                               set hexadecimal base
20854 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
20855 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
20856 LO2HI                           \                                               switch from assembler to FORTH
20857     LCD_CLEAR                   \                                               set LCD cursor at home
20858     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
20859     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
20860     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
20861     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
20862 HI2LO                           \     --                                        switch from FORTH to assembler
20863 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
20864 MOV @PSP+,TOS                   \     -- TOS
20865 RET
20866 ENDASM
20867
20868 \ ******************************\
20869 ASM BACKGROUND                  \
20870 \ ******************************\
20871 BEGIN
20872 \     ...                         \ insert here your background task
20873 \     ...                         \
20874 \     ...                         \
20875     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
20876     BIS &LPM_MODE,SR            \
20877 \ ******************************\
20878 \ here start all interrupts     \
20879 \ ******************************\
20880 \ here return all interrupts    \
20881 \ ******************************\
20882 AGAIN                           \
20883 ENDASM                          \
20884 \ ******************************\
20885
20886 \ ------------------------------\
20887 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
20888 \ ------------------------------\
20889 \     ...                         \ init specific I/O sys as you want
20890 \     ...                         \ before executing default WARM
20891     MOV #WARM,X                 \ ['] WARM 
20892     ADD #4,X                    \ >BODY
20893     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
20894 ENDASM
20895 \ ------------------------------\
20896
20897 \ ------------------------------\
20898 CODE STOP                       \ stops multitasking, must to be used before downloading app
20899 \ ------------------------------\
20900 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
20901     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
20902     MOV X,-2(X)                 \ restore the default background: SLEEP
20903     MOV #WARM,X
20904     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
20905     BIC.B #RC5,&IR_IE           \ clear RC5_Int
20906     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
20907     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
20908     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
20909     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
20910     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
20911 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
20912 ECHO                            \
20913 ." RC5toLCD is removed,"
20914 ."  type START to restart"
20915  WARM                           \ performs reset to reset all interrupt vectors.    
20916 ;
20917 \ ------------------------------\
20918
20919 \ ------------------------------\
20920 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
20921 \ ------------------------------\
20922 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
20923 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
20924 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
20925 \                           --       \ID input divider \ 10 = /4
20926 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
20927 \                                 -  \TBCLR TimerB Clear
20928 \                                  - \TBIE
20929 \                                   -\TBIFG
20930 \ -------------------------------\
20931 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
20932 \                  --                 \CM Capture Mode
20933 \                    --               \CCIS
20934 \                       -             \SCS
20935 \                        --           \CLLD
20936 \                          -          \CAP
20937 \                            ---      \OUTMOD \ 011 = set/reset
20938 \                               -     \CCIE
20939 \                                 -   \CCI
20940 \                                  -  \OUT
20941 \                                   - \COV
20942 \                                    -\CCIFG
20943 \ -------------------------------\
20944 \ LCD_TIM_CCRx                   \
20945 \ -------------------------------\
20946 \ LCD_TIM_EX0                    \ 
20947 \ ------------------------------\
20948 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
20949 \ ------------------------------\
20950 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
20951 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
20952 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
20953     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
20954 [THEN]
20955 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
20956     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
20957 [THEN]
20958     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
20959 \ ------------------------------\
20960 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
20961 \ ------------------------------\
20962 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
20963     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
20964 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
20965 \ ------------------------------\
20966     BIS.B #LCDVo,&LCDVo_DIR     \
20967     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
20968 \ ------------------------------\
20969     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
20970     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
20971 \ ------------------------------\
20972     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
20973     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
20974 \ ******************************\
20975 \ init RC5_Int                  \
20976 \ ******************************\
20977     BIS.B #RC5,&IR_IE           \ enable RC5_Int
20978     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
20979     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
20980 \ ******************************\
20981 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
20982 \ ******************************\
20983 \              %01 0001 0100    \ TAxCTL
20984 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
20985 \                  --           \ ID        divided by 1
20986 \                    --         \ MC        MODE = up to TAxCCRn
20987 \                        -      \ TACLR     clear timer count
20988 \                         -     \ TAIE
20989 \                          -    \ TAIFG
20990 \ ------------------------------\
20991 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
20992 \ ------------------------------\
20993 \                        000    \ TAxEX0
20994 \                        ---    \ TAIDEX    pre divisor
20995 \ ------------------------------\
20996 \          %0000 0000 0000 0101 \ TAxCCR0
20997     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
20998 \ ------------------------------\
20999 \          %0000 0000 0001 0000 \ TAxCCTL0
21000 \                   -           \ CAP capture/compare mode = compare
21001 \                        -      \ CCIEn
21002 \                             - \ CCIFGn
21003     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
21004 \ ------------------------------\
21005     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
21006 \ ------------------------------\
21007 \ define LPM mode for ACCEPT    \
21008 \ ------------------------------\
21009 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
21010 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
21011 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
21012 \ ------------------------------\
21013 \ activate I/O                  \
21014 \ ------------------------------\
21015 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
21016 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
21017 \ ------------------------------\
21018 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
21019 \ ------------------------------\
21020 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
21021 \ CMP #2,Y                        \ Power_ON event
21022 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
21023 CMP #4,Y                        \
21024 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
21025 \ CMP #6,Y                        \
21026 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
21027 \ CMP #$0A,Y                      \
21028 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
21029 \ CMP #$16,Y                      \
21030 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
21031 \ ------------------------------\
21032 COLON                           \
21033 \ ------------------------------\
21034 \ Init LCD 2x20                 \
21035 \ ------------------------------\
21036     #1000 20_US                 \ 1- wait 20 ms
21037     %011 TOP_LCD                \ 2- send DB5=DB4=1
21038     #205 20_US                  \ 3- wait 4,1 ms
21039     %011 TOP_LCD                \ 4- send again DB5=DB4=1
21040     #5 20_US                    \ 5- wait 0,1 ms
21041     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
21042     #2 20_US                    \    wait 40 us = LCD cycle
21043     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
21044     #2 20_US                    \    wait 40 us = LCD cycle
21045     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
21046     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
21047     LCD_CLEAR                   \ 10- "LCD_Clear"
21048     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
21049     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
21050     LCD_CLEAR                   \ 10- "LCD_Clear"
21051     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
21052     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
21053     CR ." I love you"           \ display message on LCD
21054     ['] CR >BODY IS CR          \ CR executes its default value
21055     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
21056     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
21057     PWR_STATE ABORT             \ init DP and continues with ABORT
21058 ;                               \
21059 \ ------------------------------\
21060
21061 \ ------------------------------\
21062 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
21063 \ ------------------------------\
21064 MOV #SLEEP,X                    \ replace default background process SLEEP
21065 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
21066 MOV #WARM,X                     \ replace default WARM
21067 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
21068 MOV X,PC                        \ then execute new WARM
21069 ENDCODE 
21070 \ ------------------------------\
21071
21072 ECHO
21073             ; downloading RC5toLCD.4th is done
21074 RST_HERE    ; this app is protected against <reset>
21075
21076
21077 RST_STATE
21078
21079 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
21080
21081 [UNDEFINED] MARKER [IF]
21082 \  https://forth-standard.org/standard/core/MARKER
21083 \  MARKER
21084 \ ( "<spaces>name" -- )
21085 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
21086 \ with the execution semantics defined below.
21087
21088 \ name Execution: ( -- )
21089 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
21090 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
21091 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
21092 \ not necessarily provided. No other contextual information such as numeric base is affected
21093 \
21094 : MARKER
21095 CREATE
21096 HI2LO
21097 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
21098 SUB #2,Y            \ 1 Y = LFA
21099 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
21100 ADD #4,&DP          \ 3 add 2 cells
21101 LO2HI
21102 DOES>
21103 HI2LO
21104 MOV @RSP+,IP        \ -- PFA
21105 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
21106 MOV @TOS,&INIDP     \       set DP value for RST_STATE
21107 MOV @PSP+,TOS       \ --
21108 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
21109 ENDCODE
21110 [THEN]
21111
21112 MARKER {RC5TOLCD}
21113
21114 [UNDEFINED] @ [IF]
21115 \ https://forth-standard.org/standard/core/Fetch
21116 \ @     c-addr -- char   fetch char from memory
21117 CODE @
21118 MOV @TOS,TOS
21119 MOV @IP+,PC
21120 ENDCODE
21121 [THEN]
21122
21123 [UNDEFINED] CONSTANT [IF]
21124 \ https://forth-standard.org/standard/core/CONSTANT
21125 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
21126 : CONSTANT 
21127 CREATE
21128 HI2LO
21129 MOV TOS,-2(W)           \   PFA = n
21130 MOV @PSP+,TOS
21131 MOV @RSP+,IP
21132 MOV @IP+,PC
21133 ENDCODE
21134 [THEN]
21135
21136 [UNDEFINED] STATE [IF]
21137 \ https://forth-standard.org/standard/core/STATE
21138 \ STATE   -- a-addr       holds compiler state
21139 STATEADR CONSTANT STATE
21140 [THEN]
21141
21142 [UNDEFINED] = [IF]
21143 \ https://forth-standard.org/standard/core/Equal
21144 \ =      x1 x2 -- flag         test x1=x2
21145 CODE =
21146 SUB @PSP+,TOS   \ 2
21147 0<> IF          \ 2
21148     AND #0,TOS  \ 1
21149     MOV @IP+,PC \ 4
21150 THEN
21151 XOR #-1,TOS     \ 1 flag Z = 1
21152 MOV @IP+,PC     \ 4
21153 ENDCODE
21154 [THEN]
21155
21156 [UNDEFINED] IF [IF]
21157 \ https://forth-standard.org/standard/core/IF
21158 \ IF       -- IFadr    initialize conditional forward branch
21159 CODE IF       \ immediate
21160 SUB #2,PSP              \
21161 MOV TOS,0(PSP)          \
21162 MOV &DP,TOS             \ -- HERE
21163 ADD #4,&DP            \           compile one word, reserve one word
21164 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
21165 ADD #2,TOS              \ -- HERE+2=IFadr
21166 MOV @IP+,PC
21167 ENDCODE IMMEDIATE
21168 [THEN]
21169
21170 [UNDEFINED] THEN [IF]
21171 \ https://forth-standard.org/standard/core/THEN
21172 \ THEN     IFadr --                resolve forward branch
21173 CODE THEN               \ immediate
21174 MOV &DP,0(TOS)          \ -- IFadr
21175 MOV @PSP+,TOS           \ --
21176 MOV @IP+,PC
21177 ENDCODE IMMEDIATE
21178 [THEN]
21179
21180 [UNDEFINED] ELSE [IF]
21181 \ https://forth-standard.org/standard/core/ELSE
21182 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
21183 CODE ELSE     \ immediate
21184 ADD #4,&DP              \ make room to compile two words
21185 MOV &DP,W               \ W=HERE+4
21186 MOV #BRAN,-4(W)
21187 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
21188 SUB #2,W                \ HERE+2
21189 MOV W,TOS               \ -- ELSEadr
21190 MOV @IP+,PC
21191 ENDCODE IMMEDIATE
21192 [THEN]
21193
21194 [UNDEFINED] DEFER [IF]
21195 \ https://forth-standard.org/standard/core/DEFER
21196 \ DEFER "<spaces>name"   --
21197 \ Skip leading space delimiters. Parse name delimited by a space.
21198 \ Create a definition for name with the execution semantics defined below.
21199
21200 \ name Execution:   --
21201 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
21202 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
21203 : DEFER
21204 CREATE
21205 HI2LO
21206 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
21207 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
21208 MOV @RSP+,IP
21209 MOV @IP+,PC
21210 ENDCODE
21211 [THEN]
21212
21213 [UNDEFINED] DEFER! [IF]
21214 \ https://forth-standard.org/standard/core/DEFERStore
21215 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
21216 CODE DEFER!             \ xt2 xt1 --
21217 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
21218 MOV @PSP+,TOS           \ --
21219 MOV @IP+,PC
21220 ENDCODE
21221 [THEN]
21222
21223 [UNDEFINED] IS [IF]
21224 \ https://forth-standard.org/standard/core/IS
21225 \ IS <name>        xt --
21226 \ used as is :
21227 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
21228 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
21229 \ or in a definition : ... ['] U. IS DISPLAY ...
21230 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
21231 \
21232 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
21233 : IS
21234 STATE @
21235 IF  POSTPONE ['] POSTPONE DEFER! 
21236 ELSE ' DEFER! 
21237 THEN
21238 ; IMMEDIATE
21239 [THEN]
21240
21241 [UNDEFINED] >BODY [IF]
21242 \ https://forth-standard.org/standard/core/toBODY
21243 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
21244 CODE >BODY
21245 ADD #4,TOS
21246 MOV @IP+,PC
21247 ENDCODE
21248 [THEN]
21249
21250 \ CODE 20uS           \ n --      8MHz version
21251 \ BEGIN               \ 4 + 16 ~ loop
21252 \     MOV #39,rDOCON   \ 39
21253 \     BEGIN           \ 4 ~ loop
21254 \         NOP
21255 \         SUB #1,rDOCON
21256 \     0=  UNTIL
21257 \     SUB #1,TOS      \ 1
21258 \ 0= UNTIL
21259 \ MOV #XDOCON,rDOCON  \ 2
21260 \ MOV @PSP+,TOS
21261 \ MOV @RSP+,IP        \
21262 \ ENDCODE
21263
21264 CODE 20_US                      \ n --      n * 20 us
21265 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
21266     BEGIN
21267         BIT #1,&LCD_TIM_CTL     \ 3
21268     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
21269     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
21270     SUB #1,TOS                  \ 1
21271 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
21272 MOV @PSP+,TOS                   \ 2
21273 MOV @IP+,PC                     \ 4
21274 ENDCODE
21275
21276 CODE TOP_LCD                    \ LCD Sample
21277 \                               \ if write : %xxxx_WWWW --
21278 \                               \ if read  : -- %0000_RRRR
21279     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
21280     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
21281 0= IF                           \ write LCD bits pattern
21282     AND.B #LCD_DB,TOS           \ 
21283     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
21284     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
21285     MOV @PSP+,TOS               \
21286     MOV @IP+,PC
21287 THEN                            \ read LCD bits pattern
21288     SUB #2,PSP
21289     MOV TOS,0(PSP)
21290     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
21291     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
21292     AND.B #LCD_DB,TOS           \
21293     MOV @IP+,PC
21294 ENDCODE
21295
21296 CODE LCD_WRC                    \ char --         Write Char
21297     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
21298 BW1 SUB #2,PSP                  \
21299     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
21300     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
21301     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
21302     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
21303 COLON                           \ high level word starts here 
21304     TOP_LCD 2 20_US             \ write high nibble first
21305     TOP_LCD 2 20_US 
21306 ;
21307
21308 CODE LCD_WRF                    \ func --         Write Fonction
21309     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
21310     GOTO BW1
21311 ENDCODE
21312
21313 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
21314 : LCD_HOME $02 LCD_WRF 100 20_us ;
21315
21316 \ [UNDEFINED] OR [IF]
21317
21318 \ \ https://forth-standard.org/standard/core/OR
21319 \ \ C OR     x1 x2 -- x3           logical OR
21320 \ CODE OR
21321 \ BIS @PSP+,TOS
21322 \ MOV @IP+,PC
21323 \ ENDCODE
21324
21325 \ [THEN]
21326
21327 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
21328 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
21329 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
21330 \ : LCD_FN_SET        $20 OR LCD_WrF ;
21331 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
21332 \ : LCD_GOTO          $80 OR LCD_WrF ;
21333
21334
21335 \ CODE LCD_RDS                    \ -- status       Read Status
21336 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
21337 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
21338 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
21339 \ COLON                           \ starts a FORTH word
21340 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
21341 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
21342 \ HI2LO                           \ switch from FORTH to assembler
21343 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
21344 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
21345 \     MOV @RSP+,IP                \ restore IP saved by COLON
21346 \     MOV @IP+,PC                 \
21347 \ ENDCODE
21348
21349 \ CODE LCD_RDC                    \ -- char         Read Char
21350 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
21351 \     GOTO BW1
21352 \ ENDCODE
21353
21354
21355 \ ******************************\
21356 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
21357 \ ******************************\
21358 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
21359 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
21360 BIT.B #SW2,&SW2_IN              \ test switch S2
21361 0= IF                           \ case of switch S2 pressed
21362     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
21363     U< IF
21364         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
21365     THEN
21366 ELSE
21367     BIT.B #SW1,&SW1_IN          \ test switch S1 input
21368     0= IF                       \ case of Switch S1 pressed
21369         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
21370         U>= IF                  \
21371            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
21372         THEN                    \
21373     THEN                        \
21374 THEN                            \
21375 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
21376 RET                             \ 5
21377 ENDASM
21378
21379 \ ******************************\
21380 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
21381 \ ******************************\
21382 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
21383 \ ******************************\
21384 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
21385 \                               \       SMclock = 8|16|24 MHz
21386 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
21387 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
21388 \                               \       SR(9)=new Toggle bit memory (ADD on)
21389 \ ******************************\
21390 \ RC5_FirstStartBitHalfCycle:   \
21391 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
21392 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
21393 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
21394 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
21395 \ [THEN]
21396 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
21397     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
21398 [THEN]
21399 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
21400     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
21401 [THEN]
21402 MOV #1778,X                     \ RC5_Period * 1us
21403 MOV #14,W                       \ count of loop
21404 BEGIN                           \
21405 \ ******************************\
21406 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
21407 \ ******************************\                   |
21408 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
21409 \ RC5_Compute_3/4_Period:       \                   |
21410     RRUM    #1,X                \ X=1/2 cycle       |
21411     MOV     X,Y                 \                   ^
21412     RRUM    #1,Y                \ Y=1/4
21413     ADD     X,Y                 \ Y=3/4 cycle
21414     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
21415     U>= UNTIL                   \ 2
21416 \ ******************************\
21417 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
21418 \ ******************************\
21419     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
21420     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
21421     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
21422     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
21423     SUB     #1,W                \ decrement count loop
21424 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
21425 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
21426 0<> WHILE                       \ ----> out of loop ----+
21427     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
21428     BEGIN                       \                       |
21429         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
21430         CMP Y,X                 \ 1                     |   cycle time out of bound ?
21431         U>= IF                  \ 2                 ^   |   yes:
21432         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
21433         GOTO BW1                \                   |   |      quit on truncated RC5 message
21434         THEN                    \                   |   |
21435         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
21436     0<> UNTIL                   \ 2                 |   |
21437 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
21438 \ ******************************\                       |
21439 \ RC5_SampleEndOf:              \ <---------------------+
21440 \ ******************************\
21441 BIC #$30,&RC5_TIM_CTL           \   stop timer
21442 \ ******************************\
21443 \ RC5_ComputeNewRC5word         \
21444 \ ******************************\
21445 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
21446 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
21447 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
21448 \ ******************************\
21449 \ RC5_ComputeC6bit              \
21450 \ ******************************\
21451 BIT     #BIT14,T                \ test /C6 bit in T
21452 0= IF   BIS #BIT6,X             \ set C6 bit in X
21453 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
21454 \ ******************************\
21455 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
21456 \ ******************************\
21457 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
21458 \ ******************************\
21459 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
21460 XOR     @RSP,T                  \ (new XOR old) Toggle bits
21461 BIT     #UF10,T                 \ repeated RC5_command ?
21462 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
21463 XOR #UF10,0(RSP)                \ 5 toggle bit memory
21464 \ ******************************\
21465 \ Display IR_RC5 code           \
21466 \ ******************************\
21467 SUB #8,PSP                      \ TOS -- x x x x TOS
21468 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
21469 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
21470 MOV #$10,&BASEADR               \                                               set hexadecimal base
21471 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
21472 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
21473 LO2HI                           \                                               switch from assembler to FORTH
21474     LCD_CLEAR                   \                                               set LCD cursor at home
21475     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
21476     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
21477     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
21478     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
21479 HI2LO                           \     --                                        switch from FORTH to assembler
21480 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
21481 MOV @PSP+,TOS                   \     -- TOS
21482 RET
21483 ENDASM
21484
21485 \ ******************************\
21486 ASM BACKGROUND                  \
21487 \ ******************************\
21488 BEGIN
21489 \     ...                         \ insert here your background task
21490 \     ...                         \
21491 \     ...                         \
21492     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
21493     BIS &LPM_MODE,SR            \
21494 \ ******************************\
21495 \ here start all interrupts     \
21496 \ ******************************\
21497 \ here return all interrupts    \
21498 \ ******************************\
21499 AGAIN                           \
21500 ENDASM                          \
21501 \ ******************************\
21502
21503 \ ------------------------------\
21504 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
21505 \ ------------------------------\
21506 \     ...                         \ init specific I/O sys as you want
21507 \     ...                         \ before executing default WARM
21508     MOV #WARM,X                 \ ['] WARM 
21509     ADD #4,X                    \ >BODY
21510     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
21511 ENDASM
21512 \ ------------------------------\
21513
21514 \ ------------------------------\
21515 CODE STOP                       \ stops multitasking, must to be used before downloading app
21516 \ ------------------------------\
21517 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
21518     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
21519     MOV X,-2(X)                 \ restore the default background: SLEEP
21520     MOV #WARM,X
21521     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
21522     BIC.B #RC5,&IR_IE           \ clear RC5_Int
21523     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
21524     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
21525     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
21526     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
21527     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
21528 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
21529 ECHO                            \
21530 ." RC5toLCD is removed,"
21531 ."  type START to restart"
21532  WARM                           \ performs reset to reset all interrupt vectors.    
21533 ;
21534 \ ------------------------------\
21535
21536 \ ------------------------------\
21537 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
21538 \ ------------------------------\
21539 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
21540 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
21541 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
21542 \                           --       \ID input divider \ 10 = /4
21543 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
21544 \                                 -  \TBCLR TimerB Clear
21545 \                                  - \TBIE
21546 \                                   -\TBIFG
21547 \ -------------------------------\
21548 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
21549 \                  --                 \CM Capture Mode
21550 \                    --               \CCIS
21551 \                       -             \SCS
21552 \                        --           \CLLD
21553 \                          -          \CAP
21554 \                            ---      \OUTMOD \ 011 = set/reset
21555 \                               -     \CCIE
21556 \                                 -   \CCI
21557 \                                  -  \OUT
21558 \                                   - \COV
21559 \                                    -\CCIFG
21560 \ -------------------------------\
21561 \ LCD_TIM_CCRx                   \
21562 \ -------------------------------\
21563 \ LCD_TIM_EX0                    \ 
21564 \ ------------------------------\
21565 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
21566 \ ------------------------------\
21567 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
21568 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
21569 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
21570     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
21571 [THEN]
21572 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
21573     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
21574 [THEN]
21575     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
21576 \ ------------------------------\
21577 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
21578 \ ------------------------------\
21579 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
21580     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
21581 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
21582 \ ------------------------------\
21583     BIS.B #LCDVo,&LCDVo_DIR     \
21584     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
21585 \ ------------------------------\
21586     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
21587     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
21588 \ ------------------------------\
21589     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
21590     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
21591 \ ******************************\
21592 \ init RC5_Int                  \
21593 \ ******************************\
21594     BIS.B #RC5,&IR_IE           \ enable RC5_Int
21595     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
21596     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
21597 \ ******************************\
21598 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
21599 \ ******************************\
21600 \              %01 0001 0100    \ TAxCTL
21601 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
21602 \                  --           \ ID        divided by 1
21603 \                    --         \ MC        MODE = up to TAxCCRn
21604 \                        -      \ TACLR     clear timer count
21605 \                         -     \ TAIE
21606 \                          -    \ TAIFG
21607 \ ------------------------------\
21608 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
21609 \ ------------------------------\
21610 \                        000    \ TAxEX0
21611 \                        ---    \ TAIDEX    pre divisor
21612 \ ------------------------------\
21613 \          %0000 0000 0000 0101 \ TAxCCR0
21614     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
21615 \ ------------------------------\
21616 \          %0000 0000 0001 0000 \ TAxCCTL0
21617 \                   -           \ CAP capture/compare mode = compare
21618 \                        -      \ CCIEn
21619 \                             - \ CCIFGn
21620     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
21621 \ ------------------------------\
21622     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
21623 \ ------------------------------\
21624 \ define LPM mode for ACCEPT    \
21625 \ ------------------------------\
21626 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
21627 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
21628 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
21629 \ ------------------------------\
21630 \ activate I/O                  \
21631 \ ------------------------------\
21632 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
21633 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
21634 \ ------------------------------\
21635 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
21636 \ ------------------------------\
21637 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
21638 \ CMP #2,Y                        \ Power_ON event
21639 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
21640 CMP #4,Y                        \
21641 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
21642 \ CMP #6,Y                        \
21643 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
21644 \ CMP #$0A,Y                      \
21645 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
21646 \ CMP #$16,Y                      \
21647 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
21648 \ ------------------------------\
21649 COLON                           \
21650 \ ------------------------------\
21651 \ Init LCD 2x20                 \
21652 \ ------------------------------\
21653     #1000 20_US                 \ 1- wait 20 ms
21654     %011 TOP_LCD                \ 2- send DB5=DB4=1
21655     #205 20_US                  \ 3- wait 4,1 ms
21656     %011 TOP_LCD                \ 4- send again DB5=DB4=1
21657     #5 20_US                    \ 5- wait 0,1 ms
21658     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
21659     #2 20_US                    \    wait 40 us = LCD cycle
21660     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
21661     #2 20_US                    \    wait 40 us = LCD cycle
21662     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
21663     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
21664     LCD_CLEAR                   \ 10- "LCD_Clear"
21665     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
21666     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
21667     LCD_CLEAR                   \ 10- "LCD_Clear"
21668     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
21669     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
21670     CR ." I love you"           \ display message on LCD
21671     ['] CR >BODY IS CR          \ CR executes its default value
21672     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
21673     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
21674     PWR_STATE ABORT             \ init DP and continues with ABORT
21675 ;                               \
21676 \ ------------------------------\
21677
21678 \ ------------------------------\
21679 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
21680 \ ------------------------------\
21681 MOV #SLEEP,X                    \ replace default background process SLEEP
21682 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
21683 MOV #WARM,X                     \ replace default WARM
21684 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
21685 MOV X,PC                        \ then execute new WARM
21686 ENDCODE 
21687 \ ------------------------------\
21688
21689 ECHO
21690             ; downloading RC5toLCD.4th is done
21691 RST_HERE    ; this app is protected against <reset>
21692
21693
21694 RST_STATE
21695
21696 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
21697
21698 [UNDEFINED] MARKER [IF]
21699 \  https://forth-standard.org/standard/core/MARKER
21700 \  MARKER
21701 \ ( "<spaces>name" -- )
21702 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
21703 \ with the execution semantics defined below.
21704
21705 \ name Execution: ( -- )
21706 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
21707 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
21708 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
21709 \ not necessarily provided. No other contextual information such as numeric base is affected
21710 \
21711 : MARKER
21712 CREATE
21713 HI2LO
21714 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
21715 SUB #2,Y            \ 1 Y = LFA
21716 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
21717 ADD #4,&DP          \ 3 add 2 cells
21718 LO2HI
21719 DOES>
21720 HI2LO
21721 MOV @RSP+,IP        \ -- PFA
21722 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
21723 MOV @TOS,&INIDP     \       set DP value for RST_STATE
21724 MOV @PSP+,TOS       \ --
21725 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
21726 ENDCODE
21727 [THEN]
21728
21729 MARKER {RC5TOLCD}
21730
21731 [UNDEFINED] @ [IF]
21732 \ https://forth-standard.org/standard/core/Fetch
21733 \ @     c-addr -- char   fetch char from memory
21734 CODE @
21735 MOV @TOS,TOS
21736 MOV @IP+,PC
21737 ENDCODE
21738 [THEN]
21739
21740 [UNDEFINED] CONSTANT [IF]
21741 \ https://forth-standard.org/standard/core/CONSTANT
21742 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
21743 : CONSTANT 
21744 CREATE
21745 HI2LO
21746 MOV TOS,-2(W)           \   PFA = n
21747 MOV @PSP+,TOS
21748 MOV @RSP+,IP
21749 MOV @IP+,PC
21750 ENDCODE
21751 [THEN]
21752
21753 [UNDEFINED] STATE [IF]
21754 \ https://forth-standard.org/standard/core/STATE
21755 \ STATE   -- a-addr       holds compiler state
21756 STATEADR CONSTANT STATE
21757 [THEN]
21758
21759 [UNDEFINED] = [IF]
21760 \ https://forth-standard.org/standard/core/Equal
21761 \ =      x1 x2 -- flag         test x1=x2
21762 CODE =
21763 SUB @PSP+,TOS   \ 2
21764 0<> IF          \ 2
21765     AND #0,TOS  \ 1
21766     MOV @IP+,PC \ 4
21767 THEN
21768 XOR #-1,TOS     \ 1 flag Z = 1
21769 MOV @IP+,PC     \ 4
21770 ENDCODE
21771 [THEN]
21772
21773 [UNDEFINED] IF [IF]
21774 \ https://forth-standard.org/standard/core/IF
21775 \ IF       -- IFadr    initialize conditional forward branch
21776 CODE IF       \ immediate
21777 SUB #2,PSP              \
21778 MOV TOS,0(PSP)          \
21779 MOV &DP,TOS             \ -- HERE
21780 ADD #4,&DP            \           compile one word, reserve one word
21781 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
21782 ADD #2,TOS              \ -- HERE+2=IFadr
21783 MOV @IP+,PC
21784 ENDCODE IMMEDIATE
21785 [THEN]
21786
21787 [UNDEFINED] THEN [IF]
21788 \ https://forth-standard.org/standard/core/THEN
21789 \ THEN     IFadr --                resolve forward branch
21790 CODE THEN               \ immediate
21791 MOV &DP,0(TOS)          \ -- IFadr
21792 MOV @PSP+,TOS           \ --
21793 MOV @IP+,PC
21794 ENDCODE IMMEDIATE
21795 [THEN]
21796
21797 [UNDEFINED] ELSE [IF]
21798 \ https://forth-standard.org/standard/core/ELSE
21799 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
21800 CODE ELSE     \ immediate
21801 ADD #4,&DP              \ make room to compile two words
21802 MOV &DP,W               \ W=HERE+4
21803 MOV #BRAN,-4(W)
21804 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
21805 SUB #2,W                \ HERE+2
21806 MOV W,TOS               \ -- ELSEadr
21807 MOV @IP+,PC
21808 ENDCODE IMMEDIATE
21809 [THEN]
21810
21811 [UNDEFINED] DEFER [IF]
21812 \ https://forth-standard.org/standard/core/DEFER
21813 \ DEFER "<spaces>name"   --
21814 \ Skip leading space delimiters. Parse name delimited by a space.
21815 \ Create a definition for name with the execution semantics defined below.
21816
21817 \ name Execution:   --
21818 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
21819 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
21820 : DEFER
21821 CREATE
21822 HI2LO
21823 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
21824 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
21825 MOV @RSP+,IP
21826 MOV @IP+,PC
21827 ENDCODE
21828 [THEN]
21829
21830 [UNDEFINED] DEFER! [IF]
21831 \ https://forth-standard.org/standard/core/DEFERStore
21832 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
21833 CODE DEFER!             \ xt2 xt1 --
21834 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
21835 MOV @PSP+,TOS           \ --
21836 MOV @IP+,PC
21837 ENDCODE
21838 [THEN]
21839
21840 [UNDEFINED] IS [IF]
21841 \ https://forth-standard.org/standard/core/IS
21842 \ IS <name>        xt --
21843 \ used as is :
21844 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
21845 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
21846 \ or in a definition : ... ['] U. IS DISPLAY ...
21847 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
21848 \
21849 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
21850 : IS
21851 STATE @
21852 IF  POSTPONE ['] POSTPONE DEFER! 
21853 ELSE ' DEFER! 
21854 THEN
21855 ; IMMEDIATE
21856 [THEN]
21857
21858 [UNDEFINED] >BODY [IF]
21859 \ https://forth-standard.org/standard/core/toBODY
21860 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
21861 CODE >BODY
21862 ADD #4,TOS
21863 MOV @IP+,PC
21864 ENDCODE
21865 [THEN]
21866
21867 \ CODE 20uS           \ n --      8MHz version
21868 \ BEGIN               \ 4 + 16 ~ loop
21869 \     MOV #39,rDOCON   \ 39
21870 \     BEGIN           \ 4 ~ loop
21871 \         NOP
21872 \         SUB #1,rDOCON
21873 \     0=  UNTIL
21874 \     SUB #1,TOS      \ 1
21875 \ 0= UNTIL
21876 \ MOV #XDOCON,rDOCON  \ 2
21877 \ MOV @PSP+,TOS
21878 \ MOV @RSP+,IP        \
21879 \ ENDCODE
21880
21881 CODE 20_US                      \ n --      n * 20 us
21882 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
21883     BEGIN
21884         BIT #1,&LCD_TIM_CTL     \ 3
21885     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
21886     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
21887     SUB #1,TOS                  \ 1
21888 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
21889 MOV @PSP+,TOS                   \ 2
21890 MOV @IP+,PC                     \ 4
21891 ENDCODE
21892
21893 CODE TOP_LCD                    \ LCD Sample
21894 \                               \ if write : %xxxx_WWWW --
21895 \                               \ if read  : -- %0000_RRRR
21896     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
21897     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
21898 0= IF                           \ write LCD bits pattern
21899     AND.B #LCD_DB,TOS           \ 
21900     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
21901     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
21902     MOV @PSP+,TOS               \
21903     MOV @IP+,PC
21904 THEN                            \ read LCD bits pattern
21905     SUB #2,PSP
21906     MOV TOS,0(PSP)
21907     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
21908     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
21909     AND.B #LCD_DB,TOS           \
21910     MOV @IP+,PC
21911 ENDCODE
21912
21913 CODE LCD_WRC                    \ char --         Write Char
21914     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
21915 BW1 SUB #2,PSP                  \
21916     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
21917     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
21918     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
21919     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
21920 COLON                           \ high level word starts here 
21921     TOP_LCD 2 20_US             \ write high nibble first
21922     TOP_LCD 2 20_US 
21923 ;
21924
21925 CODE LCD_WRF                    \ func --         Write Fonction
21926     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
21927     GOTO BW1
21928 ENDCODE
21929
21930 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
21931 : LCD_HOME $02 LCD_WRF 100 20_us ;
21932
21933 \ [UNDEFINED] OR [IF]
21934
21935 \ \ https://forth-standard.org/standard/core/OR
21936 \ \ C OR     x1 x2 -- x3           logical OR
21937 \ CODE OR
21938 \ BIS @PSP+,TOS
21939 \ MOV @IP+,PC
21940 \ ENDCODE
21941
21942 \ [THEN]
21943
21944 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
21945 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
21946 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
21947 \ : LCD_FN_SET        $20 OR LCD_WrF ;
21948 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
21949 \ : LCD_GOTO          $80 OR LCD_WrF ;
21950
21951
21952 \ CODE LCD_RDS                    \ -- status       Read Status
21953 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
21954 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
21955 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
21956 \ COLON                           \ starts a FORTH word
21957 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
21958 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
21959 \ HI2LO                           \ switch from FORTH to assembler
21960 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
21961 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
21962 \     MOV @RSP+,IP                \ restore IP saved by COLON
21963 \     MOV @IP+,PC                 \
21964 \ ENDCODE
21965
21966 \ CODE LCD_RDC                    \ -- char         Read Char
21967 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
21968 \     GOTO BW1
21969 \ ENDCODE
21970
21971
21972 \ ******************************\
21973 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
21974 \ ******************************\
21975 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
21976 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
21977 BIT.B #SW2,&SW2_IN              \ test switch S2
21978 0= IF                           \ case of switch S2 pressed
21979     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
21980     U< IF
21981         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
21982     THEN
21983 ELSE
21984     BIT.B #SW1,&SW1_IN          \ test switch S1 input
21985     0= IF                       \ case of Switch S1 pressed
21986         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
21987         U>= IF                  \
21988            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
21989         THEN                    \
21990     THEN                        \
21991 THEN                            \
21992 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
21993 RET                             \ 5
21994 ENDASM
21995
21996 \ ******************************\
21997 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
21998 \ ******************************\
21999 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
22000 \ ******************************\
22001 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
22002 \                               \       SMclock = 8|16|24 MHz
22003 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
22004 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
22005 \                               \       SR(9)=new Toggle bit memory (ADD on)
22006 \ ******************************\
22007 \ RC5_FirstStartBitHalfCycle:   \
22008 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
22009 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
22010 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
22011 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
22012 \ [THEN]
22013 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
22014     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
22015 [THEN]
22016 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
22017     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
22018 [THEN]
22019 MOV #1778,X                     \ RC5_Period * 1us
22020 MOV #14,W                       \ count of loop
22021 BEGIN                           \
22022 \ ******************************\
22023 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
22024 \ ******************************\                   |
22025 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
22026 \ RC5_Compute_3/4_Period:       \                   |
22027     RRUM    #1,X                \ X=1/2 cycle       |
22028     MOV     X,Y                 \                   ^
22029     RRUM    #1,Y                \ Y=1/4
22030     ADD     X,Y                 \ Y=3/4 cycle
22031     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
22032     U>= UNTIL                   \ 2
22033 \ ******************************\
22034 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
22035 \ ******************************\
22036     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
22037     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
22038     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
22039     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
22040     SUB     #1,W                \ decrement count loop
22041 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
22042 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
22043 0<> WHILE                       \ ----> out of loop ----+
22044     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
22045     BEGIN                       \                       |
22046         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
22047         CMP Y,X                 \ 1                     |   cycle time out of bound ?
22048         U>= IF                  \ 2                 ^   |   yes:
22049         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
22050         GOTO BW1                \                   |   |      quit on truncated RC5 message
22051         THEN                    \                   |   |
22052         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
22053     0<> UNTIL                   \ 2                 |   |
22054 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
22055 \ ******************************\                       |
22056 \ RC5_SampleEndOf:              \ <---------------------+
22057 \ ******************************\
22058 BIC #$30,&RC5_TIM_CTL           \   stop timer
22059 \ ******************************\
22060 \ RC5_ComputeNewRC5word         \
22061 \ ******************************\
22062 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
22063 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
22064 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
22065 \ ******************************\
22066 \ RC5_ComputeC6bit              \
22067 \ ******************************\
22068 BIT     #BIT14,T                \ test /C6 bit in T
22069 0= IF   BIS #BIT6,X             \ set C6 bit in X
22070 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
22071 \ ******************************\
22072 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
22073 \ ******************************\
22074 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
22075 \ ******************************\
22076 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
22077 XOR     @RSP,T                  \ (new XOR old) Toggle bits
22078 BIT     #UF10,T                 \ repeated RC5_command ?
22079 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
22080 XOR #UF10,0(RSP)                \ 5 toggle bit memory
22081 \ ******************************\
22082 \ Display IR_RC5 code           \
22083 \ ******************************\
22084 SUB #8,PSP                      \ TOS -- x x x x TOS
22085 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
22086 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
22087 MOV #$10,&BASEADR               \                                               set hexadecimal base
22088 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
22089 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
22090 LO2HI                           \                                               switch from assembler to FORTH
22091     LCD_CLEAR                   \                                               set LCD cursor at home
22092     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
22093     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
22094     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
22095     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
22096 HI2LO                           \     --                                        switch from FORTH to assembler
22097 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
22098 MOV @PSP+,TOS                   \     -- TOS
22099 RET
22100 ENDASM
22101
22102 \ ******************************\
22103 ASM BACKGROUND                  \
22104 \ ******************************\
22105 BEGIN
22106 \     ...                         \ insert here your background task
22107 \     ...                         \
22108 \     ...                         \
22109     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
22110     BIS &LPM_MODE,SR            \
22111 \ ******************************\
22112 \ here start all interrupts     \
22113 \ ******************************\
22114 \ here return all interrupts    \
22115 \ ******************************\
22116 AGAIN                           \
22117 ENDASM                          \
22118 \ ******************************\
22119
22120 \ ------------------------------\
22121 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
22122 \ ------------------------------\
22123 \     ...                         \ init specific I/O sys as you want
22124 \     ...                         \ before executing default WARM
22125     MOV #WARM,X                 \ ['] WARM 
22126     ADD #4,X                    \ >BODY
22127     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
22128 ENDASM
22129 \ ------------------------------\
22130
22131 \ ------------------------------\
22132 CODE STOP                       \ stops multitasking, must to be used before downloading app
22133 \ ------------------------------\
22134 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
22135     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
22136     MOV X,-2(X)                 \ restore the default background: SLEEP
22137     MOV #WARM,X
22138     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
22139     BIC.B #RC5,&IR_IE           \ clear RC5_Int
22140     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
22141     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
22142     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
22143     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
22144     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
22145 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
22146 ECHO                            \
22147 ." RC5toLCD is removed,"
22148 ."  type START to restart"
22149  WARM                           \ performs reset to reset all interrupt vectors.    
22150 ;
22151 \ ------------------------------\
22152
22153 \ ------------------------------\
22154 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
22155 \ ------------------------------\
22156 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
22157 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
22158 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
22159 \                           --       \ID input divider \ 10 = /4
22160 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
22161 \                                 -  \TBCLR TimerB Clear
22162 \                                  - \TBIE
22163 \                                   -\TBIFG
22164 \ -------------------------------\
22165 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
22166 \                  --                 \CM Capture Mode
22167 \                    --               \CCIS
22168 \                       -             \SCS
22169 \                        --           \CLLD
22170 \                          -          \CAP
22171 \                            ---      \OUTMOD \ 011 = set/reset
22172 \                               -     \CCIE
22173 \                                 -   \CCI
22174 \                                  -  \OUT
22175 \                                   - \COV
22176 \                                    -\CCIFG
22177 \ -------------------------------\
22178 \ LCD_TIM_CCRx                   \
22179 \ -------------------------------\
22180 \ LCD_TIM_EX0                    \ 
22181 \ ------------------------------\
22182 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
22183 \ ------------------------------\
22184 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
22185 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
22186 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
22187     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
22188 [THEN]
22189 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
22190     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
22191 [THEN]
22192     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
22193 \ ------------------------------\
22194 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
22195 \ ------------------------------\
22196 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
22197     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
22198 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
22199 \ ------------------------------\
22200     BIS.B #LCDVo,&LCDVo_DIR     \
22201     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
22202 \ ------------------------------\
22203     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
22204     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
22205 \ ------------------------------\
22206     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
22207     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
22208 \ ******************************\
22209 \ init RC5_Int                  \
22210 \ ******************************\
22211     BIS.B #RC5,&IR_IE           \ enable RC5_Int
22212     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
22213     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
22214 \ ******************************\
22215 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
22216 \ ******************************\
22217 \              %01 0001 0100    \ TAxCTL
22218 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
22219 \                  --           \ ID        divided by 1
22220 \                    --         \ MC        MODE = up to TAxCCRn
22221 \                        -      \ TACLR     clear timer count
22222 \                         -     \ TAIE
22223 \                          -    \ TAIFG
22224 \ ------------------------------\
22225 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
22226 \ ------------------------------\
22227 \                        000    \ TAxEX0
22228 \                        ---    \ TAIDEX    pre divisor
22229 \ ------------------------------\
22230 \          %0000 0000 0000 0101 \ TAxCCR0
22231     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
22232 \ ------------------------------\
22233 \          %0000 0000 0001 0000 \ TAxCCTL0
22234 \                   -           \ CAP capture/compare mode = compare
22235 \                        -      \ CCIEn
22236 \                             - \ CCIFGn
22237     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
22238 \ ------------------------------\
22239     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
22240 \ ------------------------------\
22241 \ define LPM mode for ACCEPT    \
22242 \ ------------------------------\
22243 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
22244 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
22245 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
22246 \ ------------------------------\
22247 \ activate I/O                  \
22248 \ ------------------------------\
22249 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
22250 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
22251 \ ------------------------------\
22252 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
22253 \ ------------------------------\
22254 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
22255 \ CMP #2,Y                        \ Power_ON event
22256 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
22257 CMP #4,Y                        \
22258 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
22259 \ CMP #6,Y                        \
22260 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
22261 \ CMP #$0A,Y                      \
22262 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
22263 \ CMP #$16,Y                      \
22264 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
22265 \ ------------------------------\
22266 COLON                           \
22267 \ ------------------------------\
22268 \ Init LCD 2x20                 \
22269 \ ------------------------------\
22270     #1000 20_US                 \ 1- wait 20 ms
22271     %011 TOP_LCD                \ 2- send DB5=DB4=1
22272     #205 20_US                  \ 3- wait 4,1 ms
22273     %011 TOP_LCD                \ 4- send again DB5=DB4=1
22274     #5 20_US                    \ 5- wait 0,1 ms
22275     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
22276     #2 20_US                    \    wait 40 us = LCD cycle
22277     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
22278     #2 20_US                    \    wait 40 us = LCD cycle
22279     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
22280     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
22281     LCD_CLEAR                   \ 10- "LCD_Clear"
22282     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
22283     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
22284     LCD_CLEAR                   \ 10- "LCD_Clear"
22285     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
22286     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
22287     CR ." I love you"           \ display message on LCD
22288     ['] CR >BODY IS CR          \ CR executes its default value
22289     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
22290     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
22291     PWR_STATE ABORT             \ init DP and continues with ABORT
22292 ;                               \
22293 \ ------------------------------\
22294
22295 \ ------------------------------\
22296 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
22297 \ ------------------------------\
22298 MOV #SLEEP,X                    \ replace default background process SLEEP
22299 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
22300 MOV #WARM,X                     \ replace default WARM
22301 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
22302 MOV X,PC                        \ then execute new WARM
22303 ENDCODE 
22304 \ ------------------------------\
22305
22306 ECHO
22307             ; downloading RC5toLCD.4th is done
22308 RST_HERE    ; this app is protected against <reset>
22309
22310
22311 RST_STATE
22312
22313 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
22314
22315 [UNDEFINED] MARKER [IF]
22316 \  https://forth-standard.org/standard/core/MARKER
22317 \  MARKER
22318 \ ( "<spaces>name" -- )
22319 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
22320 \ with the execution semantics defined below.
22321
22322 \ name Execution: ( -- )
22323 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
22324 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
22325 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
22326 \ not necessarily provided. No other contextual information such as numeric base is affected
22327 \
22328 : MARKER
22329 CREATE
22330 HI2LO
22331 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
22332 SUB #2,Y            \ 1 Y = LFA
22333 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
22334 ADD #4,&DP          \ 3 add 2 cells
22335 LO2HI
22336 DOES>
22337 HI2LO
22338 MOV @RSP+,IP        \ -- PFA
22339 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
22340 MOV @TOS,&INIDP     \       set DP value for RST_STATE
22341 MOV @PSP+,TOS       \ --
22342 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
22343 ENDCODE
22344 [THEN]
22345
22346 MARKER {RC5TOLCD}
22347
22348 [UNDEFINED] @ [IF]
22349 \ https://forth-standard.org/standard/core/Fetch
22350 \ @     c-addr -- char   fetch char from memory
22351 CODE @
22352 MOV @TOS,TOS
22353 MOV @IP+,PC
22354 ENDCODE
22355 [THEN]
22356
22357 [UNDEFINED] CONSTANT [IF]
22358 \ https://forth-standard.org/standard/core/CONSTANT
22359 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
22360 : CONSTANT 
22361 CREATE
22362 HI2LO
22363 MOV TOS,-2(W)           \   PFA = n
22364 MOV @PSP+,TOS
22365 MOV @RSP+,IP
22366 MOV @IP+,PC
22367 ENDCODE
22368 [THEN]
22369
22370 [UNDEFINED] STATE [IF]
22371 \ https://forth-standard.org/standard/core/STATE
22372 \ STATE   -- a-addr       holds compiler state
22373 STATEADR CONSTANT STATE
22374 [THEN]
22375
22376 [UNDEFINED] = [IF]
22377 \ https://forth-standard.org/standard/core/Equal
22378 \ =      x1 x2 -- flag         test x1=x2
22379 CODE =
22380 SUB @PSP+,TOS   \ 2
22381 0<> IF          \ 2
22382     AND #0,TOS  \ 1
22383     MOV @IP+,PC \ 4
22384 THEN
22385 XOR #-1,TOS     \ 1 flag Z = 1
22386 MOV @IP+,PC     \ 4
22387 ENDCODE
22388 [THEN]
22389
22390 [UNDEFINED] IF [IF]
22391 \ https://forth-standard.org/standard/core/IF
22392 \ IF       -- IFadr    initialize conditional forward branch
22393 CODE IF       \ immediate
22394 SUB #2,PSP              \
22395 MOV TOS,0(PSP)          \
22396 MOV &DP,TOS             \ -- HERE
22397 ADD #4,&DP            \           compile one word, reserve one word
22398 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
22399 ADD #2,TOS              \ -- HERE+2=IFadr
22400 MOV @IP+,PC
22401 ENDCODE IMMEDIATE
22402 [THEN]
22403
22404 [UNDEFINED] THEN [IF]
22405 \ https://forth-standard.org/standard/core/THEN
22406 \ THEN     IFadr --                resolve forward branch
22407 CODE THEN               \ immediate
22408 MOV &DP,0(TOS)          \ -- IFadr
22409 MOV @PSP+,TOS           \ --
22410 MOV @IP+,PC
22411 ENDCODE IMMEDIATE
22412 [THEN]
22413
22414 [UNDEFINED] ELSE [IF]
22415 \ https://forth-standard.org/standard/core/ELSE
22416 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
22417 CODE ELSE     \ immediate
22418 ADD #4,&DP              \ make room to compile two words
22419 MOV &DP,W               \ W=HERE+4
22420 MOV #BRAN,-4(W)
22421 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
22422 SUB #2,W                \ HERE+2
22423 MOV W,TOS               \ -- ELSEadr
22424 MOV @IP+,PC
22425 ENDCODE IMMEDIATE
22426 [THEN]
22427
22428 [UNDEFINED] DEFER [IF]
22429 \ https://forth-standard.org/standard/core/DEFER
22430 \ DEFER "<spaces>name"   --
22431 \ Skip leading space delimiters. Parse name delimited by a space.
22432 \ Create a definition for name with the execution semantics defined below.
22433
22434 \ name Execution:   --
22435 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
22436 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
22437 : DEFER
22438 CREATE
22439 HI2LO
22440 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
22441 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
22442 MOV @RSP+,IP
22443 MOV @IP+,PC
22444 ENDCODE
22445 [THEN]
22446
22447 [UNDEFINED] DEFER! [IF]
22448 \ https://forth-standard.org/standard/core/DEFERStore
22449 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
22450 CODE DEFER!             \ xt2 xt1 --
22451 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
22452 MOV @PSP+,TOS           \ --
22453 MOV @IP+,PC
22454 ENDCODE
22455 [THEN]
22456
22457 [UNDEFINED] IS [IF]
22458 \ https://forth-standard.org/standard/core/IS
22459 \ IS <name>        xt --
22460 \ used as is :
22461 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
22462 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
22463 \ or in a definition : ... ['] U. IS DISPLAY ...
22464 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
22465 \
22466 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
22467 : IS
22468 STATE @
22469 IF  POSTPONE ['] POSTPONE DEFER! 
22470 ELSE ' DEFER! 
22471 THEN
22472 ; IMMEDIATE
22473 [THEN]
22474
22475 [UNDEFINED] >BODY [IF]
22476 \ https://forth-standard.org/standard/core/toBODY
22477 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
22478 CODE >BODY
22479 ADD #4,TOS
22480 MOV @IP+,PC
22481 ENDCODE
22482 [THEN]
22483
22484 \ CODE 20uS           \ n --      8MHz version
22485 \ BEGIN               \ 4 + 16 ~ loop
22486 \     MOV #39,rDOCON   \ 39
22487 \     BEGIN           \ 4 ~ loop
22488 \         NOP
22489 \         SUB #1,rDOCON
22490 \     0=  UNTIL
22491 \     SUB #1,TOS      \ 1
22492 \ 0= UNTIL
22493 \ MOV #XDOCON,rDOCON  \ 2
22494 \ MOV @PSP+,TOS
22495 \ MOV @RSP+,IP        \
22496 \ ENDCODE
22497
22498 CODE 20_US                      \ n --      n * 20 us
22499 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
22500     BEGIN
22501         BIT #1,&LCD_TIM_CTL     \ 3
22502     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
22503     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
22504     SUB #1,TOS                  \ 1
22505 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
22506 MOV @PSP+,TOS                   \ 2
22507 MOV @IP+,PC                     \ 4
22508 ENDCODE
22509
22510 CODE TOP_LCD                    \ LCD Sample
22511 \                               \ if write : %xxxx_WWWW --
22512 \                               \ if read  : -- %0000_RRRR
22513     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
22514     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
22515 0= IF                           \ write LCD bits pattern
22516     AND.B #LCD_DB,TOS           \ 
22517     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
22518     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
22519     MOV @PSP+,TOS               \
22520     MOV @IP+,PC
22521 THEN                            \ read LCD bits pattern
22522     SUB #2,PSP
22523     MOV TOS,0(PSP)
22524     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
22525     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
22526     AND.B #LCD_DB,TOS           \
22527     MOV @IP+,PC
22528 ENDCODE
22529
22530 CODE LCD_WRC                    \ char --         Write Char
22531     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
22532 BW1 SUB #2,PSP                  \
22533     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
22534     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
22535     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
22536     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
22537 COLON                           \ high level word starts here 
22538     TOP_LCD 2 20_US             \ write high nibble first
22539     TOP_LCD 2 20_US 
22540 ;
22541
22542 CODE LCD_WRF                    \ func --         Write Fonction
22543     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
22544     GOTO BW1
22545 ENDCODE
22546
22547 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
22548 : LCD_HOME $02 LCD_WRF 100 20_us ;
22549
22550 \ [UNDEFINED] OR [IF]
22551
22552 \ \ https://forth-standard.org/standard/core/OR
22553 \ \ C OR     x1 x2 -- x3           logical OR
22554 \ CODE OR
22555 \ BIS @PSP+,TOS
22556 \ MOV @IP+,PC
22557 \ ENDCODE
22558
22559 \ [THEN]
22560
22561 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
22562 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
22563 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
22564 \ : LCD_FN_SET        $20 OR LCD_WrF ;
22565 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
22566 \ : LCD_GOTO          $80 OR LCD_WrF ;
22567
22568
22569 \ CODE LCD_RDS                    \ -- status       Read Status
22570 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
22571 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
22572 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
22573 \ COLON                           \ starts a FORTH word
22574 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
22575 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
22576 \ HI2LO                           \ switch from FORTH to assembler
22577 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
22578 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
22579 \     MOV @RSP+,IP                \ restore IP saved by COLON
22580 \     MOV @IP+,PC                 \
22581 \ ENDCODE
22582
22583 \ CODE LCD_RDC                    \ -- char         Read Char
22584 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
22585 \     GOTO BW1
22586 \ ENDCODE
22587
22588
22589 \ ******************************\
22590 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
22591 \ ******************************\
22592 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
22593 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
22594 BIT.B #SW2,&SW2_IN              \ test switch S2
22595 0= IF                           \ case of switch S2 pressed
22596     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
22597     U< IF
22598         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
22599     THEN
22600 ELSE
22601     BIT.B #SW1,&SW1_IN          \ test switch S1 input
22602     0= IF                       \ case of Switch S1 pressed
22603         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
22604         U>= IF                  \
22605            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
22606         THEN                    \
22607     THEN                        \
22608 THEN                            \
22609 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
22610 RET                             \ 5
22611 ENDASM
22612
22613 \ ******************************\
22614 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
22615 \ ******************************\
22616 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
22617 \ ******************************\
22618 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
22619 \                               \       SMclock = 8|16|24 MHz
22620 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
22621 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
22622 \                               \       SR(9)=new Toggle bit memory (ADD on)
22623 \ ******************************\
22624 \ RC5_FirstStartBitHalfCycle:   \
22625 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
22626 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
22627 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
22628 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
22629 \ [THEN]
22630 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
22631     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
22632 [THEN]
22633 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
22634     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
22635 [THEN]
22636 MOV #1778,X                     \ RC5_Period * 1us
22637 MOV #14,W                       \ count of loop
22638 BEGIN                           \
22639 \ ******************************\
22640 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
22641 \ ******************************\                   |
22642 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
22643 \ RC5_Compute_3/4_Period:       \                   |
22644     RRUM    #1,X                \ X=1/2 cycle       |
22645     MOV     X,Y                 \                   ^
22646     RRUM    #1,Y                \ Y=1/4
22647     ADD     X,Y                 \ Y=3/4 cycle
22648     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
22649     U>= UNTIL                   \ 2
22650 \ ******************************\
22651 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
22652 \ ******************************\
22653     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
22654     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
22655     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
22656     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
22657     SUB     #1,W                \ decrement count loop
22658 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
22659 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
22660 0<> WHILE                       \ ----> out of loop ----+
22661     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
22662     BEGIN                       \                       |
22663         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
22664         CMP Y,X                 \ 1                     |   cycle time out of bound ?
22665         U>= IF                  \ 2                 ^   |   yes:
22666         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
22667         GOTO BW1                \                   |   |      quit on truncated RC5 message
22668         THEN                    \                   |   |
22669         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
22670     0<> UNTIL                   \ 2                 |   |
22671 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
22672 \ ******************************\                       |
22673 \ RC5_SampleEndOf:              \ <---------------------+
22674 \ ******************************\
22675 BIC #$30,&RC5_TIM_CTL           \   stop timer
22676 \ ******************************\
22677 \ RC5_ComputeNewRC5word         \
22678 \ ******************************\
22679 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
22680 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
22681 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
22682 \ ******************************\
22683 \ RC5_ComputeC6bit              \
22684 \ ******************************\
22685 BIT     #BIT14,T                \ test /C6 bit in T
22686 0= IF   BIS #BIT6,X             \ set C6 bit in X
22687 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
22688 \ ******************************\
22689 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
22690 \ ******************************\
22691 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
22692 \ ******************************\
22693 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
22694 XOR     @RSP,T                  \ (new XOR old) Toggle bits
22695 BIT     #UF10,T                 \ repeated RC5_command ?
22696 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
22697 XOR #UF10,0(RSP)                \ 5 toggle bit memory
22698 \ ******************************\
22699 \ Display IR_RC5 code           \
22700 \ ******************************\
22701 SUB #8,PSP                      \ TOS -- x x x x TOS
22702 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
22703 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
22704 MOV #$10,&BASEADR               \                                               set hexadecimal base
22705 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
22706 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
22707 LO2HI                           \                                               switch from assembler to FORTH
22708     LCD_CLEAR                   \                                               set LCD cursor at home
22709     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
22710     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
22711     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
22712     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
22713 HI2LO                           \     --                                        switch from FORTH to assembler
22714 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
22715 MOV @PSP+,TOS                   \     -- TOS
22716 RET
22717 ENDASM
22718
22719 \ ******************************\
22720 ASM BACKGROUND                  \
22721 \ ******************************\
22722 BEGIN
22723 \     ...                         \ insert here your background task
22724 \     ...                         \
22725 \     ...                         \
22726     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
22727     BIS &LPM_MODE,SR            \
22728 \ ******************************\
22729 \ here start all interrupts     \
22730 \ ******************************\
22731 \ here return all interrupts    \
22732 \ ******************************\
22733 AGAIN                           \
22734 ENDASM                          \
22735 \ ******************************\
22736
22737 \ ------------------------------\
22738 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
22739 \ ------------------------------\
22740 \     ...                         \ init specific I/O sys as you want
22741 \     ...                         \ before executing default WARM
22742     MOV #WARM,X                 \ ['] WARM 
22743     ADD #4,X                    \ >BODY
22744     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
22745 ENDASM
22746 \ ------------------------------\
22747
22748 \ ------------------------------\
22749 CODE STOP                       \ stops multitasking, must to be used before downloading app
22750 \ ------------------------------\
22751 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
22752     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
22753     MOV X,-2(X)                 \ restore the default background: SLEEP
22754     MOV #WARM,X
22755     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
22756     BIC.B #RC5,&IR_IE           \ clear RC5_Int
22757     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
22758     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
22759     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
22760     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
22761     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
22762 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
22763 ECHO                            \
22764 ." RC5toLCD is removed,"
22765 ."  type START to restart"
22766  WARM                           \ performs reset to reset all interrupt vectors.    
22767 ;
22768 \ ------------------------------\
22769
22770 \ ------------------------------\
22771 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
22772 \ ------------------------------\
22773 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
22774 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
22775 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
22776 \                           --       \ID input divider \ 10 = /4
22777 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
22778 \                                 -  \TBCLR TimerB Clear
22779 \                                  - \TBIE
22780 \                                   -\TBIFG
22781 \ -------------------------------\
22782 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
22783 \                  --                 \CM Capture Mode
22784 \                    --               \CCIS
22785 \                       -             \SCS
22786 \                        --           \CLLD
22787 \                          -          \CAP
22788 \                            ---      \OUTMOD \ 011 = set/reset
22789 \                               -     \CCIE
22790 \                                 -   \CCI
22791 \                                  -  \OUT
22792 \                                   - \COV
22793 \                                    -\CCIFG
22794 \ -------------------------------\
22795 \ LCD_TIM_CCRx                   \
22796 \ -------------------------------\
22797 \ LCD_TIM_EX0                    \ 
22798 \ ------------------------------\
22799 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
22800 \ ------------------------------\
22801 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
22802 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
22803 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
22804     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
22805 [THEN]
22806 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
22807     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
22808 [THEN]
22809     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
22810 \ ------------------------------\
22811 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
22812 \ ------------------------------\
22813 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
22814     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
22815 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
22816 \ ------------------------------\
22817     BIS.B #LCDVo,&LCDVo_DIR     \
22818     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
22819 \ ------------------------------\
22820     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
22821     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
22822 \ ------------------------------\
22823     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
22824     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
22825 \ ******************************\
22826 \ init RC5_Int                  \
22827 \ ******************************\
22828     BIS.B #RC5,&IR_IE           \ enable RC5_Int
22829     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
22830     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
22831 \ ******************************\
22832 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
22833 \ ******************************\
22834 \              %01 0001 0100    \ TAxCTL
22835 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
22836 \                  --           \ ID        divided by 1
22837 \                    --         \ MC        MODE = up to TAxCCRn
22838 \                        -      \ TACLR     clear timer count
22839 \                         -     \ TAIE
22840 \                          -    \ TAIFG
22841 \ ------------------------------\
22842 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
22843 \ ------------------------------\
22844 \                        000    \ TAxEX0
22845 \                        ---    \ TAIDEX    pre divisor
22846 \ ------------------------------\
22847 \          %0000 0000 0000 0101 \ TAxCCR0
22848     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
22849 \ ------------------------------\
22850 \          %0000 0000 0001 0000 \ TAxCCTL0
22851 \                   -           \ CAP capture/compare mode = compare
22852 \                        -      \ CCIEn
22853 \                             - \ CCIFGn
22854     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
22855 \ ------------------------------\
22856     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
22857 \ ------------------------------\
22858 \ define LPM mode for ACCEPT    \
22859 \ ------------------------------\
22860 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
22861 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
22862 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
22863 \ ------------------------------\
22864 \ activate I/O                  \
22865 \ ------------------------------\
22866 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
22867 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
22868 \ ------------------------------\
22869 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
22870 \ ------------------------------\
22871 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
22872 \ CMP #2,Y                        \ Power_ON event
22873 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
22874 CMP #4,Y                        \
22875 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
22876 \ CMP #6,Y                        \
22877 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
22878 \ CMP #$0A,Y                      \
22879 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
22880 \ CMP #$16,Y                      \
22881 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
22882 \ ------------------------------\
22883 COLON                           \
22884 \ ------------------------------\
22885 \ Init LCD 2x20                 \
22886 \ ------------------------------\
22887     #1000 20_US                 \ 1- wait 20 ms
22888     %011 TOP_LCD                \ 2- send DB5=DB4=1
22889     #205 20_US                  \ 3- wait 4,1 ms
22890     %011 TOP_LCD                \ 4- send again DB5=DB4=1
22891     #5 20_US                    \ 5- wait 0,1 ms
22892     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
22893     #2 20_US                    \    wait 40 us = LCD cycle
22894     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
22895     #2 20_US                    \    wait 40 us = LCD cycle
22896     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
22897     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
22898     LCD_CLEAR                   \ 10- "LCD_Clear"
22899     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
22900     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
22901     LCD_CLEAR                   \ 10- "LCD_Clear"
22902     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
22903     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
22904     CR ." I love you"           \ display message on LCD
22905     ['] CR >BODY IS CR          \ CR executes its default value
22906     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
22907     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
22908     PWR_STATE ABORT             \ init DP and continues with ABORT
22909 ;                               \
22910 \ ------------------------------\
22911
22912 \ ------------------------------\
22913 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
22914 \ ------------------------------\
22915 MOV #SLEEP,X                    \ replace default background process SLEEP
22916 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
22917 MOV #WARM,X                     \ replace default WARM
22918 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
22919 MOV X,PC                        \ then execute new WARM
22920 ENDCODE 
22921 \ ------------------------------\
22922
22923 ECHO
22924             ; downloading RC5toLCD.4th is done
22925 RST_HERE    ; this app is protected against <reset>
22926
22927
22928 RST_STATE
22929
22930 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
22931
22932 [UNDEFINED] MARKER [IF]
22933 \  https://forth-standard.org/standard/core/MARKER
22934 \  MARKER
22935 \ ( "<spaces>name" -- )
22936 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
22937 \ with the execution semantics defined below.
22938
22939 \ name Execution: ( -- )
22940 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
22941 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
22942 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
22943 \ not necessarily provided. No other contextual information such as numeric base is affected
22944 \
22945 : MARKER
22946 CREATE
22947 HI2LO
22948 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
22949 SUB #2,Y            \ 1 Y = LFA
22950 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
22951 ADD #4,&DP          \ 3 add 2 cells
22952 LO2HI
22953 DOES>
22954 HI2LO
22955 MOV @RSP+,IP        \ -- PFA
22956 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
22957 MOV @TOS,&INIDP     \       set DP value for RST_STATE
22958 MOV @PSP+,TOS       \ --
22959 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
22960 ENDCODE
22961 [THEN]
22962
22963 MARKER {RC5TOLCD}
22964
22965 [UNDEFINED] @ [IF]
22966 \ https://forth-standard.org/standard/core/Fetch
22967 \ @     c-addr -- char   fetch char from memory
22968 CODE @
22969 MOV @TOS,TOS
22970 MOV @IP+,PC
22971 ENDCODE
22972 [THEN]
22973
22974 [UNDEFINED] CONSTANT [IF]
22975 \ https://forth-standard.org/standard/core/CONSTANT
22976 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
22977 : CONSTANT 
22978 CREATE
22979 HI2LO
22980 MOV TOS,-2(W)           \   PFA = n
22981 MOV @PSP+,TOS
22982 MOV @RSP+,IP
22983 MOV @IP+,PC
22984 ENDCODE
22985 [THEN]
22986
22987 [UNDEFINED] STATE [IF]
22988 \ https://forth-standard.org/standard/core/STATE
22989 \ STATE   -- a-addr       holds compiler state
22990 STATEADR CONSTANT STATE
22991 [THEN]
22992
22993 [UNDEFINED] = [IF]
22994 \ https://forth-standard.org/standard/core/Equal
22995 \ =      x1 x2 -- flag         test x1=x2
22996 CODE =
22997 SUB @PSP+,TOS   \ 2
22998 0<> IF          \ 2
22999     AND #0,TOS  \ 1
23000     MOV @IP+,PC \ 4
23001 THEN
23002 XOR #-1,TOS     \ 1 flag Z = 1
23003 MOV @IP+,PC     \ 4
23004 ENDCODE
23005 [THEN]
23006
23007 [UNDEFINED] IF [IF]
23008 \ https://forth-standard.org/standard/core/IF
23009 \ IF       -- IFadr    initialize conditional forward branch
23010 CODE IF       \ immediate
23011 SUB #2,PSP              \
23012 MOV TOS,0(PSP)          \
23013 MOV &DP,TOS             \ -- HERE
23014 ADD #4,&DP            \           compile one word, reserve one word
23015 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
23016 ADD #2,TOS              \ -- HERE+2=IFadr
23017 MOV @IP+,PC
23018 ENDCODE IMMEDIATE
23019 [THEN]
23020
23021 [UNDEFINED] THEN [IF]
23022 \ https://forth-standard.org/standard/core/THEN
23023 \ THEN     IFadr --                resolve forward branch
23024 CODE THEN               \ immediate
23025 MOV &DP,0(TOS)          \ -- IFadr
23026 MOV @PSP+,TOS           \ --
23027 MOV @IP+,PC
23028 ENDCODE IMMEDIATE
23029 [THEN]
23030
23031 [UNDEFINED] ELSE [IF]
23032 \ https://forth-standard.org/standard/core/ELSE
23033 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
23034 CODE ELSE     \ immediate
23035 ADD #4,&DP              \ make room to compile two words
23036 MOV &DP,W               \ W=HERE+4
23037 MOV #BRAN,-4(W)
23038 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
23039 SUB #2,W                \ HERE+2
23040 MOV W,TOS               \ -- ELSEadr
23041 MOV @IP+,PC
23042 ENDCODE IMMEDIATE
23043 [THEN]
23044
23045 [UNDEFINED] DEFER [IF]
23046 \ https://forth-standard.org/standard/core/DEFER
23047 \ DEFER "<spaces>name"   --
23048 \ Skip leading space delimiters. Parse name delimited by a space.
23049 \ Create a definition for name with the execution semantics defined below.
23050
23051 \ name Execution:   --
23052 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
23053 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
23054 : DEFER
23055 CREATE
23056 HI2LO
23057 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
23058 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
23059 MOV @RSP+,IP
23060 MOV @IP+,PC
23061 ENDCODE
23062 [THEN]
23063
23064 [UNDEFINED] DEFER! [IF]
23065 \ https://forth-standard.org/standard/core/DEFERStore
23066 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
23067 CODE DEFER!             \ xt2 xt1 --
23068 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
23069 MOV @PSP+,TOS           \ --
23070 MOV @IP+,PC
23071 ENDCODE
23072 [THEN]
23073
23074 [UNDEFINED] IS [IF]
23075 \ https://forth-standard.org/standard/core/IS
23076 \ IS <name>        xt --
23077 \ used as is :
23078 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
23079 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
23080 \ or in a definition : ... ['] U. IS DISPLAY ...
23081 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
23082 \
23083 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
23084 : IS
23085 STATE @
23086 IF  POSTPONE ['] POSTPONE DEFER! 
23087 ELSE ' DEFER! 
23088 THEN
23089 ; IMMEDIATE
23090 [THEN]
23091
23092 [UNDEFINED] >BODY [IF]
23093 \ https://forth-standard.org/standard/core/toBODY
23094 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
23095 CODE >BODY
23096 ADD #4,TOS
23097 MOV @IP+,PC
23098 ENDCODE
23099 [THEN]
23100
23101 \ CODE 20uS           \ n --      8MHz version
23102 \ BEGIN               \ 4 + 16 ~ loop
23103 \     MOV #39,rDOCON   \ 39
23104 \     BEGIN           \ 4 ~ loop
23105 \         NOP
23106 \         SUB #1,rDOCON
23107 \     0=  UNTIL
23108 \     SUB #1,TOS      \ 1
23109 \ 0= UNTIL
23110 \ MOV #XDOCON,rDOCON  \ 2
23111 \ MOV @PSP+,TOS
23112 \ MOV @RSP+,IP        \
23113 \ ENDCODE
23114
23115 CODE 20_US                      \ n --      n * 20 us
23116 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
23117     BEGIN
23118         BIT #1,&LCD_TIM_CTL     \ 3
23119     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
23120     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
23121     SUB #1,TOS                  \ 1
23122 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
23123 MOV @PSP+,TOS                   \ 2
23124 MOV @IP+,PC                     \ 4
23125 ENDCODE
23126
23127 CODE TOP_LCD                    \ LCD Sample
23128 \                               \ if write : %xxxx_WWWW --
23129 \                               \ if read  : -- %0000_RRRR
23130     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
23131     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
23132 0= IF                           \ write LCD bits pattern
23133     AND.B #LCD_DB,TOS           \ 
23134     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
23135     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
23136     MOV @PSP+,TOS               \
23137     MOV @IP+,PC
23138 THEN                            \ read LCD bits pattern
23139     SUB #2,PSP
23140     MOV TOS,0(PSP)
23141     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
23142     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
23143     AND.B #LCD_DB,TOS           \
23144     MOV @IP+,PC
23145 ENDCODE
23146
23147 CODE LCD_WRC                    \ char --         Write Char
23148     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
23149 BW1 SUB #2,PSP                  \
23150     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
23151     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
23152     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
23153     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
23154 COLON                           \ high level word starts here 
23155     TOP_LCD 2 20_US             \ write high nibble first
23156     TOP_LCD 2 20_US 
23157 ;
23158
23159 CODE LCD_WRF                    \ func --         Write Fonction
23160     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
23161     GOTO BW1
23162 ENDCODE
23163
23164 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
23165 : LCD_HOME $02 LCD_WRF 100 20_us ;
23166
23167 \ [UNDEFINED] OR [IF]
23168
23169 \ \ https://forth-standard.org/standard/core/OR
23170 \ \ C OR     x1 x2 -- x3           logical OR
23171 \ CODE OR
23172 \ BIS @PSP+,TOS
23173 \ MOV @IP+,PC
23174 \ ENDCODE
23175
23176 \ [THEN]
23177
23178 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
23179 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
23180 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
23181 \ : LCD_FN_SET        $20 OR LCD_WrF ;
23182 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
23183 \ : LCD_GOTO          $80 OR LCD_WrF ;
23184
23185
23186 \ CODE LCD_RDS                    \ -- status       Read Status
23187 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
23188 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
23189 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
23190 \ COLON                           \ starts a FORTH word
23191 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
23192 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
23193 \ HI2LO                           \ switch from FORTH to assembler
23194 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
23195 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
23196 \     MOV @RSP+,IP                \ restore IP saved by COLON
23197 \     MOV @IP+,PC                 \
23198 \ ENDCODE
23199
23200 \ CODE LCD_RDC                    \ -- char         Read Char
23201 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
23202 \     GOTO BW1
23203 \ ENDCODE
23204
23205
23206 \ ******************************\
23207 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
23208 \ ******************************\
23209 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
23210 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
23211 BIT.B #SW2,&SW2_IN              \ test switch S2
23212 0= IF                           \ case of switch S2 pressed
23213     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
23214     U< IF
23215         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
23216     THEN
23217 ELSE
23218     BIT.B #SW1,&SW1_IN          \ test switch S1 input
23219     0= IF                       \ case of Switch S1 pressed
23220         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
23221         U>= IF                  \
23222            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
23223         THEN                    \
23224     THEN                        \
23225 THEN                            \
23226 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
23227 RET                             \ 5
23228 ENDASM
23229
23230 \ ******************************\
23231 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
23232 \ ******************************\
23233 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
23234 \ ******************************\
23235 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
23236 \                               \       SMclock = 8|16|24 MHz
23237 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
23238 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
23239 \                               \       SR(9)=new Toggle bit memory (ADD on)
23240 \ ******************************\
23241 \ RC5_FirstStartBitHalfCycle:   \
23242 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
23243 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
23244 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
23245 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
23246 \ [THEN]
23247 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
23248     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
23249 [THEN]
23250 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
23251     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
23252 [THEN]
23253 MOV #1778,X                     \ RC5_Period * 1us
23254 MOV #14,W                       \ count of loop
23255 BEGIN                           \
23256 \ ******************************\
23257 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
23258 \ ******************************\                   |
23259 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
23260 \ RC5_Compute_3/4_Period:       \                   |
23261     RRUM    #1,X                \ X=1/2 cycle       |
23262     MOV     X,Y                 \                   ^
23263     RRUM    #1,Y                \ Y=1/4
23264     ADD     X,Y                 \ Y=3/4 cycle
23265     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
23266     U>= UNTIL                   \ 2
23267 \ ******************************\
23268 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
23269 \ ******************************\
23270     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
23271     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
23272     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
23273     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
23274     SUB     #1,W                \ decrement count loop
23275 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
23276 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
23277 0<> WHILE                       \ ----> out of loop ----+
23278     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
23279     BEGIN                       \                       |
23280         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
23281         CMP Y,X                 \ 1                     |   cycle time out of bound ?
23282         U>= IF                  \ 2                 ^   |   yes:
23283         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
23284         GOTO BW1                \                   |   |      quit on truncated RC5 message
23285         THEN                    \                   |   |
23286         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
23287     0<> UNTIL                   \ 2                 |   |
23288 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
23289 \ ******************************\                       |
23290 \ RC5_SampleEndOf:              \ <---------------------+
23291 \ ******************************\
23292 BIC #$30,&RC5_TIM_CTL           \   stop timer
23293 \ ******************************\
23294 \ RC5_ComputeNewRC5word         \
23295 \ ******************************\
23296 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
23297 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
23298 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
23299 \ ******************************\
23300 \ RC5_ComputeC6bit              \
23301 \ ******************************\
23302 BIT     #BIT14,T                \ test /C6 bit in T
23303 0= IF   BIS #BIT6,X             \ set C6 bit in X
23304 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
23305 \ ******************************\
23306 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
23307 \ ******************************\
23308 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
23309 \ ******************************\
23310 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
23311 XOR     @RSP,T                  \ (new XOR old) Toggle bits
23312 BIT     #UF10,T                 \ repeated RC5_command ?
23313 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
23314 XOR #UF10,0(RSP)                \ 5 toggle bit memory
23315 \ ******************************\
23316 \ Display IR_RC5 code           \
23317 \ ******************************\
23318 SUB #8,PSP                      \ TOS -- x x x x TOS
23319 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
23320 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
23321 MOV #$10,&BASEADR               \                                               set hexadecimal base
23322 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
23323 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
23324 LO2HI                           \                                               switch from assembler to FORTH
23325     LCD_CLEAR                   \                                               set LCD cursor at home
23326     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
23327     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
23328     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
23329     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
23330 HI2LO                           \     --                                        switch from FORTH to assembler
23331 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
23332 MOV @PSP+,TOS                   \     -- TOS
23333 RET
23334 ENDASM
23335
23336 \ ******************************\
23337 ASM BACKGROUND                  \
23338 \ ******************************\
23339 BEGIN
23340 \     ...                         \ insert here your background task
23341 \     ...                         \
23342 \     ...                         \
23343     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
23344     BIS &LPM_MODE,SR            \
23345 \ ******************************\
23346 \ here start all interrupts     \
23347 \ ******************************\
23348 \ here return all interrupts    \
23349 \ ******************************\
23350 AGAIN                           \
23351 ENDASM                          \
23352 \ ******************************\
23353
23354 \ ------------------------------\
23355 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
23356 \ ------------------------------\
23357 \     ...                         \ init specific I/O sys as you want
23358 \     ...                         \ before executing default WARM
23359     MOV #WARM,X                 \ ['] WARM 
23360     ADD #4,X                    \ >BODY
23361     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
23362 ENDASM
23363 \ ------------------------------\
23364
23365 \ ------------------------------\
23366 CODE STOP                       \ stops multitasking, must to be used before downloading app
23367 \ ------------------------------\
23368 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
23369     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
23370     MOV X,-2(X)                 \ restore the default background: SLEEP
23371     MOV #WARM,X
23372     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
23373     BIC.B #RC5,&IR_IE           \ clear RC5_Int
23374     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
23375     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
23376     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
23377     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
23378     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
23379 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
23380 ECHO                            \
23381 ." RC5toLCD is removed,"
23382 ."  type START to restart"
23383  WARM                           \ performs reset to reset all interrupt vectors.    
23384 ;
23385 \ ------------------------------\
23386
23387 \ ------------------------------\
23388 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
23389 \ ------------------------------\
23390 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
23391 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
23392 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
23393 \                           --       \ID input divider \ 10 = /4
23394 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
23395 \                                 -  \TBCLR TimerB Clear
23396 \                                  - \TBIE
23397 \                                   -\TBIFG
23398 \ -------------------------------\
23399 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
23400 \                  --                 \CM Capture Mode
23401 \                    --               \CCIS
23402 \                       -             \SCS
23403 \                        --           \CLLD
23404 \                          -          \CAP
23405 \                            ---      \OUTMOD \ 011 = set/reset
23406 \                               -     \CCIE
23407 \                                 -   \CCI
23408 \                                  -  \OUT
23409 \                                   - \COV
23410 \                                    -\CCIFG
23411 \ -------------------------------\
23412 \ LCD_TIM_CCRx                   \
23413 \ -------------------------------\
23414 \ LCD_TIM_EX0                    \ 
23415 \ ------------------------------\
23416 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
23417 \ ------------------------------\
23418 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
23419 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
23420 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
23421     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
23422 [THEN]
23423 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
23424     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
23425 [THEN]
23426     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
23427 \ ------------------------------\
23428 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
23429 \ ------------------------------\
23430 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
23431     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
23432 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
23433 \ ------------------------------\
23434     BIS.B #LCDVo,&LCDVo_DIR     \
23435     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
23436 \ ------------------------------\
23437     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
23438     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
23439 \ ------------------------------\
23440     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
23441     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
23442 \ ******************************\
23443 \ init RC5_Int                  \
23444 \ ******************************\
23445     BIS.B #RC5,&IR_IE           \ enable RC5_Int
23446     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
23447     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
23448 \ ******************************\
23449 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
23450 \ ******************************\
23451 \              %01 0001 0100    \ TAxCTL
23452 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
23453 \                  --           \ ID        divided by 1
23454 \                    --         \ MC        MODE = up to TAxCCRn
23455 \                        -      \ TACLR     clear timer count
23456 \                         -     \ TAIE
23457 \                          -    \ TAIFG
23458 \ ------------------------------\
23459 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
23460 \ ------------------------------\
23461 \                        000    \ TAxEX0
23462 \                        ---    \ TAIDEX    pre divisor
23463 \ ------------------------------\
23464 \          %0000 0000 0000 0101 \ TAxCCR0
23465     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
23466 \ ------------------------------\
23467 \          %0000 0000 0001 0000 \ TAxCCTL0
23468 \                   -           \ CAP capture/compare mode = compare
23469 \                        -      \ CCIEn
23470 \                             - \ CCIFGn
23471     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
23472 \ ------------------------------\
23473     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
23474 \ ------------------------------\
23475 \ define LPM mode for ACCEPT    \
23476 \ ------------------------------\
23477 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
23478 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
23479 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
23480 \ ------------------------------\
23481 \ activate I/O                  \
23482 \ ------------------------------\
23483 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
23484 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
23485 \ ------------------------------\
23486 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
23487 \ ------------------------------\
23488 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
23489 \ CMP #2,Y                        \ Power_ON event
23490 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
23491 CMP #4,Y                        \
23492 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
23493 \ CMP #6,Y                        \
23494 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
23495 \ CMP #$0A,Y                      \
23496 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
23497 \ CMP #$16,Y                      \
23498 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
23499 \ ------------------------------\
23500 COLON                           \
23501 \ ------------------------------\
23502 \ Init LCD 2x20                 \
23503 \ ------------------------------\
23504     #1000 20_US                 \ 1- wait 20 ms
23505     %011 TOP_LCD                \ 2- send DB5=DB4=1
23506     #205 20_US                  \ 3- wait 4,1 ms
23507     %011 TOP_LCD                \ 4- send again DB5=DB4=1
23508     #5 20_US                    \ 5- wait 0,1 ms
23509     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
23510     #2 20_US                    \    wait 40 us = LCD cycle
23511     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
23512     #2 20_US                    \    wait 40 us = LCD cycle
23513     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
23514     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
23515     LCD_CLEAR                   \ 10- "LCD_Clear"
23516     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
23517     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
23518     LCD_CLEAR                   \ 10- "LCD_Clear"
23519     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
23520     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
23521     CR ." I love you"           \ display message on LCD
23522     ['] CR >BODY IS CR          \ CR executes its default value
23523     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
23524     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
23525     PWR_STATE ABORT             \ init DP and continues with ABORT
23526 ;                               \
23527 \ ------------------------------\
23528
23529 \ ------------------------------\
23530 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
23531 \ ------------------------------\
23532 MOV #SLEEP,X                    \ replace default background process SLEEP
23533 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
23534 MOV #WARM,X                     \ replace default WARM
23535 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
23536 MOV X,PC                        \ then execute new WARM
23537 ENDCODE 
23538 \ ------------------------------\
23539
23540 ECHO
23541             ; downloading RC5toLCD.4th is done
23542 RST_HERE    ; this app is protected against <reset>
23543
23544
23545 RST_STATE
23546
23547 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
23548
23549 [UNDEFINED] MARKER [IF]
23550 \  https://forth-standard.org/standard/core/MARKER
23551 \  MARKER
23552 \ ( "<spaces>name" -- )
23553 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
23554 \ with the execution semantics defined below.
23555
23556 \ name Execution: ( -- )
23557 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
23558 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
23559 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
23560 \ not necessarily provided. No other contextual information such as numeric base is affected
23561 \
23562 : MARKER
23563 CREATE
23564 HI2LO
23565 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
23566 SUB #2,Y            \ 1 Y = LFA
23567 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
23568 ADD #4,&DP          \ 3 add 2 cells
23569 LO2HI
23570 DOES>
23571 HI2LO
23572 MOV @RSP+,IP        \ -- PFA
23573 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
23574 MOV @TOS,&INIDP     \       set DP value for RST_STATE
23575 MOV @PSP+,TOS       \ --
23576 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
23577 ENDCODE
23578 [THEN]
23579
23580 MARKER {RC5TOLCD}
23581
23582 [UNDEFINED] @ [IF]
23583 \ https://forth-standard.org/standard/core/Fetch
23584 \ @     c-addr -- char   fetch char from memory
23585 CODE @
23586 MOV @TOS,TOS
23587 MOV @IP+,PC
23588 ENDCODE
23589 [THEN]
23590
23591 [UNDEFINED] CONSTANT [IF]
23592 \ https://forth-standard.org/standard/core/CONSTANT
23593 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
23594 : CONSTANT 
23595 CREATE
23596 HI2LO
23597 MOV TOS,-2(W)           \   PFA = n
23598 MOV @PSP+,TOS
23599 MOV @RSP+,IP
23600 MOV @IP+,PC
23601 ENDCODE
23602 [THEN]
23603
23604 [UNDEFINED] STATE [IF]
23605 \ https://forth-standard.org/standard/core/STATE
23606 \ STATE   -- a-addr       holds compiler state
23607 STATEADR CONSTANT STATE
23608 [THEN]
23609
23610 [UNDEFINED] = [IF]
23611 \ https://forth-standard.org/standard/core/Equal
23612 \ =      x1 x2 -- flag         test x1=x2
23613 CODE =
23614 SUB @PSP+,TOS   \ 2
23615 0<> IF          \ 2
23616     AND #0,TOS  \ 1
23617     MOV @IP+,PC \ 4
23618 THEN
23619 XOR #-1,TOS     \ 1 flag Z = 1
23620 MOV @IP+,PC     \ 4
23621 ENDCODE
23622 [THEN]
23623
23624 [UNDEFINED] IF [IF]
23625 \ https://forth-standard.org/standard/core/IF
23626 \ IF       -- IFadr    initialize conditional forward branch
23627 CODE IF       \ immediate
23628 SUB #2,PSP              \
23629 MOV TOS,0(PSP)          \
23630 MOV &DP,TOS             \ -- HERE
23631 ADD #4,&DP            \           compile one word, reserve one word
23632 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
23633 ADD #2,TOS              \ -- HERE+2=IFadr
23634 MOV @IP+,PC
23635 ENDCODE IMMEDIATE
23636 [THEN]
23637
23638 [UNDEFINED] THEN [IF]
23639 \ https://forth-standard.org/standard/core/THEN
23640 \ THEN     IFadr --                resolve forward branch
23641 CODE THEN               \ immediate
23642 MOV &DP,0(TOS)          \ -- IFadr
23643 MOV @PSP+,TOS           \ --
23644 MOV @IP+,PC
23645 ENDCODE IMMEDIATE
23646 [THEN]
23647
23648 [UNDEFINED] ELSE [IF]
23649 \ https://forth-standard.org/standard/core/ELSE
23650 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
23651 CODE ELSE     \ immediate
23652 ADD #4,&DP              \ make room to compile two words
23653 MOV &DP,W               \ W=HERE+4
23654 MOV #BRAN,-4(W)
23655 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
23656 SUB #2,W                \ HERE+2
23657 MOV W,TOS               \ -- ELSEadr
23658 MOV @IP+,PC
23659 ENDCODE IMMEDIATE
23660 [THEN]
23661
23662 [UNDEFINED] DEFER [IF]
23663 \ https://forth-standard.org/standard/core/DEFER
23664 \ DEFER "<spaces>name"   --
23665 \ Skip leading space delimiters. Parse name delimited by a space.
23666 \ Create a definition for name with the execution semantics defined below.
23667
23668 \ name Execution:   --
23669 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
23670 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
23671 : DEFER
23672 CREATE
23673 HI2LO
23674 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
23675 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
23676 MOV @RSP+,IP
23677 MOV @IP+,PC
23678 ENDCODE
23679 [THEN]
23680
23681 [UNDEFINED] DEFER! [IF]
23682 \ https://forth-standard.org/standard/core/DEFERStore
23683 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
23684 CODE DEFER!             \ xt2 xt1 --
23685 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
23686 MOV @PSP+,TOS           \ --
23687 MOV @IP+,PC
23688 ENDCODE
23689 [THEN]
23690
23691 [UNDEFINED] IS [IF]
23692 \ https://forth-standard.org/standard/core/IS
23693 \ IS <name>        xt --
23694 \ used as is :
23695 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
23696 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
23697 \ or in a definition : ... ['] U. IS DISPLAY ...
23698 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
23699 \
23700 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
23701 : IS
23702 STATE @
23703 IF  POSTPONE ['] POSTPONE DEFER! 
23704 ELSE ' DEFER! 
23705 THEN
23706 ; IMMEDIATE
23707 [THEN]
23708
23709 [UNDEFINED] >BODY [IF]
23710 \ https://forth-standard.org/standard/core/toBODY
23711 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
23712 CODE >BODY
23713 ADD #4,TOS
23714 MOV @IP+,PC
23715 ENDCODE
23716 [THEN]
23717
23718 \ CODE 20uS           \ n --      8MHz version
23719 \ BEGIN               \ 4 + 16 ~ loop
23720 \     MOV #39,rDOCON   \ 39
23721 \     BEGIN           \ 4 ~ loop
23722 \         NOP
23723 \         SUB #1,rDOCON
23724 \     0=  UNTIL
23725 \     SUB #1,TOS      \ 1
23726 \ 0= UNTIL
23727 \ MOV #XDOCON,rDOCON  \ 2
23728 \ MOV @PSP+,TOS
23729 \ MOV @RSP+,IP        \
23730 \ ENDCODE
23731
23732 CODE 20_US                      \ n --      n * 20 us
23733 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
23734     BEGIN
23735         BIT #1,&LCD_TIM_CTL     \ 3
23736     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
23737     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
23738     SUB #1,TOS                  \ 1
23739 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
23740 MOV @PSP+,TOS                   \ 2
23741 MOV @IP+,PC                     \ 4
23742 ENDCODE
23743
23744 CODE TOP_LCD                    \ LCD Sample
23745 \                               \ if write : %xxxx_WWWW --
23746 \                               \ if read  : -- %0000_RRRR
23747     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
23748     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
23749 0= IF                           \ write LCD bits pattern
23750     AND.B #LCD_DB,TOS           \ 
23751     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
23752     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
23753     MOV @PSP+,TOS               \
23754     MOV @IP+,PC
23755 THEN                            \ read LCD bits pattern
23756     SUB #2,PSP
23757     MOV TOS,0(PSP)
23758     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
23759     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
23760     AND.B #LCD_DB,TOS           \
23761     MOV @IP+,PC
23762 ENDCODE
23763
23764 CODE LCD_WRC                    \ char --         Write Char
23765     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
23766 BW1 SUB #2,PSP                  \
23767     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
23768     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
23769     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
23770     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
23771 COLON                           \ high level word starts here 
23772     TOP_LCD 2 20_US             \ write high nibble first
23773     TOP_LCD 2 20_US 
23774 ;
23775
23776 CODE LCD_WRF                    \ func --         Write Fonction
23777     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
23778     GOTO BW1
23779 ENDCODE
23780
23781 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
23782 : LCD_HOME $02 LCD_WRF 100 20_us ;
23783
23784 \ [UNDEFINED] OR [IF]
23785
23786 \ \ https://forth-standard.org/standard/core/OR
23787 \ \ C OR     x1 x2 -- x3           logical OR
23788 \ CODE OR
23789 \ BIS @PSP+,TOS
23790 \ MOV @IP+,PC
23791 \ ENDCODE
23792
23793 \ [THEN]
23794
23795 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
23796 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
23797 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
23798 \ : LCD_FN_SET        $20 OR LCD_WrF ;
23799 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
23800 \ : LCD_GOTO          $80 OR LCD_WrF ;
23801
23802
23803 \ CODE LCD_RDS                    \ -- status       Read Status
23804 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
23805 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
23806 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
23807 \ COLON                           \ starts a FORTH word
23808 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
23809 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
23810 \ HI2LO                           \ switch from FORTH to assembler
23811 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
23812 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
23813 \     MOV @RSP+,IP                \ restore IP saved by COLON
23814 \     MOV @IP+,PC                 \
23815 \ ENDCODE
23816
23817 \ CODE LCD_RDC                    \ -- char         Read Char
23818 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
23819 \     GOTO BW1
23820 \ ENDCODE
23821
23822
23823 \ ******************************\
23824 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
23825 \ ******************************\
23826 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
23827 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
23828 BIT.B #SW2,&SW2_IN              \ test switch S2
23829 0= IF                           \ case of switch S2 pressed
23830     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
23831     U< IF
23832         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
23833     THEN
23834 ELSE
23835     BIT.B #SW1,&SW1_IN          \ test switch S1 input
23836     0= IF                       \ case of Switch S1 pressed
23837         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
23838         U>= IF                  \
23839            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
23840         THEN                    \
23841     THEN                        \
23842 THEN                            \
23843 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
23844 RET                             \ 5
23845 ENDASM
23846
23847 \ ******************************\
23848 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
23849 \ ******************************\
23850 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
23851 \ ******************************\
23852 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
23853 \                               \       SMclock = 8|16|24 MHz
23854 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
23855 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
23856 \                               \       SR(9)=new Toggle bit memory (ADD on)
23857 \ ******************************\
23858 \ RC5_FirstStartBitHalfCycle:   \
23859 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
23860 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
23861 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
23862 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
23863 \ [THEN]
23864 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
23865     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
23866 [THEN]
23867 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
23868     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
23869 [THEN]
23870 MOV #1778,X                     \ RC5_Period * 1us
23871 MOV #14,W                       \ count of loop
23872 BEGIN                           \
23873 \ ******************************\
23874 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
23875 \ ******************************\                   |
23876 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
23877 \ RC5_Compute_3/4_Period:       \                   |
23878     RRUM    #1,X                \ X=1/2 cycle       |
23879     MOV     X,Y                 \                   ^
23880     RRUM    #1,Y                \ Y=1/4
23881     ADD     X,Y                 \ Y=3/4 cycle
23882     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
23883     U>= UNTIL                   \ 2
23884 \ ******************************\
23885 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
23886 \ ******************************\
23887     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
23888     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
23889     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
23890     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
23891     SUB     #1,W                \ decrement count loop
23892 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
23893 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
23894 0<> WHILE                       \ ----> out of loop ----+
23895     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
23896     BEGIN                       \                       |
23897         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
23898         CMP Y,X                 \ 1                     |   cycle time out of bound ?
23899         U>= IF                  \ 2                 ^   |   yes:
23900         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
23901         GOTO BW1                \                   |   |      quit on truncated RC5 message
23902         THEN                    \                   |   |
23903         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
23904     0<> UNTIL                   \ 2                 |   |
23905 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
23906 \ ******************************\                       |
23907 \ RC5_SampleEndOf:              \ <---------------------+
23908 \ ******************************\
23909 BIC #$30,&RC5_TIM_CTL           \   stop timer
23910 \ ******************************\
23911 \ RC5_ComputeNewRC5word         \
23912 \ ******************************\
23913 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
23914 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
23915 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
23916 \ ******************************\
23917 \ RC5_ComputeC6bit              \
23918 \ ******************************\
23919 BIT     #BIT14,T                \ test /C6 bit in T
23920 0= IF   BIS #BIT6,X             \ set C6 bit in X
23921 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
23922 \ ******************************\
23923 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
23924 \ ******************************\
23925 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
23926 \ ******************************\
23927 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
23928 XOR     @RSP,T                  \ (new XOR old) Toggle bits
23929 BIT     #UF10,T                 \ repeated RC5_command ?
23930 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
23931 XOR #UF10,0(RSP)                \ 5 toggle bit memory
23932 \ ******************************\
23933 \ Display IR_RC5 code           \
23934 \ ******************************\
23935 SUB #8,PSP                      \ TOS -- x x x x TOS
23936 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
23937 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
23938 MOV #$10,&BASEADR               \                                               set hexadecimal base
23939 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
23940 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
23941 LO2HI                           \                                               switch from assembler to FORTH
23942     LCD_CLEAR                   \                                               set LCD cursor at home
23943     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
23944     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
23945     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
23946     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
23947 HI2LO                           \     --                                        switch from FORTH to assembler
23948 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
23949 MOV @PSP+,TOS                   \     -- TOS
23950 RET
23951 ENDASM
23952
23953 \ ******************************\
23954 ASM BACKGROUND                  \
23955 \ ******************************\
23956 BEGIN
23957 \     ...                         \ insert here your background task
23958 \     ...                         \
23959 \     ...                         \
23960     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
23961     BIS &LPM_MODE,SR            \
23962 \ ******************************\
23963 \ here start all interrupts     \
23964 \ ******************************\
23965 \ here return all interrupts    \
23966 \ ******************************\
23967 AGAIN                           \
23968 ENDASM                          \
23969 \ ******************************\
23970
23971 \ ------------------------------\
23972 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
23973 \ ------------------------------\
23974 \     ...                         \ init specific I/O sys as you want
23975 \     ...                         \ before executing default WARM
23976     MOV #WARM,X                 \ ['] WARM 
23977     ADD #4,X                    \ >BODY
23978     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
23979 ENDASM
23980 \ ------------------------------\
23981
23982 \ ------------------------------\
23983 CODE STOP                       \ stops multitasking, must to be used before downloading app
23984 \ ------------------------------\
23985 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
23986     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
23987     MOV X,-2(X)                 \ restore the default background: SLEEP
23988     MOV #WARM,X
23989     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
23990     BIC.B #RC5,&IR_IE           \ clear RC5_Int
23991     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
23992     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
23993     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
23994     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
23995     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
23996 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
23997 ECHO                            \
23998 ." RC5toLCD is removed,"
23999 ."  type START to restart"
24000  WARM                           \ performs reset to reset all interrupt vectors.    
24001 ;
24002 \ ------------------------------\
24003
24004 \ ------------------------------\
24005 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
24006 \ ------------------------------\
24007 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
24008 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
24009 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
24010 \                           --       \ID input divider \ 10 = /4
24011 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
24012 \                                 -  \TBCLR TimerB Clear
24013 \                                  - \TBIE
24014 \                                   -\TBIFG
24015 \ -------------------------------\
24016 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
24017 \                  --                 \CM Capture Mode
24018 \                    --               \CCIS
24019 \                       -             \SCS
24020 \                        --           \CLLD
24021 \                          -          \CAP
24022 \                            ---      \OUTMOD \ 011 = set/reset
24023 \                               -     \CCIE
24024 \                                 -   \CCI
24025 \                                  -  \OUT
24026 \                                   - \COV
24027 \                                    -\CCIFG
24028 \ -------------------------------\
24029 \ LCD_TIM_CCRx                   \
24030 \ -------------------------------\
24031 \ LCD_TIM_EX0                    \ 
24032 \ ------------------------------\
24033 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
24034 \ ------------------------------\
24035 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
24036 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
24037 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
24038     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
24039 [THEN]
24040 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
24041     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
24042 [THEN]
24043     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
24044 \ ------------------------------\
24045 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
24046 \ ------------------------------\
24047 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
24048     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
24049 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
24050 \ ------------------------------\
24051     BIS.B #LCDVo,&LCDVo_DIR     \
24052     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
24053 \ ------------------------------\
24054     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
24055     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
24056 \ ------------------------------\
24057     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
24058     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
24059 \ ******************************\
24060 \ init RC5_Int                  \
24061 \ ******************************\
24062     BIS.B #RC5,&IR_IE           \ enable RC5_Int
24063     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
24064     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
24065 \ ******************************\
24066 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
24067 \ ******************************\
24068 \              %01 0001 0100    \ TAxCTL
24069 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
24070 \                  --           \ ID        divided by 1
24071 \                    --         \ MC        MODE = up to TAxCCRn
24072 \                        -      \ TACLR     clear timer count
24073 \                         -     \ TAIE
24074 \                          -    \ TAIFG
24075 \ ------------------------------\
24076 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
24077 \ ------------------------------\
24078 \                        000    \ TAxEX0
24079 \                        ---    \ TAIDEX    pre divisor
24080 \ ------------------------------\
24081 \          %0000 0000 0000 0101 \ TAxCCR0
24082     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
24083 \ ------------------------------\
24084 \          %0000 0000 0001 0000 \ TAxCCTL0
24085 \                   -           \ CAP capture/compare mode = compare
24086 \                        -      \ CCIEn
24087 \                             - \ CCIFGn
24088     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
24089 \ ------------------------------\
24090     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
24091 \ ------------------------------\
24092 \ define LPM mode for ACCEPT    \
24093 \ ------------------------------\
24094 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
24095 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
24096 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
24097 \ ------------------------------\
24098 \ activate I/O                  \
24099 \ ------------------------------\
24100 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
24101 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
24102 \ ------------------------------\
24103 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
24104 \ ------------------------------\
24105 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
24106 \ CMP #2,Y                        \ Power_ON event
24107 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
24108 CMP #4,Y                        \
24109 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
24110 \ CMP #6,Y                        \
24111 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
24112 \ CMP #$0A,Y                      \
24113 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
24114 \ CMP #$16,Y                      \
24115 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
24116 \ ------------------------------\
24117 COLON                           \
24118 \ ------------------------------\
24119 \ Init LCD 2x20                 \
24120 \ ------------------------------\
24121     #1000 20_US                 \ 1- wait 20 ms
24122     %011 TOP_LCD                \ 2- send DB5=DB4=1
24123     #205 20_US                  \ 3- wait 4,1 ms
24124     %011 TOP_LCD                \ 4- send again DB5=DB4=1
24125     #5 20_US                    \ 5- wait 0,1 ms
24126     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
24127     #2 20_US                    \    wait 40 us = LCD cycle
24128     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
24129     #2 20_US                    \    wait 40 us = LCD cycle
24130     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
24131     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
24132     LCD_CLEAR                   \ 10- "LCD_Clear"
24133     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
24134     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
24135     LCD_CLEAR                   \ 10- "LCD_Clear"
24136     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
24137     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
24138     CR ." I love you"           \ display message on LCD
24139     ['] CR >BODY IS CR          \ CR executes its default value
24140     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
24141     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
24142     PWR_STATE ABORT             \ init DP and continues with ABORT
24143 ;                               \
24144 \ ------------------------------\
24145
24146 \ ------------------------------\
24147 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
24148 \ ------------------------------\
24149 MOV #SLEEP,X                    \ replace default background process SLEEP
24150 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
24151 MOV #WARM,X                     \ replace default WARM
24152 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
24153 MOV X,PC                        \ then execute new WARM
24154 ENDCODE 
24155 \ ------------------------------\
24156
24157 ECHO
24158             ; downloading RC5toLCD.4th is done
24159 RST_HERE    ; this app is protected against <reset>
24160
24161
24162 RST_STATE
24163
24164 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
24165
24166 [UNDEFINED] MARKER [IF]
24167 \  https://forth-standard.org/standard/core/MARKER
24168 \  MARKER
24169 \ ( "<spaces>name" -- )
24170 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
24171 \ with the execution semantics defined below.
24172
24173 \ name Execution: ( -- )
24174 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
24175 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
24176 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
24177 \ not necessarily provided. No other contextual information such as numeric base is affected
24178 \
24179 : MARKER
24180 CREATE
24181 HI2LO
24182 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
24183 SUB #2,Y            \ 1 Y = LFA
24184 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
24185 ADD #4,&DP          \ 3 add 2 cells
24186 LO2HI
24187 DOES>
24188 HI2LO
24189 MOV @RSP+,IP        \ -- PFA
24190 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
24191 MOV @TOS,&INIDP     \       set DP value for RST_STATE
24192 MOV @PSP+,TOS       \ --
24193 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
24194 ENDCODE
24195 [THEN]
24196
24197 MARKER {RC5TOLCD}
24198
24199 [UNDEFINED] @ [IF]
24200 \ https://forth-standard.org/standard/core/Fetch
24201 \ @     c-addr -- char   fetch char from memory
24202 CODE @
24203 MOV @TOS,TOS
24204 MOV @IP+,PC
24205 ENDCODE
24206 [THEN]
24207
24208 [UNDEFINED] CONSTANT [IF]
24209 \ https://forth-standard.org/standard/core/CONSTANT
24210 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
24211 : CONSTANT 
24212 CREATE
24213 HI2LO
24214 MOV TOS,-2(W)           \   PFA = n
24215 MOV @PSP+,TOS
24216 MOV @RSP+,IP
24217 MOV @IP+,PC
24218 ENDCODE
24219 [THEN]
24220
24221 [UNDEFINED] STATE [IF]
24222 \ https://forth-standard.org/standard/core/STATE
24223 \ STATE   -- a-addr       holds compiler state
24224 STATEADR CONSTANT STATE
24225 [THEN]
24226
24227 [UNDEFINED] = [IF]
24228 \ https://forth-standard.org/standard/core/Equal
24229 \ =      x1 x2 -- flag         test x1=x2
24230 CODE =
24231 SUB @PSP+,TOS   \ 2
24232 0<> IF          \ 2
24233     AND #0,TOS  \ 1
24234     MOV @IP+,PC \ 4
24235 THEN
24236 XOR #-1,TOS     \ 1 flag Z = 1
24237 MOV @IP+,PC     \ 4
24238 ENDCODE
24239 [THEN]
24240
24241 [UNDEFINED] IF [IF]
24242 \ https://forth-standard.org/standard/core/IF
24243 \ IF       -- IFadr    initialize conditional forward branch
24244 CODE IF       \ immediate
24245 SUB #2,PSP              \
24246 MOV TOS,0(PSP)          \
24247 MOV &DP,TOS             \ -- HERE
24248 ADD #4,&DP            \           compile one word, reserve one word
24249 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
24250 ADD #2,TOS              \ -- HERE+2=IFadr
24251 MOV @IP+,PC
24252 ENDCODE IMMEDIATE
24253 [THEN]
24254
24255 [UNDEFINED] THEN [IF]
24256 \ https://forth-standard.org/standard/core/THEN
24257 \ THEN     IFadr --                resolve forward branch
24258 CODE THEN               \ immediate
24259 MOV &DP,0(TOS)          \ -- IFadr
24260 MOV @PSP+,TOS           \ --
24261 MOV @IP+,PC
24262 ENDCODE IMMEDIATE
24263 [THEN]
24264
24265 [UNDEFINED] ELSE [IF]
24266 \ https://forth-standard.org/standard/core/ELSE
24267 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
24268 CODE ELSE     \ immediate
24269 ADD #4,&DP              \ make room to compile two words
24270 MOV &DP,W               \ W=HERE+4
24271 MOV #BRAN,-4(W)
24272 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
24273 SUB #2,W                \ HERE+2
24274 MOV W,TOS               \ -- ELSEadr
24275 MOV @IP+,PC
24276 ENDCODE IMMEDIATE
24277 [THEN]
24278
24279 [UNDEFINED] DEFER [IF]
24280 \ https://forth-standard.org/standard/core/DEFER
24281 \ DEFER "<spaces>name"   --
24282 \ Skip leading space delimiters. Parse name delimited by a space.
24283 \ Create a definition for name with the execution semantics defined below.
24284
24285 \ name Execution:   --
24286 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
24287 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
24288 : DEFER
24289 CREATE
24290 HI2LO
24291 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
24292 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
24293 MOV @RSP+,IP
24294 MOV @IP+,PC
24295 ENDCODE
24296 [THEN]
24297
24298 [UNDEFINED] DEFER! [IF]
24299 \ https://forth-standard.org/standard/core/DEFERStore
24300 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
24301 CODE DEFER!             \ xt2 xt1 --
24302 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
24303 MOV @PSP+,TOS           \ --
24304 MOV @IP+,PC
24305 ENDCODE
24306 [THEN]
24307
24308 [UNDEFINED] IS [IF]
24309 \ https://forth-standard.org/standard/core/IS
24310 \ IS <name>        xt --
24311 \ used as is :
24312 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
24313 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
24314 \ or in a definition : ... ['] U. IS DISPLAY ...
24315 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
24316 \
24317 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
24318 : IS
24319 STATE @
24320 IF  POSTPONE ['] POSTPONE DEFER! 
24321 ELSE ' DEFER! 
24322 THEN
24323 ; IMMEDIATE
24324 [THEN]
24325
24326 [UNDEFINED] >BODY [IF]
24327 \ https://forth-standard.org/standard/core/toBODY
24328 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
24329 CODE >BODY
24330 ADD #4,TOS
24331 MOV @IP+,PC
24332 ENDCODE
24333 [THEN]
24334
24335 \ CODE 20uS           \ n --      8MHz version
24336 \ BEGIN               \ 4 + 16 ~ loop
24337 \     MOV #39,rDOCON   \ 39
24338 \     BEGIN           \ 4 ~ loop
24339 \         NOP
24340 \         SUB #1,rDOCON
24341 \     0=  UNTIL
24342 \     SUB #1,TOS      \ 1
24343 \ 0= UNTIL
24344 \ MOV #XDOCON,rDOCON  \ 2
24345 \ MOV @PSP+,TOS
24346 \ MOV @RSP+,IP        \
24347 \ ENDCODE
24348
24349 CODE 20_US                      \ n --      n * 20 us
24350 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
24351     BEGIN
24352         BIT #1,&LCD_TIM_CTL     \ 3
24353     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
24354     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
24355     SUB #1,TOS                  \ 1
24356 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
24357 MOV @PSP+,TOS                   \ 2
24358 MOV @IP+,PC                     \ 4
24359 ENDCODE
24360
24361 CODE TOP_LCD                    \ LCD Sample
24362 \                               \ if write : %xxxx_WWWW --
24363 \                               \ if read  : -- %0000_RRRR
24364     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
24365     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
24366 0= IF                           \ write LCD bits pattern
24367     AND.B #LCD_DB,TOS           \ 
24368     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
24369     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
24370     MOV @PSP+,TOS               \
24371     MOV @IP+,PC
24372 THEN                            \ read LCD bits pattern
24373     SUB #2,PSP
24374     MOV TOS,0(PSP)
24375     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
24376     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
24377     AND.B #LCD_DB,TOS           \
24378     MOV @IP+,PC
24379 ENDCODE
24380
24381 CODE LCD_WRC                    \ char --         Write Char
24382     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
24383 BW1 SUB #2,PSP                  \
24384     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
24385     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
24386     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
24387     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
24388 COLON                           \ high level word starts here 
24389     TOP_LCD 2 20_US             \ write high nibble first
24390     TOP_LCD 2 20_US 
24391 ;
24392
24393 CODE LCD_WRF                    \ func --         Write Fonction
24394     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
24395     GOTO BW1
24396 ENDCODE
24397
24398 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
24399 : LCD_HOME $02 LCD_WRF 100 20_us ;
24400
24401 \ [UNDEFINED] OR [IF]
24402
24403 \ \ https://forth-standard.org/standard/core/OR
24404 \ \ C OR     x1 x2 -- x3           logical OR
24405 \ CODE OR
24406 \ BIS @PSP+,TOS
24407 \ MOV @IP+,PC
24408 \ ENDCODE
24409
24410 \ [THEN]
24411
24412 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
24413 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
24414 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
24415 \ : LCD_FN_SET        $20 OR LCD_WrF ;
24416 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
24417 \ : LCD_GOTO          $80 OR LCD_WrF ;
24418
24419
24420 \ CODE LCD_RDS                    \ -- status       Read Status
24421 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
24422 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
24423 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
24424 \ COLON                           \ starts a FORTH word
24425 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
24426 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
24427 \ HI2LO                           \ switch from FORTH to assembler
24428 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
24429 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
24430 \     MOV @RSP+,IP                \ restore IP saved by COLON
24431 \     MOV @IP+,PC                 \
24432 \ ENDCODE
24433
24434 \ CODE LCD_RDC                    \ -- char         Read Char
24435 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
24436 \     GOTO BW1
24437 \ ENDCODE
24438
24439
24440 \ ******************************\
24441 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
24442 \ ******************************\
24443 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
24444 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
24445 BIT.B #SW2,&SW2_IN              \ test switch S2
24446 0= IF                           \ case of switch S2 pressed
24447     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
24448     U< IF
24449         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
24450     THEN
24451 ELSE
24452     BIT.B #SW1,&SW1_IN          \ test switch S1 input
24453     0= IF                       \ case of Switch S1 pressed
24454         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
24455         U>= IF                  \
24456            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
24457         THEN                    \
24458     THEN                        \
24459 THEN                            \
24460 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
24461 RET                             \ 5
24462 ENDASM
24463
24464 \ ******************************\
24465 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
24466 \ ******************************\
24467 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
24468 \ ******************************\
24469 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
24470 \                               \       SMclock = 8|16|24 MHz
24471 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
24472 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
24473 \                               \       SR(9)=new Toggle bit memory (ADD on)
24474 \ ******************************\
24475 \ RC5_FirstStartBitHalfCycle:   \
24476 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
24477 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
24478 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
24479 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
24480 \ [THEN]
24481 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
24482     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
24483 [THEN]
24484 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
24485     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
24486 [THEN]
24487 MOV #1778,X                     \ RC5_Period * 1us
24488 MOV #14,W                       \ count of loop
24489 BEGIN                           \
24490 \ ******************************\
24491 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
24492 \ ******************************\                   |
24493 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
24494 \ RC5_Compute_3/4_Period:       \                   |
24495     RRUM    #1,X                \ X=1/2 cycle       |
24496     MOV     X,Y                 \                   ^
24497     RRUM    #1,Y                \ Y=1/4
24498     ADD     X,Y                 \ Y=3/4 cycle
24499     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
24500     U>= UNTIL                   \ 2
24501 \ ******************************\
24502 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
24503 \ ******************************\
24504     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
24505     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
24506     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
24507     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
24508     SUB     #1,W                \ decrement count loop
24509 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
24510 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
24511 0<> WHILE                       \ ----> out of loop ----+
24512     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
24513     BEGIN                       \                       |
24514         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
24515         CMP Y,X                 \ 1                     |   cycle time out of bound ?
24516         U>= IF                  \ 2                 ^   |   yes:
24517         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
24518         GOTO BW1                \                   |   |      quit on truncated RC5 message
24519         THEN                    \                   |   |
24520         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
24521     0<> UNTIL                   \ 2                 |   |
24522 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
24523 \ ******************************\                       |
24524 \ RC5_SampleEndOf:              \ <---------------------+
24525 \ ******************************\
24526 BIC #$30,&RC5_TIM_CTL           \   stop timer
24527 \ ******************************\
24528 \ RC5_ComputeNewRC5word         \
24529 \ ******************************\
24530 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
24531 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
24532 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
24533 \ ******************************\
24534 \ RC5_ComputeC6bit              \
24535 \ ******************************\
24536 BIT     #BIT14,T                \ test /C6 bit in T
24537 0= IF   BIS #BIT6,X             \ set C6 bit in X
24538 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
24539 \ ******************************\
24540 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
24541 \ ******************************\
24542 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
24543 \ ******************************\
24544 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
24545 XOR     @RSP,T                  \ (new XOR old) Toggle bits
24546 BIT     #UF10,T                 \ repeated RC5_command ?
24547 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
24548 XOR #UF10,0(RSP)                \ 5 toggle bit memory
24549 \ ******************************\
24550 \ Display IR_RC5 code           \
24551 \ ******************************\
24552 SUB #8,PSP                      \ TOS -- x x x x TOS
24553 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
24554 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
24555 MOV #$10,&BASEADR               \                                               set hexadecimal base
24556 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
24557 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
24558 LO2HI                           \                                               switch from assembler to FORTH
24559     LCD_CLEAR                   \                                               set LCD cursor at home
24560     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
24561     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
24562     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
24563     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
24564 HI2LO                           \     --                                        switch from FORTH to assembler
24565 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
24566 MOV @PSP+,TOS                   \     -- TOS
24567 RET
24568 ENDASM
24569
24570 \ ******************************\
24571 ASM BACKGROUND                  \
24572 \ ******************************\
24573 BEGIN
24574 \     ...                         \ insert here your background task
24575 \     ...                         \
24576 \     ...                         \
24577     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
24578     BIS &LPM_MODE,SR            \
24579 \ ******************************\
24580 \ here start all interrupts     \
24581 \ ******************************\
24582 \ here return all interrupts    \
24583 \ ******************************\
24584 AGAIN                           \
24585 ENDASM                          \
24586 \ ******************************\
24587
24588 \ ------------------------------\
24589 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
24590 \ ------------------------------\
24591 \     ...                         \ init specific I/O sys as you want
24592 \     ...                         \ before executing default WARM
24593     MOV #WARM,X                 \ ['] WARM 
24594     ADD #4,X                    \ >BODY
24595     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
24596 ENDASM
24597 \ ------------------------------\
24598
24599 \ ------------------------------\
24600 CODE STOP                       \ stops multitasking, must to be used before downloading app
24601 \ ------------------------------\
24602 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
24603     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
24604     MOV X,-2(X)                 \ restore the default background: SLEEP
24605     MOV #WARM,X
24606     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
24607     BIC.B #RC5,&IR_IE           \ clear RC5_Int
24608     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
24609     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
24610     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
24611     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
24612     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
24613 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
24614 ECHO                            \
24615 ." RC5toLCD is removed,"
24616 ."  type START to restart"
24617  WARM                           \ performs reset to reset all interrupt vectors.    
24618 ;
24619 \ ------------------------------\
24620
24621 \ ------------------------------\
24622 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
24623 \ ------------------------------\
24624 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
24625 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
24626 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
24627 \                           --       \ID input divider \ 10 = /4
24628 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
24629 \                                 -  \TBCLR TimerB Clear
24630 \                                  - \TBIE
24631 \                                   -\TBIFG
24632 \ -------------------------------\
24633 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
24634 \                  --                 \CM Capture Mode
24635 \                    --               \CCIS
24636 \                       -             \SCS
24637 \                        --           \CLLD
24638 \                          -          \CAP
24639 \                            ---      \OUTMOD \ 011 = set/reset
24640 \                               -     \CCIE
24641 \                                 -   \CCI
24642 \                                  -  \OUT
24643 \                                   - \COV
24644 \                                    -\CCIFG
24645 \ -------------------------------\
24646 \ LCD_TIM_CCRx                   \
24647 \ -------------------------------\
24648 \ LCD_TIM_EX0                    \ 
24649 \ ------------------------------\
24650 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
24651 \ ------------------------------\
24652 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
24653 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
24654 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
24655     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
24656 [THEN]
24657 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
24658     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
24659 [THEN]
24660     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
24661 \ ------------------------------\
24662 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
24663 \ ------------------------------\
24664 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
24665     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
24666 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
24667 \ ------------------------------\
24668     BIS.B #LCDVo,&LCDVo_DIR     \
24669     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
24670 \ ------------------------------\
24671     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
24672     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
24673 \ ------------------------------\
24674     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
24675     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
24676 \ ******************************\
24677 \ init RC5_Int                  \
24678 \ ******************************\
24679     BIS.B #RC5,&IR_IE           \ enable RC5_Int
24680     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
24681     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
24682 \ ******************************\
24683 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
24684 \ ******************************\
24685 \              %01 0001 0100    \ TAxCTL
24686 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
24687 \                  --           \ ID        divided by 1
24688 \                    --         \ MC        MODE = up to TAxCCRn
24689 \                        -      \ TACLR     clear timer count
24690 \                         -     \ TAIE
24691 \                          -    \ TAIFG
24692 \ ------------------------------\
24693 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
24694 \ ------------------------------\
24695 \                        000    \ TAxEX0
24696 \                        ---    \ TAIDEX    pre divisor
24697 \ ------------------------------\
24698 \          %0000 0000 0000 0101 \ TAxCCR0
24699     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
24700 \ ------------------------------\
24701 \          %0000 0000 0001 0000 \ TAxCCTL0
24702 \                   -           \ CAP capture/compare mode = compare
24703 \                        -      \ CCIEn
24704 \                             - \ CCIFGn
24705     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
24706 \ ------------------------------\
24707     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
24708 \ ------------------------------\
24709 \ define LPM mode for ACCEPT    \
24710 \ ------------------------------\
24711 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
24712 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
24713 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
24714 \ ------------------------------\
24715 \ activate I/O                  \
24716 \ ------------------------------\
24717 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
24718 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
24719 \ ------------------------------\
24720 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
24721 \ ------------------------------\
24722 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
24723 \ CMP #2,Y                        \ Power_ON event
24724 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
24725 CMP #4,Y                        \
24726 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
24727 \ CMP #6,Y                        \
24728 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
24729 \ CMP #$0A,Y                      \
24730 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
24731 \ CMP #$16,Y                      \
24732 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
24733 \ ------------------------------\
24734 COLON                           \
24735 \ ------------------------------\
24736 \ Init LCD 2x20                 \
24737 \ ------------------------------\
24738     #1000 20_US                 \ 1- wait 20 ms
24739     %011 TOP_LCD                \ 2- send DB5=DB4=1
24740     #205 20_US                  \ 3- wait 4,1 ms
24741     %011 TOP_LCD                \ 4- send again DB5=DB4=1
24742     #5 20_US                    \ 5- wait 0,1 ms
24743     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
24744     #2 20_US                    \    wait 40 us = LCD cycle
24745     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
24746     #2 20_US                    \    wait 40 us = LCD cycle
24747     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
24748     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
24749     LCD_CLEAR                   \ 10- "LCD_Clear"
24750     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
24751     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
24752     LCD_CLEAR                   \ 10- "LCD_Clear"
24753     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
24754     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
24755     CR ." I love you"           \ display message on LCD
24756     ['] CR >BODY IS CR          \ CR executes its default value
24757     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
24758     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
24759     PWR_STATE ABORT             \ init DP and continues with ABORT
24760 ;                               \
24761 \ ------------------------------\
24762
24763 \ ------------------------------\
24764 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
24765 \ ------------------------------\
24766 MOV #SLEEP,X                    \ replace default background process SLEEP
24767 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
24768 MOV #WARM,X                     \ replace default WARM
24769 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
24770 MOV X,PC                        \ then execute new WARM
24771 ENDCODE 
24772 \ ------------------------------\
24773
24774 ECHO
24775             ; downloading RC5toLCD.4th is done
24776 RST_HERE    ; this app is protected against <reset>
24777
24778
24779 RST_STATE
24780
24781 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
24782
24783 [UNDEFINED] MARKER [IF]
24784 \  https://forth-standard.org/standard/core/MARKER
24785 \  MARKER
24786 \ ( "<spaces>name" -- )
24787 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
24788 \ with the execution semantics defined below.
24789
24790 \ name Execution: ( -- )
24791 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
24792 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
24793 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
24794 \ not necessarily provided. No other contextual information such as numeric base is affected
24795 \
24796 : MARKER
24797 CREATE
24798 HI2LO
24799 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
24800 SUB #2,Y            \ 1 Y = LFA
24801 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
24802 ADD #4,&DP          \ 3 add 2 cells
24803 LO2HI
24804 DOES>
24805 HI2LO
24806 MOV @RSP+,IP        \ -- PFA
24807 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
24808 MOV @TOS,&INIDP     \       set DP value for RST_STATE
24809 MOV @PSP+,TOS       \ --
24810 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
24811 ENDCODE
24812 [THEN]
24813
24814 MARKER {RC5TOLCD}
24815
24816 [UNDEFINED] @ [IF]
24817 \ https://forth-standard.org/standard/core/Fetch
24818 \ @     c-addr -- char   fetch char from memory
24819 CODE @
24820 MOV @TOS,TOS
24821 MOV @IP+,PC
24822 ENDCODE
24823 [THEN]
24824
24825 [UNDEFINED] CONSTANT [IF]
24826 \ https://forth-standard.org/standard/core/CONSTANT
24827 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
24828 : CONSTANT 
24829 CREATE
24830 HI2LO
24831 MOV TOS,-2(W)           \   PFA = n
24832 MOV @PSP+,TOS
24833 MOV @RSP+,IP
24834 MOV @IP+,PC
24835 ENDCODE
24836 [THEN]
24837
24838 [UNDEFINED] STATE [IF]
24839 \ https://forth-standard.org/standard/core/STATE
24840 \ STATE   -- a-addr       holds compiler state
24841 STATEADR CONSTANT STATE
24842 [THEN]
24843
24844 [UNDEFINED] = [IF]
24845 \ https://forth-standard.org/standard/core/Equal
24846 \ =      x1 x2 -- flag         test x1=x2
24847 CODE =
24848 SUB @PSP+,TOS   \ 2
24849 0<> IF          \ 2
24850     AND #0,TOS  \ 1
24851     MOV @IP+,PC \ 4
24852 THEN
24853 XOR #-1,TOS     \ 1 flag Z = 1
24854 MOV @IP+,PC     \ 4
24855 ENDCODE
24856 [THEN]
24857
24858 [UNDEFINED] IF [IF]
24859 \ https://forth-standard.org/standard/core/IF
24860 \ IF       -- IFadr    initialize conditional forward branch
24861 CODE IF       \ immediate
24862 SUB #2,PSP              \
24863 MOV TOS,0(PSP)          \
24864 MOV &DP,TOS             \ -- HERE
24865 ADD #4,&DP            \           compile one word, reserve one word
24866 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
24867 ADD #2,TOS              \ -- HERE+2=IFadr
24868 MOV @IP+,PC
24869 ENDCODE IMMEDIATE
24870 [THEN]
24871
24872 [UNDEFINED] THEN [IF]
24873 \ https://forth-standard.org/standard/core/THEN
24874 \ THEN     IFadr --                resolve forward branch
24875 CODE THEN               \ immediate
24876 MOV &DP,0(TOS)          \ -- IFadr
24877 MOV @PSP+,TOS           \ --
24878 MOV @IP+,PC
24879 ENDCODE IMMEDIATE
24880 [THEN]
24881
24882 [UNDEFINED] ELSE [IF]
24883 \ https://forth-standard.org/standard/core/ELSE
24884 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
24885 CODE ELSE     \ immediate
24886 ADD #4,&DP              \ make room to compile two words
24887 MOV &DP,W               \ W=HERE+4
24888 MOV #BRAN,-4(W)
24889 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
24890 SUB #2,W                \ HERE+2
24891 MOV W,TOS               \ -- ELSEadr
24892 MOV @IP+,PC
24893 ENDCODE IMMEDIATE
24894 [THEN]
24895
24896 [UNDEFINED] DEFER [IF]
24897 \ https://forth-standard.org/standard/core/DEFER
24898 \ DEFER "<spaces>name"   --
24899 \ Skip leading space delimiters. Parse name delimited by a space.
24900 \ Create a definition for name with the execution semantics defined below.
24901
24902 \ name Execution:   --
24903 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
24904 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
24905 : DEFER
24906 CREATE
24907 HI2LO
24908 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
24909 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
24910 MOV @RSP+,IP
24911 MOV @IP+,PC
24912 ENDCODE
24913 [THEN]
24914
24915 [UNDEFINED] DEFER! [IF]
24916 \ https://forth-standard.org/standard/core/DEFERStore
24917 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
24918 CODE DEFER!             \ xt2 xt1 --
24919 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
24920 MOV @PSP+,TOS           \ --
24921 MOV @IP+,PC
24922 ENDCODE
24923 [THEN]
24924
24925 [UNDEFINED] IS [IF]
24926 \ https://forth-standard.org/standard/core/IS
24927 \ IS <name>        xt --
24928 \ used as is :
24929 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
24930 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
24931 \ or in a definition : ... ['] U. IS DISPLAY ...
24932 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
24933 \
24934 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
24935 : IS
24936 STATE @
24937 IF  POSTPONE ['] POSTPONE DEFER! 
24938 ELSE ' DEFER! 
24939 THEN
24940 ; IMMEDIATE
24941 [THEN]
24942
24943 [UNDEFINED] >BODY [IF]
24944 \ https://forth-standard.org/standard/core/toBODY
24945 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
24946 CODE >BODY
24947 ADD #4,TOS
24948 MOV @IP+,PC
24949 ENDCODE
24950 [THEN]
24951
24952 \ CODE 20uS           \ n --      8MHz version
24953 \ BEGIN               \ 4 + 16 ~ loop
24954 \     MOV #39,rDOCON   \ 39
24955 \     BEGIN           \ 4 ~ loop
24956 \         NOP
24957 \         SUB #1,rDOCON
24958 \     0=  UNTIL
24959 \     SUB #1,TOS      \ 1
24960 \ 0= UNTIL
24961 \ MOV #XDOCON,rDOCON  \ 2
24962 \ MOV @PSP+,TOS
24963 \ MOV @RSP+,IP        \
24964 \ ENDCODE
24965
24966 CODE 20_US                      \ n --      n * 20 us
24967 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
24968     BEGIN
24969         BIT #1,&LCD_TIM_CTL     \ 3
24970     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
24971     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
24972     SUB #1,TOS                  \ 1
24973 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
24974 MOV @PSP+,TOS                   \ 2
24975 MOV @IP+,PC                     \ 4
24976 ENDCODE
24977
24978 CODE TOP_LCD                    \ LCD Sample
24979 \                               \ if write : %xxxx_WWWW --
24980 \                               \ if read  : -- %0000_RRRR
24981     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
24982     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
24983 0= IF                           \ write LCD bits pattern
24984     AND.B #LCD_DB,TOS           \ 
24985     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
24986     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
24987     MOV @PSP+,TOS               \
24988     MOV @IP+,PC
24989 THEN                            \ read LCD bits pattern
24990     SUB #2,PSP
24991     MOV TOS,0(PSP)
24992     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
24993     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
24994     AND.B #LCD_DB,TOS           \
24995     MOV @IP+,PC
24996 ENDCODE
24997
24998 CODE LCD_WRC                    \ char --         Write Char
24999     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
25000 BW1 SUB #2,PSP                  \
25001     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
25002     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
25003     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
25004     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
25005 COLON                           \ high level word starts here 
25006     TOP_LCD 2 20_US             \ write high nibble first
25007     TOP_LCD 2 20_US 
25008 ;
25009
25010 CODE LCD_WRF                    \ func --         Write Fonction
25011     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
25012     GOTO BW1
25013 ENDCODE
25014
25015 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
25016 : LCD_HOME $02 LCD_WRF 100 20_us ;
25017
25018 \ [UNDEFINED] OR [IF]
25019
25020 \ \ https://forth-standard.org/standard/core/OR
25021 \ \ C OR     x1 x2 -- x3           logical OR
25022 \ CODE OR
25023 \ BIS @PSP+,TOS
25024 \ MOV @IP+,PC
25025 \ ENDCODE
25026
25027 \ [THEN]
25028
25029 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
25030 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
25031 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
25032 \ : LCD_FN_SET        $20 OR LCD_WrF ;
25033 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
25034 \ : LCD_GOTO          $80 OR LCD_WrF ;
25035
25036
25037 \ CODE LCD_RDS                    \ -- status       Read Status
25038 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
25039 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
25040 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
25041 \ COLON                           \ starts a FORTH word
25042 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
25043 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
25044 \ HI2LO                           \ switch from FORTH to assembler
25045 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
25046 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
25047 \     MOV @RSP+,IP                \ restore IP saved by COLON
25048 \     MOV @IP+,PC                 \
25049 \ ENDCODE
25050
25051 \ CODE LCD_RDC                    \ -- char         Read Char
25052 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
25053 \     GOTO BW1
25054 \ ENDCODE
25055
25056
25057 \ ******************************\
25058 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
25059 \ ******************************\
25060 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
25061 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
25062 BIT.B #SW2,&SW2_IN              \ test switch S2
25063 0= IF                           \ case of switch S2 pressed
25064     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
25065     U< IF
25066         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
25067     THEN
25068 ELSE
25069     BIT.B #SW1,&SW1_IN          \ test switch S1 input
25070     0= IF                       \ case of Switch S1 pressed
25071         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
25072         U>= IF                  \
25073            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
25074         THEN                    \
25075     THEN                        \
25076 THEN                            \
25077 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
25078 RET                             \ 5
25079 ENDASM
25080
25081 \ ******************************\
25082 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
25083 \ ******************************\
25084 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
25085 \ ******************************\
25086 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
25087 \                               \       SMclock = 8|16|24 MHz
25088 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
25089 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
25090 \                               \       SR(9)=new Toggle bit memory (ADD on)
25091 \ ******************************\
25092 \ RC5_FirstStartBitHalfCycle:   \
25093 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
25094 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
25095 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
25096 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
25097 \ [THEN]
25098 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
25099     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
25100 [THEN]
25101 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
25102     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
25103 [THEN]
25104 MOV #1778,X                     \ RC5_Period * 1us
25105 MOV #14,W                       \ count of loop
25106 BEGIN                           \
25107 \ ******************************\
25108 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
25109 \ ******************************\                   |
25110 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
25111 \ RC5_Compute_3/4_Period:       \                   |
25112     RRUM    #1,X                \ X=1/2 cycle       |
25113     MOV     X,Y                 \                   ^
25114     RRUM    #1,Y                \ Y=1/4
25115     ADD     X,Y                 \ Y=3/4 cycle
25116     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
25117     U>= UNTIL                   \ 2
25118 \ ******************************\
25119 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
25120 \ ******************************\
25121     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
25122     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
25123     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
25124     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
25125     SUB     #1,W                \ decrement count loop
25126 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
25127 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
25128 0<> WHILE                       \ ----> out of loop ----+
25129     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
25130     BEGIN                       \                       |
25131         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
25132         CMP Y,X                 \ 1                     |   cycle time out of bound ?
25133         U>= IF                  \ 2                 ^   |   yes:
25134         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
25135         GOTO BW1                \                   |   |      quit on truncated RC5 message
25136         THEN                    \                   |   |
25137         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
25138     0<> UNTIL                   \ 2                 |   |
25139 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
25140 \ ******************************\                       |
25141 \ RC5_SampleEndOf:              \ <---------------------+
25142 \ ******************************\
25143 BIC #$30,&RC5_TIM_CTL           \   stop timer
25144 \ ******************************\
25145 \ RC5_ComputeNewRC5word         \
25146 \ ******************************\
25147 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
25148 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
25149 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
25150 \ ******************************\
25151 \ RC5_ComputeC6bit              \
25152 \ ******************************\
25153 BIT     #BIT14,T                \ test /C6 bit in T
25154 0= IF   BIS #BIT6,X             \ set C6 bit in X
25155 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
25156 \ ******************************\
25157 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
25158 \ ******************************\
25159 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
25160 \ ******************************\
25161 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
25162 XOR     @RSP,T                  \ (new XOR old) Toggle bits
25163 BIT     #UF10,T                 \ repeated RC5_command ?
25164 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
25165 XOR #UF10,0(RSP)                \ 5 toggle bit memory
25166 \ ******************************\
25167 \ Display IR_RC5 code           \
25168 \ ******************************\
25169 SUB #8,PSP                      \ TOS -- x x x x TOS
25170 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
25171 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
25172 MOV #$10,&BASEADR               \                                               set hexadecimal base
25173 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
25174 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
25175 LO2HI                           \                                               switch from assembler to FORTH
25176     LCD_CLEAR                   \                                               set LCD cursor at home
25177     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
25178     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
25179     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
25180     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
25181 HI2LO                           \     --                                        switch from FORTH to assembler
25182 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
25183 MOV @PSP+,TOS                   \     -- TOS
25184 RET
25185 ENDASM
25186
25187 \ ******************************\
25188 ASM BACKGROUND                  \
25189 \ ******************************\
25190 BEGIN
25191 \     ...                         \ insert here your background task
25192 \     ...                         \
25193 \     ...                         \
25194     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
25195     BIS &LPM_MODE,SR            \
25196 \ ******************************\
25197 \ here start all interrupts     \
25198 \ ******************************\
25199 \ here return all interrupts    \
25200 \ ******************************\
25201 AGAIN                           \
25202 ENDASM                          \
25203 \ ******************************\
25204
25205 \ ------------------------------\
25206 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
25207 \ ------------------------------\
25208 \     ...                         \ init specific I/O sys as you want
25209 \     ...                         \ before executing default WARM
25210     MOV #WARM,X                 \ ['] WARM 
25211     ADD #4,X                    \ >BODY
25212     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
25213 ENDASM
25214 \ ------------------------------\
25215
25216 \ ------------------------------\
25217 CODE STOP                       \ stops multitasking, must to be used before downloading app
25218 \ ------------------------------\
25219 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
25220     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
25221     MOV X,-2(X)                 \ restore the default background: SLEEP
25222     MOV #WARM,X
25223     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
25224     BIC.B #RC5,&IR_IE           \ clear RC5_Int
25225     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
25226     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
25227     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
25228     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
25229     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
25230 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
25231 ECHO                            \
25232 ." RC5toLCD is removed,"
25233 ."  type START to restart"
25234  WARM                           \ performs reset to reset all interrupt vectors.    
25235 ;
25236 \ ------------------------------\
25237
25238 \ ------------------------------\
25239 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
25240 \ ------------------------------\
25241 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
25242 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
25243 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
25244 \                           --       \ID input divider \ 10 = /4
25245 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
25246 \                                 -  \TBCLR TimerB Clear
25247 \                                  - \TBIE
25248 \                                   -\TBIFG
25249 \ -------------------------------\
25250 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
25251 \                  --                 \CM Capture Mode
25252 \                    --               \CCIS
25253 \                       -             \SCS
25254 \                        --           \CLLD
25255 \                          -          \CAP
25256 \                            ---      \OUTMOD \ 011 = set/reset
25257 \                               -     \CCIE
25258 \                                 -   \CCI
25259 \                                  -  \OUT
25260 \                                   - \COV
25261 \                                    -\CCIFG
25262 \ -------------------------------\
25263 \ LCD_TIM_CCRx                   \
25264 \ -------------------------------\
25265 \ LCD_TIM_EX0                    \ 
25266 \ ------------------------------\
25267 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
25268 \ ------------------------------\
25269 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
25270 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
25271 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
25272     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
25273 [THEN]
25274 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
25275     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
25276 [THEN]
25277     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
25278 \ ------------------------------\
25279 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
25280 \ ------------------------------\
25281 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
25282     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
25283 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
25284 \ ------------------------------\
25285     BIS.B #LCDVo,&LCDVo_DIR     \
25286     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
25287 \ ------------------------------\
25288     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
25289     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
25290 \ ------------------------------\
25291     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
25292     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
25293 \ ******************************\
25294 \ init RC5_Int                  \
25295 \ ******************************\
25296     BIS.B #RC5,&IR_IE           \ enable RC5_Int
25297     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
25298     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
25299 \ ******************************\
25300 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
25301 \ ******************************\
25302 \              %01 0001 0100    \ TAxCTL
25303 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
25304 \                  --           \ ID        divided by 1
25305 \                    --         \ MC        MODE = up to TAxCCRn
25306 \                        -      \ TACLR     clear timer count
25307 \                         -     \ TAIE
25308 \                          -    \ TAIFG
25309 \ ------------------------------\
25310 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
25311 \ ------------------------------\
25312 \                        000    \ TAxEX0
25313 \                        ---    \ TAIDEX    pre divisor
25314 \ ------------------------------\
25315 \          %0000 0000 0000 0101 \ TAxCCR0
25316     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
25317 \ ------------------------------\
25318 \          %0000 0000 0001 0000 \ TAxCCTL0
25319 \                   -           \ CAP capture/compare mode = compare
25320 \                        -      \ CCIEn
25321 \                             - \ CCIFGn
25322     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
25323 \ ------------------------------\
25324     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
25325 \ ------------------------------\
25326 \ define LPM mode for ACCEPT    \
25327 \ ------------------------------\
25328 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
25329 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
25330 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
25331 \ ------------------------------\
25332 \ activate I/O                  \
25333 \ ------------------------------\
25334 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
25335 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
25336 \ ------------------------------\
25337 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
25338 \ ------------------------------\
25339 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
25340 \ CMP #2,Y                        \ Power_ON event
25341 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
25342 CMP #4,Y                        \
25343 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
25344 \ CMP #6,Y                        \
25345 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
25346 \ CMP #$0A,Y                      \
25347 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
25348 \ CMP #$16,Y                      \
25349 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
25350 \ ------------------------------\
25351 COLON                           \
25352 \ ------------------------------\
25353 \ Init LCD 2x20                 \
25354 \ ------------------------------\
25355     #1000 20_US                 \ 1- wait 20 ms
25356     %011 TOP_LCD                \ 2- send DB5=DB4=1
25357     #205 20_US                  \ 3- wait 4,1 ms
25358     %011 TOP_LCD                \ 4- send again DB5=DB4=1
25359     #5 20_US                    \ 5- wait 0,1 ms
25360     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
25361     #2 20_US                    \    wait 40 us = LCD cycle
25362     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
25363     #2 20_US                    \    wait 40 us = LCD cycle
25364     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
25365     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
25366     LCD_CLEAR                   \ 10- "LCD_Clear"
25367     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
25368     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
25369     LCD_CLEAR                   \ 10- "LCD_Clear"
25370     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
25371     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
25372     CR ." I love you"           \ display message on LCD
25373     ['] CR >BODY IS CR          \ CR executes its default value
25374     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
25375     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
25376     PWR_STATE ABORT             \ init DP and continues with ABORT
25377 ;                               \
25378 \ ------------------------------\
25379
25380 \ ------------------------------\
25381 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
25382 \ ------------------------------\
25383 MOV #SLEEP,X                    \ replace default background process SLEEP
25384 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
25385 MOV #WARM,X                     \ replace default WARM
25386 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
25387 MOV X,PC                        \ then execute new WARM
25388 ENDCODE 
25389 \ ------------------------------\
25390
25391 ECHO
25392             ; downloading RC5toLCD.4th is done
25393 RST_HERE    ; this app is protected against <reset>
25394
25395
25396 RST_STATE
25397
25398 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
25399
25400 [UNDEFINED] MARKER [IF]
25401 \  https://forth-standard.org/standard/core/MARKER
25402 \  MARKER
25403 \ ( "<spaces>name" -- )
25404 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
25405 \ with the execution semantics defined below.
25406
25407 \ name Execution: ( -- )
25408 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
25409 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
25410 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
25411 \ not necessarily provided. No other contextual information such as numeric base is affected
25412 \
25413 : MARKER
25414 CREATE
25415 HI2LO
25416 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
25417 SUB #2,Y            \ 1 Y = LFA
25418 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
25419 ADD #4,&DP          \ 3 add 2 cells
25420 LO2HI
25421 DOES>
25422 HI2LO
25423 MOV @RSP+,IP        \ -- PFA
25424 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
25425 MOV @TOS,&INIDP     \       set DP value for RST_STATE
25426 MOV @PSP+,TOS       \ --
25427 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
25428 ENDCODE
25429 [THEN]
25430
25431 MARKER {RC5TOLCD}
25432
25433 [UNDEFINED] @ [IF]
25434 \ https://forth-standard.org/standard/core/Fetch
25435 \ @     c-addr -- char   fetch char from memory
25436 CODE @
25437 MOV @TOS,TOS
25438 MOV @IP+,PC
25439 ENDCODE
25440 [THEN]
25441
25442 [UNDEFINED] CONSTANT [IF]
25443 \ https://forth-standard.org/standard/core/CONSTANT
25444 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
25445 : CONSTANT 
25446 CREATE
25447 HI2LO
25448 MOV TOS,-2(W)           \   PFA = n
25449 MOV @PSP+,TOS
25450 MOV @RSP+,IP
25451 MOV @IP+,PC
25452 ENDCODE
25453 [THEN]
25454
25455 [UNDEFINED] STATE [IF]
25456 \ https://forth-standard.org/standard/core/STATE
25457 \ STATE   -- a-addr       holds compiler state
25458 STATEADR CONSTANT STATE
25459 [THEN]
25460
25461 [UNDEFINED] = [IF]
25462 \ https://forth-standard.org/standard/core/Equal
25463 \ =      x1 x2 -- flag         test x1=x2
25464 CODE =
25465 SUB @PSP+,TOS   \ 2
25466 0<> IF          \ 2
25467     AND #0,TOS  \ 1
25468     MOV @IP+,PC \ 4
25469 THEN
25470 XOR #-1,TOS     \ 1 flag Z = 1
25471 MOV @IP+,PC     \ 4
25472 ENDCODE
25473 [THEN]
25474
25475 [UNDEFINED] IF [IF]
25476 \ https://forth-standard.org/standard/core/IF
25477 \ IF       -- IFadr    initialize conditional forward branch
25478 CODE IF       \ immediate
25479 SUB #2,PSP              \
25480 MOV TOS,0(PSP)          \
25481 MOV &DP,TOS             \ -- HERE
25482 ADD #4,&DP            \           compile one word, reserve one word
25483 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
25484 ADD #2,TOS              \ -- HERE+2=IFadr
25485 MOV @IP+,PC
25486 ENDCODE IMMEDIATE
25487 [THEN]
25488
25489 [UNDEFINED] THEN [IF]
25490 \ https://forth-standard.org/standard/core/THEN
25491 \ THEN     IFadr --                resolve forward branch
25492 CODE THEN               \ immediate
25493 MOV &DP,0(TOS)          \ -- IFadr
25494 MOV @PSP+,TOS           \ --
25495 MOV @IP+,PC
25496 ENDCODE IMMEDIATE
25497 [THEN]
25498
25499 [UNDEFINED] ELSE [IF]
25500 \ https://forth-standard.org/standard/core/ELSE
25501 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
25502 CODE ELSE     \ immediate
25503 ADD #4,&DP              \ make room to compile two words
25504 MOV &DP,W               \ W=HERE+4
25505 MOV #BRAN,-4(W)
25506 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
25507 SUB #2,W                \ HERE+2
25508 MOV W,TOS               \ -- ELSEadr
25509 MOV @IP+,PC
25510 ENDCODE IMMEDIATE
25511 [THEN]
25512
25513 [UNDEFINED] DEFER [IF]
25514 \ https://forth-standard.org/standard/core/DEFER
25515 \ DEFER "<spaces>name"   --
25516 \ Skip leading space delimiters. Parse name delimited by a space.
25517 \ Create a definition for name with the execution semantics defined below.
25518
25519 \ name Execution:   --
25520 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
25521 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
25522 : DEFER
25523 CREATE
25524 HI2LO
25525 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
25526 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
25527 MOV @RSP+,IP
25528 MOV @IP+,PC
25529 ENDCODE
25530 [THEN]
25531
25532 [UNDEFINED] DEFER! [IF]
25533 \ https://forth-standard.org/standard/core/DEFERStore
25534 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
25535 CODE DEFER!             \ xt2 xt1 --
25536 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
25537 MOV @PSP+,TOS           \ --
25538 MOV @IP+,PC
25539 ENDCODE
25540 [THEN]
25541
25542 [UNDEFINED] IS [IF]
25543 \ https://forth-standard.org/standard/core/IS
25544 \ IS <name>        xt --
25545 \ used as is :
25546 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
25547 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
25548 \ or in a definition : ... ['] U. IS DISPLAY ...
25549 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
25550 \
25551 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
25552 : IS
25553 STATE @
25554 IF  POSTPONE ['] POSTPONE DEFER! 
25555 ELSE ' DEFER! 
25556 THEN
25557 ; IMMEDIATE
25558 [THEN]
25559
25560 [UNDEFINED] >BODY [IF]
25561 \ https://forth-standard.org/standard/core/toBODY
25562 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
25563 CODE >BODY
25564 ADD #4,TOS
25565 MOV @IP+,PC
25566 ENDCODE
25567 [THEN]
25568
25569 \ CODE 20uS           \ n --      8MHz version
25570 \ BEGIN               \ 4 + 16 ~ loop
25571 \     MOV #39,rDOCON   \ 39
25572 \     BEGIN           \ 4 ~ loop
25573 \         NOP
25574 \         SUB #1,rDOCON
25575 \     0=  UNTIL
25576 \     SUB #1,TOS      \ 1
25577 \ 0= UNTIL
25578 \ MOV #XDOCON,rDOCON  \ 2
25579 \ MOV @PSP+,TOS
25580 \ MOV @RSP+,IP        \
25581 \ ENDCODE
25582
25583 CODE 20_US                      \ n --      n * 20 us
25584 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
25585     BEGIN
25586         BIT #1,&LCD_TIM_CTL     \ 3
25587     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
25588     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
25589     SUB #1,TOS                  \ 1
25590 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
25591 MOV @PSP+,TOS                   \ 2
25592 MOV @IP+,PC                     \ 4
25593 ENDCODE
25594
25595 CODE TOP_LCD                    \ LCD Sample
25596 \                               \ if write : %xxxx_WWWW --
25597 \                               \ if read  : -- %0000_RRRR
25598     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
25599     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
25600 0= IF                           \ write LCD bits pattern
25601     AND.B #LCD_DB,TOS           \ 
25602     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
25603     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
25604     MOV @PSP+,TOS               \
25605     MOV @IP+,PC
25606 THEN                            \ read LCD bits pattern
25607     SUB #2,PSP
25608     MOV TOS,0(PSP)
25609     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
25610     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
25611     AND.B #LCD_DB,TOS           \
25612     MOV @IP+,PC
25613 ENDCODE
25614
25615 CODE LCD_WRC                    \ char --         Write Char
25616     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
25617 BW1 SUB #2,PSP                  \
25618     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
25619     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
25620     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
25621     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
25622 COLON                           \ high level word starts here 
25623     TOP_LCD 2 20_US             \ write high nibble first
25624     TOP_LCD 2 20_US 
25625 ;
25626
25627 CODE LCD_WRF                    \ func --         Write Fonction
25628     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
25629     GOTO BW1
25630 ENDCODE
25631
25632 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
25633 : LCD_HOME $02 LCD_WRF 100 20_us ;
25634
25635 \ [UNDEFINED] OR [IF]
25636
25637 \ \ https://forth-standard.org/standard/core/OR
25638 \ \ C OR     x1 x2 -- x3           logical OR
25639 \ CODE OR
25640 \ BIS @PSP+,TOS
25641 \ MOV @IP+,PC
25642 \ ENDCODE
25643
25644 \ [THEN]
25645
25646 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
25647 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
25648 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
25649 \ : LCD_FN_SET        $20 OR LCD_WrF ;
25650 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
25651 \ : LCD_GOTO          $80 OR LCD_WrF ;
25652
25653
25654 \ CODE LCD_RDS                    \ -- status       Read Status
25655 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
25656 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
25657 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
25658 \ COLON                           \ starts a FORTH word
25659 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
25660 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
25661 \ HI2LO                           \ switch from FORTH to assembler
25662 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
25663 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
25664 \     MOV @RSP+,IP                \ restore IP saved by COLON
25665 \     MOV @IP+,PC                 \
25666 \ ENDCODE
25667
25668 \ CODE LCD_RDC                    \ -- char         Read Char
25669 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
25670 \     GOTO BW1
25671 \ ENDCODE
25672
25673
25674 \ ******************************\
25675 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
25676 \ ******************************\
25677 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
25678 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
25679 BIT.B #SW2,&SW2_IN              \ test switch S2
25680 0= IF                           \ case of switch S2 pressed
25681     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
25682     U< IF
25683         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
25684     THEN
25685 ELSE
25686     BIT.B #SW1,&SW1_IN          \ test switch S1 input
25687     0= IF                       \ case of Switch S1 pressed
25688         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
25689         U>= IF                  \
25690            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
25691         THEN                    \
25692     THEN                        \
25693 THEN                            \
25694 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
25695 RET                             \ 5
25696 ENDASM
25697
25698 \ ******************************\
25699 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
25700 \ ******************************\
25701 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
25702 \ ******************************\
25703 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
25704 \                               \       SMclock = 8|16|24 MHz
25705 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
25706 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
25707 \                               \       SR(9)=new Toggle bit memory (ADD on)
25708 \ ******************************\
25709 \ RC5_FirstStartBitHalfCycle:   \
25710 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
25711 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
25712 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
25713 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
25714 \ [THEN]
25715 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
25716     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
25717 [THEN]
25718 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
25719     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
25720 [THEN]
25721 MOV #1778,X                     \ RC5_Period * 1us
25722 MOV #14,W                       \ count of loop
25723 BEGIN                           \
25724 \ ******************************\
25725 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
25726 \ ******************************\                   |
25727 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
25728 \ RC5_Compute_3/4_Period:       \                   |
25729     RRUM    #1,X                \ X=1/2 cycle       |
25730     MOV     X,Y                 \                   ^
25731     RRUM    #1,Y                \ Y=1/4
25732     ADD     X,Y                 \ Y=3/4 cycle
25733     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
25734     U>= UNTIL                   \ 2
25735 \ ******************************\
25736 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
25737 \ ******************************\
25738     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
25739     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
25740     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
25741     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
25742     SUB     #1,W                \ decrement count loop
25743 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
25744 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
25745 0<> WHILE                       \ ----> out of loop ----+
25746     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
25747     BEGIN                       \                       |
25748         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
25749         CMP Y,X                 \ 1                     |   cycle time out of bound ?
25750         U>= IF                  \ 2                 ^   |   yes:
25751         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
25752         GOTO BW1                \                   |   |      quit on truncated RC5 message
25753         THEN                    \                   |   |
25754         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
25755     0<> UNTIL                   \ 2                 |   |
25756 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
25757 \ ******************************\                       |
25758 \ RC5_SampleEndOf:              \ <---------------------+
25759 \ ******************************\
25760 BIC #$30,&RC5_TIM_CTL           \   stop timer
25761 \ ******************************\
25762 \ RC5_ComputeNewRC5word         \
25763 \ ******************************\
25764 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
25765 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
25766 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
25767 \ ******************************\
25768 \ RC5_ComputeC6bit              \
25769 \ ******************************\
25770 BIT     #BIT14,T                \ test /C6 bit in T
25771 0= IF   BIS #BIT6,X             \ set C6 bit in X
25772 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
25773 \ ******************************\
25774 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
25775 \ ******************************\
25776 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
25777 \ ******************************\
25778 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
25779 XOR     @RSP,T                  \ (new XOR old) Toggle bits
25780 BIT     #UF10,T                 \ repeated RC5_command ?
25781 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
25782 XOR #UF10,0(RSP)                \ 5 toggle bit memory
25783 \ ******************************\
25784 \ Display IR_RC5 code           \
25785 \ ******************************\
25786 SUB #8,PSP                      \ TOS -- x x x x TOS
25787 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
25788 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
25789 MOV #$10,&BASEADR               \                                               set hexadecimal base
25790 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
25791 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
25792 LO2HI                           \                                               switch from assembler to FORTH
25793     LCD_CLEAR                   \                                               set LCD cursor at home
25794     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
25795     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
25796     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
25797     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
25798 HI2LO                           \     --                                        switch from FORTH to assembler
25799 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
25800 MOV @PSP+,TOS                   \     -- TOS
25801 RET
25802 ENDASM
25803
25804 \ ******************************\
25805 ASM BACKGROUND                  \
25806 \ ******************************\
25807 BEGIN
25808 \     ...                         \ insert here your background task
25809 \     ...                         \
25810 \     ...                         \
25811     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
25812     BIS &LPM_MODE,SR            \
25813 \ ******************************\
25814 \ here start all interrupts     \
25815 \ ******************************\
25816 \ here return all interrupts    \
25817 \ ******************************\
25818 AGAIN                           \
25819 ENDASM                          \
25820 \ ******************************\
25821
25822 \ ------------------------------\
25823 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
25824 \ ------------------------------\
25825 \     ...                         \ init specific I/O sys as you want
25826 \     ...                         \ before executing default WARM
25827     MOV #WARM,X                 \ ['] WARM 
25828     ADD #4,X                    \ >BODY
25829     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
25830 ENDASM
25831 \ ------------------------------\
25832
25833 \ ------------------------------\
25834 CODE STOP                       \ stops multitasking, must to be used before downloading app
25835 \ ------------------------------\
25836 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
25837     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
25838     MOV X,-2(X)                 \ restore the default background: SLEEP
25839     MOV #WARM,X
25840     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
25841     BIC.B #RC5,&IR_IE           \ clear RC5_Int
25842     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
25843     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
25844     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
25845     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
25846     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
25847 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
25848 ECHO                            \
25849 ." RC5toLCD is removed,"
25850 ."  type START to restart"
25851  WARM                           \ performs reset to reset all interrupt vectors.    
25852 ;
25853 \ ------------------------------\
25854
25855 \ ------------------------------\
25856 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
25857 \ ------------------------------\
25858 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
25859 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
25860 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
25861 \                           --       \ID input divider \ 10 = /4
25862 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
25863 \                                 -  \TBCLR TimerB Clear
25864 \                                  - \TBIE
25865 \                                   -\TBIFG
25866 \ -------------------------------\
25867 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
25868 \                  --                 \CM Capture Mode
25869 \                    --               \CCIS
25870 \                       -             \SCS
25871 \                        --           \CLLD
25872 \                          -          \CAP
25873 \                            ---      \OUTMOD \ 011 = set/reset
25874 \                               -     \CCIE
25875 \                                 -   \CCI
25876 \                                  -  \OUT
25877 \                                   - \COV
25878 \                                    -\CCIFG
25879 \ -------------------------------\
25880 \ LCD_TIM_CCRx                   \
25881 \ -------------------------------\
25882 \ LCD_TIM_EX0                    \ 
25883 \ ------------------------------\
25884 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
25885 \ ------------------------------\
25886 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
25887 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
25888 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
25889     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
25890 [THEN]
25891 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
25892     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
25893 [THEN]
25894     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
25895 \ ------------------------------\
25896 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
25897 \ ------------------------------\
25898 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
25899     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
25900 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
25901 \ ------------------------------\
25902     BIS.B #LCDVo,&LCDVo_DIR     \
25903     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
25904 \ ------------------------------\
25905     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
25906     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
25907 \ ------------------------------\
25908     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
25909     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
25910 \ ******************************\
25911 \ init RC5_Int                  \
25912 \ ******************************\
25913     BIS.B #RC5,&IR_IE           \ enable RC5_Int
25914     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
25915     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
25916 \ ******************************\
25917 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
25918 \ ******************************\
25919 \              %01 0001 0100    \ TAxCTL
25920 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
25921 \                  --           \ ID        divided by 1
25922 \                    --         \ MC        MODE = up to TAxCCRn
25923 \                        -      \ TACLR     clear timer count
25924 \                         -     \ TAIE
25925 \                          -    \ TAIFG
25926 \ ------------------------------\
25927 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
25928 \ ------------------------------\
25929 \                        000    \ TAxEX0
25930 \                        ---    \ TAIDEX    pre divisor
25931 \ ------------------------------\
25932 \          %0000 0000 0000 0101 \ TAxCCR0
25933     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
25934 \ ------------------------------\
25935 \          %0000 0000 0001 0000 \ TAxCCTL0
25936 \                   -           \ CAP capture/compare mode = compare
25937 \                        -      \ CCIEn
25938 \                             - \ CCIFGn
25939     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
25940 \ ------------------------------\
25941     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
25942 \ ------------------------------\
25943 \ define LPM mode for ACCEPT    \
25944 \ ------------------------------\
25945 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
25946 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
25947 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
25948 \ ------------------------------\
25949 \ activate I/O                  \
25950 \ ------------------------------\
25951 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
25952 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
25953 \ ------------------------------\
25954 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
25955 \ ------------------------------\
25956 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
25957 \ CMP #2,Y                        \ Power_ON event
25958 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
25959 CMP #4,Y                        \
25960 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
25961 \ CMP #6,Y                        \
25962 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
25963 \ CMP #$0A,Y                      \
25964 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
25965 \ CMP #$16,Y                      \
25966 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
25967 \ ------------------------------\
25968 COLON                           \
25969 \ ------------------------------\
25970 \ Init LCD 2x20                 \
25971 \ ------------------------------\
25972     #1000 20_US                 \ 1- wait 20 ms
25973     %011 TOP_LCD                \ 2- send DB5=DB4=1
25974     #205 20_US                  \ 3- wait 4,1 ms
25975     %011 TOP_LCD                \ 4- send again DB5=DB4=1
25976     #5 20_US                    \ 5- wait 0,1 ms
25977     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
25978     #2 20_US                    \    wait 40 us = LCD cycle
25979     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
25980     #2 20_US                    \    wait 40 us = LCD cycle
25981     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
25982     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
25983     LCD_CLEAR                   \ 10- "LCD_Clear"
25984     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
25985     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
25986     LCD_CLEAR                   \ 10- "LCD_Clear"
25987     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
25988     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
25989     CR ." I love you"           \ display message on LCD
25990     ['] CR >BODY IS CR          \ CR executes its default value
25991     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
25992     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
25993     PWR_STATE ABORT             \ init DP and continues with ABORT
25994 ;                               \
25995 \ ------------------------------\
25996
25997 \ ------------------------------\
25998 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
25999 \ ------------------------------\
26000 MOV #SLEEP,X                    \ replace default background process SLEEP
26001 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
26002 MOV #WARM,X                     \ replace default WARM
26003 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
26004 MOV X,PC                        \ then execute new WARM
26005 ENDCODE 
26006 \ ------------------------------\
26007
26008 ECHO
26009             ; downloading RC5toLCD.4th is done
26010 RST_HERE    ; this app is protected against <reset>
26011
26012
26013 RST_STATE
26014
26015 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
26016
26017 [UNDEFINED] MARKER [IF]
26018 \  https://forth-standard.org/standard/core/MARKER
26019 \  MARKER
26020 \ ( "<spaces>name" -- )
26021 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
26022 \ with the execution semantics defined below.
26023
26024 \ name Execution: ( -- )
26025 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
26026 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
26027 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
26028 \ not necessarily provided. No other contextual information such as numeric base is affected
26029 \
26030 : MARKER
26031 CREATE
26032 HI2LO
26033 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
26034 SUB #2,Y            \ 1 Y = LFA
26035 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
26036 ADD #4,&DP          \ 3 add 2 cells
26037 LO2HI
26038 DOES>
26039 HI2LO
26040 MOV @RSP+,IP        \ -- PFA
26041 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
26042 MOV @TOS,&INIDP     \       set DP value for RST_STATE
26043 MOV @PSP+,TOS       \ --
26044 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
26045 ENDCODE
26046 [THEN]
26047
26048 MARKER {RC5TOLCD}
26049
26050 [UNDEFINED] @ [IF]
26051 \ https://forth-standard.org/standard/core/Fetch
26052 \ @     c-addr -- char   fetch char from memory
26053 CODE @
26054 MOV @TOS,TOS
26055 MOV @IP+,PC
26056 ENDCODE
26057 [THEN]
26058
26059 [UNDEFINED] CONSTANT [IF]
26060 \ https://forth-standard.org/standard/core/CONSTANT
26061 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
26062 : CONSTANT 
26063 CREATE
26064 HI2LO
26065 MOV TOS,-2(W)           \   PFA = n
26066 MOV @PSP+,TOS
26067 MOV @RSP+,IP
26068 MOV @IP+,PC
26069 ENDCODE
26070 [THEN]
26071
26072 [UNDEFINED] STATE [IF]
26073 \ https://forth-standard.org/standard/core/STATE
26074 \ STATE   -- a-addr       holds compiler state
26075 STATEADR CONSTANT STATE
26076 [THEN]
26077
26078 [UNDEFINED] = [IF]
26079 \ https://forth-standard.org/standard/core/Equal
26080 \ =      x1 x2 -- flag         test x1=x2
26081 CODE =
26082 SUB @PSP+,TOS   \ 2
26083 0<> IF          \ 2
26084     AND #0,TOS  \ 1
26085     MOV @IP+,PC \ 4
26086 THEN
26087 XOR #-1,TOS     \ 1 flag Z = 1
26088 MOV @IP+,PC     \ 4
26089 ENDCODE
26090 [THEN]
26091
26092 [UNDEFINED] IF [IF]
26093 \ https://forth-standard.org/standard/core/IF
26094 \ IF       -- IFadr    initialize conditional forward branch
26095 CODE IF       \ immediate
26096 SUB #2,PSP              \
26097 MOV TOS,0(PSP)          \
26098 MOV &DP,TOS             \ -- HERE
26099 ADD #4,&DP            \           compile one word, reserve one word
26100 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
26101 ADD #2,TOS              \ -- HERE+2=IFadr
26102 MOV @IP+,PC
26103 ENDCODE IMMEDIATE
26104 [THEN]
26105
26106 [UNDEFINED] THEN [IF]
26107 \ https://forth-standard.org/standard/core/THEN
26108 \ THEN     IFadr --                resolve forward branch
26109 CODE THEN               \ immediate
26110 MOV &DP,0(TOS)          \ -- IFadr
26111 MOV @PSP+,TOS           \ --
26112 MOV @IP+,PC
26113 ENDCODE IMMEDIATE
26114 [THEN]
26115
26116 [UNDEFINED] ELSE [IF]
26117 \ https://forth-standard.org/standard/core/ELSE
26118 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
26119 CODE ELSE     \ immediate
26120 ADD #4,&DP              \ make room to compile two words
26121 MOV &DP,W               \ W=HERE+4
26122 MOV #BRAN,-4(W)
26123 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
26124 SUB #2,W                \ HERE+2
26125 MOV W,TOS               \ -- ELSEadr
26126 MOV @IP+,PC
26127 ENDCODE IMMEDIATE
26128 [THEN]
26129
26130 [UNDEFINED] DEFER [IF]
26131 \ https://forth-standard.org/standard/core/DEFER
26132 \ DEFER "<spaces>name"   --
26133 \ Skip leading space delimiters. Parse name delimited by a space.
26134 \ Create a definition for name with the execution semantics defined below.
26135
26136 \ name Execution:   --
26137 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
26138 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
26139 : DEFER
26140 CREATE
26141 HI2LO
26142 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
26143 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
26144 MOV @RSP+,IP
26145 MOV @IP+,PC
26146 ENDCODE
26147 [THEN]
26148
26149 [UNDEFINED] DEFER! [IF]
26150 \ https://forth-standard.org/standard/core/DEFERStore
26151 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
26152 CODE DEFER!             \ xt2 xt1 --
26153 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
26154 MOV @PSP+,TOS           \ --
26155 MOV @IP+,PC
26156 ENDCODE
26157 [THEN]
26158
26159 [UNDEFINED] IS [IF]
26160 \ https://forth-standard.org/standard/core/IS
26161 \ IS <name>        xt --
26162 \ used as is :
26163 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
26164 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
26165 \ or in a definition : ... ['] U. IS DISPLAY ...
26166 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
26167 \
26168 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
26169 : IS
26170 STATE @
26171 IF  POSTPONE ['] POSTPONE DEFER! 
26172 ELSE ' DEFER! 
26173 THEN
26174 ; IMMEDIATE
26175 [THEN]
26176
26177 [UNDEFINED] >BODY [IF]
26178 \ https://forth-standard.org/standard/core/toBODY
26179 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
26180 CODE >BODY
26181 ADD #4,TOS
26182 MOV @IP+,PC
26183 ENDCODE
26184 [THEN]
26185
26186 \ CODE 20uS           \ n --      8MHz version
26187 \ BEGIN               \ 4 + 16 ~ loop
26188 \     MOV #39,rDOCON   \ 39
26189 \     BEGIN           \ 4 ~ loop
26190 \         NOP
26191 \         SUB #1,rDOCON
26192 \     0=  UNTIL
26193 \     SUB #1,TOS      \ 1
26194 \ 0= UNTIL
26195 \ MOV #XDOCON,rDOCON  \ 2
26196 \ MOV @PSP+,TOS
26197 \ MOV @RSP+,IP        \
26198 \ ENDCODE
26199
26200 CODE 20_US                      \ n --      n * 20 us
26201 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
26202     BEGIN
26203         BIT #1,&LCD_TIM_CTL     \ 3
26204     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
26205     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
26206     SUB #1,TOS                  \ 1
26207 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
26208 MOV @PSP+,TOS                   \ 2
26209 MOV @IP+,PC                     \ 4
26210 ENDCODE
26211
26212 CODE TOP_LCD                    \ LCD Sample
26213 \                               \ if write : %xxxx_WWWW --
26214 \                               \ if read  : -- %0000_RRRR
26215     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
26216     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
26217 0= IF                           \ write LCD bits pattern
26218     AND.B #LCD_DB,TOS           \ 
26219     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
26220     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
26221     MOV @PSP+,TOS               \
26222     MOV @IP+,PC
26223 THEN                            \ read LCD bits pattern
26224     SUB #2,PSP
26225     MOV TOS,0(PSP)
26226     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
26227     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
26228     AND.B #LCD_DB,TOS           \
26229     MOV @IP+,PC
26230 ENDCODE
26231
26232 CODE LCD_WRC                    \ char --         Write Char
26233     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
26234 BW1 SUB #2,PSP                  \
26235     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
26236     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
26237     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
26238     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
26239 COLON                           \ high level word starts here 
26240     TOP_LCD 2 20_US             \ write high nibble first
26241     TOP_LCD 2 20_US 
26242 ;
26243
26244 CODE LCD_WRF                    \ func --         Write Fonction
26245     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
26246     GOTO BW1
26247 ENDCODE
26248
26249 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
26250 : LCD_HOME $02 LCD_WRF 100 20_us ;
26251
26252 \ [UNDEFINED] OR [IF]
26253
26254 \ \ https://forth-standard.org/standard/core/OR
26255 \ \ C OR     x1 x2 -- x3           logical OR
26256 \ CODE OR
26257 \ BIS @PSP+,TOS
26258 \ MOV @IP+,PC
26259 \ ENDCODE
26260
26261 \ [THEN]
26262
26263 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
26264 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
26265 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
26266 \ : LCD_FN_SET        $20 OR LCD_WrF ;
26267 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
26268 \ : LCD_GOTO          $80 OR LCD_WrF ;
26269
26270
26271 \ CODE LCD_RDS                    \ -- status       Read Status
26272 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
26273 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
26274 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
26275 \ COLON                           \ starts a FORTH word
26276 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
26277 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
26278 \ HI2LO                           \ switch from FORTH to assembler
26279 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
26280 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
26281 \     MOV @RSP+,IP                \ restore IP saved by COLON
26282 \     MOV @IP+,PC                 \
26283 \ ENDCODE
26284
26285 \ CODE LCD_RDC                    \ -- char         Read Char
26286 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
26287 \     GOTO BW1
26288 \ ENDCODE
26289
26290
26291 \ ******************************\
26292 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
26293 \ ******************************\
26294 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
26295 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
26296 BIT.B #SW2,&SW2_IN              \ test switch S2
26297 0= IF                           \ case of switch S2 pressed
26298     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
26299     U< IF
26300         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
26301     THEN
26302 ELSE
26303     BIT.B #SW1,&SW1_IN          \ test switch S1 input
26304     0= IF                       \ case of Switch S1 pressed
26305         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
26306         U>= IF                  \
26307            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
26308         THEN                    \
26309     THEN                        \
26310 THEN                            \
26311 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
26312 RET                             \ 5
26313 ENDASM
26314
26315 \ ******************************\
26316 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
26317 \ ******************************\
26318 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
26319 \ ******************************\
26320 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
26321 \                               \       SMclock = 8|16|24 MHz
26322 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
26323 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
26324 \                               \       SR(9)=new Toggle bit memory (ADD on)
26325 \ ******************************\
26326 \ RC5_FirstStartBitHalfCycle:   \
26327 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
26328 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
26329 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
26330 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
26331 \ [THEN]
26332 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
26333     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
26334 [THEN]
26335 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
26336     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
26337 [THEN]
26338 MOV #1778,X                     \ RC5_Period * 1us
26339 MOV #14,W                       \ count of loop
26340 BEGIN                           \
26341 \ ******************************\
26342 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
26343 \ ******************************\                   |
26344 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
26345 \ RC5_Compute_3/4_Period:       \                   |
26346     RRUM    #1,X                \ X=1/2 cycle       |
26347     MOV     X,Y                 \                   ^
26348     RRUM    #1,Y                \ Y=1/4
26349     ADD     X,Y                 \ Y=3/4 cycle
26350     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
26351     U>= UNTIL                   \ 2
26352 \ ******************************\
26353 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
26354 \ ******************************\
26355     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
26356     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
26357     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
26358     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
26359     SUB     #1,W                \ decrement count loop
26360 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
26361 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
26362 0<> WHILE                       \ ----> out of loop ----+
26363     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
26364     BEGIN                       \                       |
26365         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
26366         CMP Y,X                 \ 1                     |   cycle time out of bound ?
26367         U>= IF                  \ 2                 ^   |   yes:
26368         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
26369         GOTO BW1                \                   |   |      quit on truncated RC5 message
26370         THEN                    \                   |   |
26371         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
26372     0<> UNTIL                   \ 2                 |   |
26373 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
26374 \ ******************************\                       |
26375 \ RC5_SampleEndOf:              \ <---------------------+
26376 \ ******************************\
26377 BIC #$30,&RC5_TIM_CTL           \   stop timer
26378 \ ******************************\
26379 \ RC5_ComputeNewRC5word         \
26380 \ ******************************\
26381 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
26382 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
26383 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
26384 \ ******************************\
26385 \ RC5_ComputeC6bit              \
26386 \ ******************************\
26387 BIT     #BIT14,T                \ test /C6 bit in T
26388 0= IF   BIS #BIT6,X             \ set C6 bit in X
26389 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
26390 \ ******************************\
26391 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
26392 \ ******************************\
26393 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
26394 \ ******************************\
26395 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
26396 XOR     @RSP,T                  \ (new XOR old) Toggle bits
26397 BIT     #UF10,T                 \ repeated RC5_command ?
26398 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
26399 XOR #UF10,0(RSP)                \ 5 toggle bit memory
26400 \ ******************************\
26401 \ Display IR_RC5 code           \
26402 \ ******************************\
26403 SUB #8,PSP                      \ TOS -- x x x x TOS
26404 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
26405 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
26406 MOV #$10,&BASEADR               \                                               set hexadecimal base
26407 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
26408 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
26409 LO2HI                           \                                               switch from assembler to FORTH
26410     LCD_CLEAR                   \                                               set LCD cursor at home
26411     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
26412     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
26413     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
26414     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
26415 HI2LO                           \     --                                        switch from FORTH to assembler
26416 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
26417 MOV @PSP+,TOS                   \     -- TOS
26418 RET
26419 ENDASM
26420
26421 \ ******************************\
26422 ASM BACKGROUND                  \
26423 \ ******************************\
26424 BEGIN
26425 \     ...                         \ insert here your background task
26426 \     ...                         \
26427 \     ...                         \
26428     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
26429     BIS &LPM_MODE,SR            \
26430 \ ******************************\
26431 \ here start all interrupts     \
26432 \ ******************************\
26433 \ here return all interrupts    \
26434 \ ******************************\
26435 AGAIN                           \
26436 ENDASM                          \
26437 \ ******************************\
26438
26439 \ ------------------------------\
26440 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
26441 \ ------------------------------\
26442 \     ...                         \ init specific I/O sys as you want
26443 \     ...                         \ before executing default WARM
26444     MOV #WARM,X                 \ ['] WARM 
26445     ADD #4,X                    \ >BODY
26446     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
26447 ENDASM
26448 \ ------------------------------\
26449
26450 \ ------------------------------\
26451 CODE STOP                       \ stops multitasking, must to be used before downloading app
26452 \ ------------------------------\
26453 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
26454     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
26455     MOV X,-2(X)                 \ restore the default background: SLEEP
26456     MOV #WARM,X
26457     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
26458     BIC.B #RC5,&IR_IE           \ clear RC5_Int
26459     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
26460     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
26461     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
26462     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
26463     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
26464 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
26465 ECHO                            \
26466 ." RC5toLCD is removed,"
26467 ."  type START to restart"
26468  WARM                           \ performs reset to reset all interrupt vectors.    
26469 ;
26470 \ ------------------------------\
26471
26472 \ ------------------------------\
26473 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
26474 \ ------------------------------\
26475 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
26476 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
26477 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
26478 \                           --       \ID input divider \ 10 = /4
26479 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
26480 \                                 -  \TBCLR TimerB Clear
26481 \                                  - \TBIE
26482 \                                   -\TBIFG
26483 \ -------------------------------\
26484 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
26485 \                  --                 \CM Capture Mode
26486 \                    --               \CCIS
26487 \                       -             \SCS
26488 \                        --           \CLLD
26489 \                          -          \CAP
26490 \                            ---      \OUTMOD \ 011 = set/reset
26491 \                               -     \CCIE
26492 \                                 -   \CCI
26493 \                                  -  \OUT
26494 \                                   - \COV
26495 \                                    -\CCIFG
26496 \ -------------------------------\
26497 \ LCD_TIM_CCRx                   \
26498 \ -------------------------------\
26499 \ LCD_TIM_EX0                    \ 
26500 \ ------------------------------\
26501 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
26502 \ ------------------------------\
26503 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
26504 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
26505 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
26506     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
26507 [THEN]
26508 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
26509     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
26510 [THEN]
26511     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
26512 \ ------------------------------\
26513 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
26514 \ ------------------------------\
26515 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
26516     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
26517 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
26518 \ ------------------------------\
26519     BIS.B #LCDVo,&LCDVo_DIR     \
26520     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
26521 \ ------------------------------\
26522     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
26523     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
26524 \ ------------------------------\
26525     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
26526     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
26527 \ ******************************\
26528 \ init RC5_Int                  \
26529 \ ******************************\
26530     BIS.B #RC5,&IR_IE           \ enable RC5_Int
26531     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
26532     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
26533 \ ******************************\
26534 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
26535 \ ******************************\
26536 \              %01 0001 0100    \ TAxCTL
26537 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
26538 \                  --           \ ID        divided by 1
26539 \                    --         \ MC        MODE = up to TAxCCRn
26540 \                        -      \ TACLR     clear timer count
26541 \                         -     \ TAIE
26542 \                          -    \ TAIFG
26543 \ ------------------------------\
26544 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
26545 \ ------------------------------\
26546 \                        000    \ TAxEX0
26547 \                        ---    \ TAIDEX    pre divisor
26548 \ ------------------------------\
26549 \          %0000 0000 0000 0101 \ TAxCCR0
26550     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
26551 \ ------------------------------\
26552 \          %0000 0000 0001 0000 \ TAxCCTL0
26553 \                   -           \ CAP capture/compare mode = compare
26554 \                        -      \ CCIEn
26555 \                             - \ CCIFGn
26556     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
26557 \ ------------------------------\
26558     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
26559 \ ------------------------------\
26560 \ define LPM mode for ACCEPT    \
26561 \ ------------------------------\
26562 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
26563 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
26564 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
26565 \ ------------------------------\
26566 \ activate I/O                  \
26567 \ ------------------------------\
26568 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
26569 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
26570 \ ------------------------------\
26571 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
26572 \ ------------------------------\
26573 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
26574 \ CMP #2,Y                        \ Power_ON event
26575 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
26576 CMP #4,Y                        \
26577 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
26578 \ CMP #6,Y                        \
26579 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
26580 \ CMP #$0A,Y                      \
26581 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
26582 \ CMP #$16,Y                      \
26583 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
26584 \ ------------------------------\
26585 COLON                           \
26586 \ ------------------------------\
26587 \ Init LCD 2x20                 \
26588 \ ------------------------------\
26589     #1000 20_US                 \ 1- wait 20 ms
26590     %011 TOP_LCD                \ 2- send DB5=DB4=1
26591     #205 20_US                  \ 3- wait 4,1 ms
26592     %011 TOP_LCD                \ 4- send again DB5=DB4=1
26593     #5 20_US                    \ 5- wait 0,1 ms
26594     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
26595     #2 20_US                    \    wait 40 us = LCD cycle
26596     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
26597     #2 20_US                    \    wait 40 us = LCD cycle
26598     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
26599     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
26600     LCD_CLEAR                   \ 10- "LCD_Clear"
26601     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
26602     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
26603     LCD_CLEAR                   \ 10- "LCD_Clear"
26604     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
26605     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
26606     CR ." I love you"           \ display message on LCD
26607     ['] CR >BODY IS CR          \ CR executes its default value
26608     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
26609     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
26610     PWR_STATE ABORT             \ init DP and continues with ABORT
26611 ;                               \
26612 \ ------------------------------\
26613
26614 \ ------------------------------\
26615 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
26616 \ ------------------------------\
26617 MOV #SLEEP,X                    \ replace default background process SLEEP
26618 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
26619 MOV #WARM,X                     \ replace default WARM
26620 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
26621 MOV X,PC                        \ then execute new WARM
26622 ENDCODE 
26623 \ ------------------------------\
26624
26625 ECHO
26626             ; downloading RC5toLCD.4th is done
26627 RST_HERE    ; this app is protected against <reset>
26628
26629
26630 RST_STATE
26631
26632 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
26633
26634 [UNDEFINED] MARKER [IF]
26635 \  https://forth-standard.org/standard/core/MARKER
26636 \  MARKER
26637 \ ( "<spaces>name" -- )
26638 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
26639 \ with the execution semantics defined below.
26640
26641 \ name Execution: ( -- )
26642 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
26643 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
26644 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
26645 \ not necessarily provided. No other contextual information such as numeric base is affected
26646 \
26647 : MARKER
26648 CREATE
26649 HI2LO
26650 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
26651 SUB #2,Y            \ 1 Y = LFA
26652 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
26653 ADD #4,&DP          \ 3 add 2 cells
26654 LO2HI
26655 DOES>
26656 HI2LO
26657 MOV @RSP+,IP        \ -- PFA
26658 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
26659 MOV @TOS,&INIDP     \       set DP value for RST_STATE
26660 MOV @PSP+,TOS       \ --
26661 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
26662 ENDCODE
26663 [THEN]
26664
26665 MARKER {RC5TOLCD}
26666
26667 [UNDEFINED] @ [IF]
26668 \ https://forth-standard.org/standard/core/Fetch
26669 \ @     c-addr -- char   fetch char from memory
26670 CODE @
26671 MOV @TOS,TOS
26672 MOV @IP+,PC
26673 ENDCODE
26674 [THEN]
26675
26676 [UNDEFINED] CONSTANT [IF]
26677 \ https://forth-standard.org/standard/core/CONSTANT
26678 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
26679 : CONSTANT 
26680 CREATE
26681 HI2LO
26682 MOV TOS,-2(W)           \   PFA = n
26683 MOV @PSP+,TOS
26684 MOV @RSP+,IP
26685 MOV @IP+,PC
26686 ENDCODE
26687 [THEN]
26688
26689 [UNDEFINED] STATE [IF]
26690 \ https://forth-standard.org/standard/core/STATE
26691 \ STATE   -- a-addr       holds compiler state
26692 STATEADR CONSTANT STATE
26693 [THEN]
26694
26695 [UNDEFINED] = [IF]
26696 \ https://forth-standard.org/standard/core/Equal
26697 \ =      x1 x2 -- flag         test x1=x2
26698 CODE =
26699 SUB @PSP+,TOS   \ 2
26700 0<> IF          \ 2
26701     AND #0,TOS  \ 1
26702     MOV @IP+,PC \ 4
26703 THEN
26704 XOR #-1,TOS     \ 1 flag Z = 1
26705 MOV @IP+,PC     \ 4
26706 ENDCODE
26707 [THEN]
26708
26709 [UNDEFINED] IF [IF]
26710 \ https://forth-standard.org/standard/core/IF
26711 \ IF       -- IFadr    initialize conditional forward branch
26712 CODE IF       \ immediate
26713 SUB #2,PSP              \
26714 MOV TOS,0(PSP)          \
26715 MOV &DP,TOS             \ -- HERE
26716 ADD #4,&DP            \           compile one word, reserve one word
26717 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
26718 ADD #2,TOS              \ -- HERE+2=IFadr
26719 MOV @IP+,PC
26720 ENDCODE IMMEDIATE
26721 [THEN]
26722
26723 [UNDEFINED] THEN [IF]
26724 \ https://forth-standard.org/standard/core/THEN
26725 \ THEN     IFadr --                resolve forward branch
26726 CODE THEN               \ immediate
26727 MOV &DP,0(TOS)          \ -- IFadr
26728 MOV @PSP+,TOS           \ --
26729 MOV @IP+,PC
26730 ENDCODE IMMEDIATE
26731 [THEN]
26732
26733 [UNDEFINED] ELSE [IF]
26734 \ https://forth-standard.org/standard/core/ELSE
26735 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
26736 CODE ELSE     \ immediate
26737 ADD #4,&DP              \ make room to compile two words
26738 MOV &DP,W               \ W=HERE+4
26739 MOV #BRAN,-4(W)
26740 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
26741 SUB #2,W                \ HERE+2
26742 MOV W,TOS               \ -- ELSEadr
26743 MOV @IP+,PC
26744 ENDCODE IMMEDIATE
26745 [THEN]
26746
26747 [UNDEFINED] DEFER [IF]
26748 \ https://forth-standard.org/standard/core/DEFER
26749 \ DEFER "<spaces>name"   --
26750 \ Skip leading space delimiters. Parse name delimited by a space.
26751 \ Create a definition for name with the execution semantics defined below.
26752
26753 \ name Execution:   --
26754 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
26755 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
26756 : DEFER
26757 CREATE
26758 HI2LO
26759 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
26760 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
26761 MOV @RSP+,IP
26762 MOV @IP+,PC
26763 ENDCODE
26764 [THEN]
26765
26766 [UNDEFINED] DEFER! [IF]
26767 \ https://forth-standard.org/standard/core/DEFERStore
26768 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
26769 CODE DEFER!             \ xt2 xt1 --
26770 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
26771 MOV @PSP+,TOS           \ --
26772 MOV @IP+,PC
26773 ENDCODE
26774 [THEN]
26775
26776 [UNDEFINED] IS [IF]
26777 \ https://forth-standard.org/standard/core/IS
26778 \ IS <name>        xt --
26779 \ used as is :
26780 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
26781 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
26782 \ or in a definition : ... ['] U. IS DISPLAY ...
26783 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
26784 \
26785 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
26786 : IS
26787 STATE @
26788 IF  POSTPONE ['] POSTPONE DEFER! 
26789 ELSE ' DEFER! 
26790 THEN
26791 ; IMMEDIATE
26792 [THEN]
26793
26794 [UNDEFINED] >BODY [IF]
26795 \ https://forth-standard.org/standard/core/toBODY
26796 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
26797 CODE >BODY
26798 ADD #4,TOS
26799 MOV @IP+,PC
26800 ENDCODE
26801 [THEN]
26802
26803 \ CODE 20uS           \ n --      8MHz version
26804 \ BEGIN               \ 4 + 16 ~ loop
26805 \     MOV #39,rDOCON   \ 39
26806 \     BEGIN           \ 4 ~ loop
26807 \         NOP
26808 \         SUB #1,rDOCON
26809 \     0=  UNTIL
26810 \     SUB #1,TOS      \ 1
26811 \ 0= UNTIL
26812 \ MOV #XDOCON,rDOCON  \ 2
26813 \ MOV @PSP+,TOS
26814 \ MOV @RSP+,IP        \
26815 \ ENDCODE
26816
26817 CODE 20_US                      \ n --      n * 20 us
26818 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
26819     BEGIN
26820         BIT #1,&LCD_TIM_CTL     \ 3
26821     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
26822     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
26823     SUB #1,TOS                  \ 1
26824 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
26825 MOV @PSP+,TOS                   \ 2
26826 MOV @IP+,PC                     \ 4
26827 ENDCODE
26828
26829 CODE TOP_LCD                    \ LCD Sample
26830 \                               \ if write : %xxxx_WWWW --
26831 \                               \ if read  : -- %0000_RRRR
26832     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
26833     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
26834 0= IF                           \ write LCD bits pattern
26835     AND.B #LCD_DB,TOS           \ 
26836     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
26837     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
26838     MOV @PSP+,TOS               \
26839     MOV @IP+,PC
26840 THEN                            \ read LCD bits pattern
26841     SUB #2,PSP
26842     MOV TOS,0(PSP)
26843     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
26844     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
26845     AND.B #LCD_DB,TOS           \
26846     MOV @IP+,PC
26847 ENDCODE
26848
26849 CODE LCD_WRC                    \ char --         Write Char
26850     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
26851 BW1 SUB #2,PSP                  \
26852     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
26853     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
26854     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
26855     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
26856 COLON                           \ high level word starts here 
26857     TOP_LCD 2 20_US             \ write high nibble first
26858     TOP_LCD 2 20_US 
26859 ;
26860
26861 CODE LCD_WRF                    \ func --         Write Fonction
26862     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
26863     GOTO BW1
26864 ENDCODE
26865
26866 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
26867 : LCD_HOME $02 LCD_WRF 100 20_us ;
26868
26869 \ [UNDEFINED] OR [IF]
26870
26871 \ \ https://forth-standard.org/standard/core/OR
26872 \ \ C OR     x1 x2 -- x3           logical OR
26873 \ CODE OR
26874 \ BIS @PSP+,TOS
26875 \ MOV @IP+,PC
26876 \ ENDCODE
26877
26878 \ [THEN]
26879
26880 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
26881 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
26882 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
26883 \ : LCD_FN_SET        $20 OR LCD_WrF ;
26884 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
26885 \ : LCD_GOTO          $80 OR LCD_WrF ;
26886
26887
26888 \ CODE LCD_RDS                    \ -- status       Read Status
26889 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
26890 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
26891 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
26892 \ COLON                           \ starts a FORTH word
26893 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
26894 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
26895 \ HI2LO                           \ switch from FORTH to assembler
26896 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
26897 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
26898 \     MOV @RSP+,IP                \ restore IP saved by COLON
26899 \     MOV @IP+,PC                 \
26900 \ ENDCODE
26901
26902 \ CODE LCD_RDC                    \ -- char         Read Char
26903 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
26904 \     GOTO BW1
26905 \ ENDCODE
26906
26907
26908 \ ******************************\
26909 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
26910 \ ******************************\
26911 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
26912 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
26913 BIT.B #SW2,&SW2_IN              \ test switch S2
26914 0= IF                           \ case of switch S2 pressed
26915     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
26916     U< IF
26917         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
26918     THEN
26919 ELSE
26920     BIT.B #SW1,&SW1_IN          \ test switch S1 input
26921     0= IF                       \ case of Switch S1 pressed
26922         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
26923         U>= IF                  \
26924            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
26925         THEN                    \
26926     THEN                        \
26927 THEN                            \
26928 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
26929 RET                             \ 5
26930 ENDASM
26931
26932 \ ******************************\
26933 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
26934 \ ******************************\
26935 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
26936 \ ******************************\
26937 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
26938 \                               \       SMclock = 8|16|24 MHz
26939 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
26940 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
26941 \                               \       SR(9)=new Toggle bit memory (ADD on)
26942 \ ******************************\
26943 \ RC5_FirstStartBitHalfCycle:   \
26944 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
26945 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
26946 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
26947 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
26948 \ [THEN]
26949 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
26950     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
26951 [THEN]
26952 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
26953     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
26954 [THEN]
26955 MOV #1778,X                     \ RC5_Period * 1us
26956 MOV #14,W                       \ count of loop
26957 BEGIN                           \
26958 \ ******************************\
26959 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
26960 \ ******************************\                   |
26961 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
26962 \ RC5_Compute_3/4_Period:       \                   |
26963     RRUM    #1,X                \ X=1/2 cycle       |
26964     MOV     X,Y                 \                   ^
26965     RRUM    #1,Y                \ Y=1/4
26966     ADD     X,Y                 \ Y=3/4 cycle
26967     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
26968     U>= UNTIL                   \ 2
26969 \ ******************************\
26970 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
26971 \ ******************************\
26972     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
26973     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
26974     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
26975     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
26976     SUB     #1,W                \ decrement count loop
26977 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
26978 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
26979 0<> WHILE                       \ ----> out of loop ----+
26980     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
26981     BEGIN                       \                       |
26982         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
26983         CMP Y,X                 \ 1                     |   cycle time out of bound ?
26984         U>= IF                  \ 2                 ^   |   yes:
26985         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
26986         GOTO BW1                \                   |   |      quit on truncated RC5 message
26987         THEN                    \                   |   |
26988         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
26989     0<> UNTIL                   \ 2                 |   |
26990 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
26991 \ ******************************\                       |
26992 \ RC5_SampleEndOf:              \ <---------------------+
26993 \ ******************************\
26994 BIC #$30,&RC5_TIM_CTL           \   stop timer
26995 \ ******************************\
26996 \ RC5_ComputeNewRC5word         \
26997 \ ******************************\
26998 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
26999 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
27000 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
27001 \ ******************************\
27002 \ RC5_ComputeC6bit              \
27003 \ ******************************\
27004 BIT     #BIT14,T                \ test /C6 bit in T
27005 0= IF   BIS #BIT6,X             \ set C6 bit in X
27006 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
27007 \ ******************************\
27008 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
27009 \ ******************************\
27010 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
27011 \ ******************************\
27012 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
27013 XOR     @RSP,T                  \ (new XOR old) Toggle bits
27014 BIT     #UF10,T                 \ repeated RC5_command ?
27015 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
27016 XOR #UF10,0(RSP)                \ 5 toggle bit memory
27017 \ ******************************\
27018 \ Display IR_RC5 code           \
27019 \ ******************************\
27020 SUB #8,PSP                      \ TOS -- x x x x TOS
27021 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
27022 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
27023 MOV #$10,&BASEADR               \                                               set hexadecimal base
27024 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
27025 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
27026 LO2HI                           \                                               switch from assembler to FORTH
27027     LCD_CLEAR                   \                                               set LCD cursor at home
27028     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
27029     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
27030     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
27031     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
27032 HI2LO                           \     --                                        switch from FORTH to assembler
27033 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
27034 MOV @PSP+,TOS                   \     -- TOS
27035 RET
27036 ENDASM
27037
27038 \ ******************************\
27039 ASM BACKGROUND                  \
27040 \ ******************************\
27041 BEGIN
27042 \     ...                         \ insert here your background task
27043 \     ...                         \
27044 \     ...                         \
27045     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
27046     BIS &LPM_MODE,SR            \
27047 \ ******************************\
27048 \ here start all interrupts     \
27049 \ ******************************\
27050 \ here return all interrupts    \
27051 \ ******************************\
27052 AGAIN                           \
27053 ENDASM                          \
27054 \ ******************************\
27055
27056 \ ------------------------------\
27057 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
27058 \ ------------------------------\
27059 \     ...                         \ init specific I/O sys as you want
27060 \     ...                         \ before executing default WARM
27061     MOV #WARM,X                 \ ['] WARM 
27062     ADD #4,X                    \ >BODY
27063     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
27064 ENDASM
27065 \ ------------------------------\
27066
27067 \ ------------------------------\
27068 CODE STOP                       \ stops multitasking, must to be used before downloading app
27069 \ ------------------------------\
27070 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
27071     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
27072     MOV X,-2(X)                 \ restore the default background: SLEEP
27073     MOV #WARM,X
27074     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
27075     BIC.B #RC5,&IR_IE           \ clear RC5_Int
27076     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
27077     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
27078     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
27079     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
27080     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
27081 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
27082 ECHO                            \
27083 ." RC5toLCD is removed,"
27084 ."  type START to restart"
27085  WARM                           \ performs reset to reset all interrupt vectors.    
27086 ;
27087 \ ------------------------------\
27088
27089 \ ------------------------------\
27090 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
27091 \ ------------------------------\
27092 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
27093 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
27094 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
27095 \                           --       \ID input divider \ 10 = /4
27096 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
27097 \                                 -  \TBCLR TimerB Clear
27098 \                                  - \TBIE
27099 \                                   -\TBIFG
27100 \ -------------------------------\
27101 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
27102 \                  --                 \CM Capture Mode
27103 \                    --               \CCIS
27104 \                       -             \SCS
27105 \                        --           \CLLD
27106 \                          -          \CAP
27107 \                            ---      \OUTMOD \ 011 = set/reset
27108 \                               -     \CCIE
27109 \                                 -   \CCI
27110 \                                  -  \OUT
27111 \                                   - \COV
27112 \                                    -\CCIFG
27113 \ -------------------------------\
27114 \ LCD_TIM_CCRx                   \
27115 \ -------------------------------\
27116 \ LCD_TIM_EX0                    \ 
27117 \ ------------------------------\
27118 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
27119 \ ------------------------------\
27120 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
27121 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
27122 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
27123     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
27124 [THEN]
27125 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
27126     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
27127 [THEN]
27128     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
27129 \ ------------------------------\
27130 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
27131 \ ------------------------------\
27132 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
27133     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
27134 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
27135 \ ------------------------------\
27136     BIS.B #LCDVo,&LCDVo_DIR     \
27137     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
27138 \ ------------------------------\
27139     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
27140     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
27141 \ ------------------------------\
27142     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
27143     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
27144 \ ******************************\
27145 \ init RC5_Int                  \
27146 \ ******************************\
27147     BIS.B #RC5,&IR_IE           \ enable RC5_Int
27148     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
27149     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
27150 \ ******************************\
27151 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
27152 \ ******************************\
27153 \              %01 0001 0100    \ TAxCTL
27154 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
27155 \                  --           \ ID        divided by 1
27156 \                    --         \ MC        MODE = up to TAxCCRn
27157 \                        -      \ TACLR     clear timer count
27158 \                         -     \ TAIE
27159 \                          -    \ TAIFG
27160 \ ------------------------------\
27161 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
27162 \ ------------------------------\
27163 \                        000    \ TAxEX0
27164 \                        ---    \ TAIDEX    pre divisor
27165 \ ------------------------------\
27166 \          %0000 0000 0000 0101 \ TAxCCR0
27167     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
27168 \ ------------------------------\
27169 \          %0000 0000 0001 0000 \ TAxCCTL0
27170 \                   -           \ CAP capture/compare mode = compare
27171 \                        -      \ CCIEn
27172 \                             - \ CCIFGn
27173     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
27174 \ ------------------------------\
27175     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
27176 \ ------------------------------\
27177 \ define LPM mode for ACCEPT    \
27178 \ ------------------------------\
27179 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
27180 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
27181 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
27182 \ ------------------------------\
27183 \ activate I/O                  \
27184 \ ------------------------------\
27185 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
27186 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
27187 \ ------------------------------\
27188 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
27189 \ ------------------------------\
27190 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
27191 \ CMP #2,Y                        \ Power_ON event
27192 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
27193 CMP #4,Y                        \
27194 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
27195 \ CMP #6,Y                        \
27196 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
27197 \ CMP #$0A,Y                      \
27198 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
27199 \ CMP #$16,Y                      \
27200 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
27201 \ ------------------------------\
27202 COLON                           \
27203 \ ------------------------------\
27204 \ Init LCD 2x20                 \
27205 \ ------------------------------\
27206     #1000 20_US                 \ 1- wait 20 ms
27207     %011 TOP_LCD                \ 2- send DB5=DB4=1
27208     #205 20_US                  \ 3- wait 4,1 ms
27209     %011 TOP_LCD                \ 4- send again DB5=DB4=1
27210     #5 20_US                    \ 5- wait 0,1 ms
27211     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
27212     #2 20_US                    \    wait 40 us = LCD cycle
27213     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
27214     #2 20_US                    \    wait 40 us = LCD cycle
27215     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
27216     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
27217     LCD_CLEAR                   \ 10- "LCD_Clear"
27218     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
27219     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
27220     LCD_CLEAR                   \ 10- "LCD_Clear"
27221     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
27222     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
27223     CR ." I love you"           \ display message on LCD
27224     ['] CR >BODY IS CR          \ CR executes its default value
27225     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
27226     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
27227     PWR_STATE ABORT             \ init DP and continues with ABORT
27228 ;                               \
27229 \ ------------------------------\
27230
27231 \ ------------------------------\
27232 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
27233 \ ------------------------------\
27234 MOV #SLEEP,X                    \ replace default background process SLEEP
27235 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
27236 MOV #WARM,X                     \ replace default WARM
27237 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
27238 MOV X,PC                        \ then execute new WARM
27239 ENDCODE 
27240 \ ------------------------------\
27241
27242 ECHO
27243             ; downloading RC5toLCD.4th is done
27244 RST_HERE    ; this app is protected against <reset>
27245
27246
27247 RST_STATE
27248
27249 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
27250
27251 [UNDEFINED] MARKER [IF]
27252 \  https://forth-standard.org/standard/core/MARKER
27253 \  MARKER
27254 \ ( "<spaces>name" -- )
27255 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
27256 \ with the execution semantics defined below.
27257
27258 \ name Execution: ( -- )
27259 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
27260 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
27261 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
27262 \ not necessarily provided. No other contextual information such as numeric base is affected
27263 \
27264 : MARKER
27265 CREATE
27266 HI2LO
27267 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
27268 SUB #2,Y            \ 1 Y = LFA
27269 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
27270 ADD #4,&DP          \ 3 add 2 cells
27271 LO2HI
27272 DOES>
27273 HI2LO
27274 MOV @RSP+,IP        \ -- PFA
27275 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
27276 MOV @TOS,&INIDP     \       set DP value for RST_STATE
27277 MOV @PSP+,TOS       \ --
27278 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
27279 ENDCODE
27280 [THEN]
27281
27282 MARKER {RC5TOLCD}
27283
27284 [UNDEFINED] @ [IF]
27285 \ https://forth-standard.org/standard/core/Fetch
27286 \ @     c-addr -- char   fetch char from memory
27287 CODE @
27288 MOV @TOS,TOS
27289 MOV @IP+,PC
27290 ENDCODE
27291 [THEN]
27292
27293 [UNDEFINED] CONSTANT [IF]
27294 \ https://forth-standard.org/standard/core/CONSTANT
27295 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
27296 : CONSTANT 
27297 CREATE
27298 HI2LO
27299 MOV TOS,-2(W)           \   PFA = n
27300 MOV @PSP+,TOS
27301 MOV @RSP+,IP
27302 MOV @IP+,PC
27303 ENDCODE
27304 [THEN]
27305
27306 [UNDEFINED] STATE [IF]
27307 \ https://forth-standard.org/standard/core/STATE
27308 \ STATE   -- a-addr       holds compiler state
27309 STATEADR CONSTANT STATE
27310 [THEN]
27311
27312 [UNDEFINED] = [IF]
27313 \ https://forth-standard.org/standard/core/Equal
27314 \ =      x1 x2 -- flag         test x1=x2
27315 CODE =
27316 SUB @PSP+,TOS   \ 2
27317 0<> IF          \ 2
27318     AND #0,TOS  \ 1
27319     MOV @IP+,PC \ 4
27320 THEN
27321 XOR #-1,TOS     \ 1 flag Z = 1
27322 MOV @IP+,PC     \ 4
27323 ENDCODE
27324 [THEN]
27325
27326 [UNDEFINED] IF [IF]
27327 \ https://forth-standard.org/standard/core/IF
27328 \ IF       -- IFadr    initialize conditional forward branch
27329 CODE IF       \ immediate
27330 SUB #2,PSP              \
27331 MOV TOS,0(PSP)          \
27332 MOV &DP,TOS             \ -- HERE
27333 ADD #4,&DP            \           compile one word, reserve one word
27334 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
27335 ADD #2,TOS              \ -- HERE+2=IFadr
27336 MOV @IP+,PC
27337 ENDCODE IMMEDIATE
27338 [THEN]
27339
27340 [UNDEFINED] THEN [IF]
27341 \ https://forth-standard.org/standard/core/THEN
27342 \ THEN     IFadr --                resolve forward branch
27343 CODE THEN               \ immediate
27344 MOV &DP,0(TOS)          \ -- IFadr
27345 MOV @PSP+,TOS           \ --
27346 MOV @IP+,PC
27347 ENDCODE IMMEDIATE
27348 [THEN]
27349
27350 [UNDEFINED] ELSE [IF]
27351 \ https://forth-standard.org/standard/core/ELSE
27352 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
27353 CODE ELSE     \ immediate
27354 ADD #4,&DP              \ make room to compile two words
27355 MOV &DP,W               \ W=HERE+4
27356 MOV #BRAN,-4(W)
27357 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
27358 SUB #2,W                \ HERE+2
27359 MOV W,TOS               \ -- ELSEadr
27360 MOV @IP+,PC
27361 ENDCODE IMMEDIATE
27362 [THEN]
27363
27364 [UNDEFINED] DEFER [IF]
27365 \ https://forth-standard.org/standard/core/DEFER
27366 \ DEFER "<spaces>name"   --
27367 \ Skip leading space delimiters. Parse name delimited by a space.
27368 \ Create a definition for name with the execution semantics defined below.
27369
27370 \ name Execution:   --
27371 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
27372 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
27373 : DEFER
27374 CREATE
27375 HI2LO
27376 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
27377 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
27378 MOV @RSP+,IP
27379 MOV @IP+,PC
27380 ENDCODE
27381 [THEN]
27382
27383 [UNDEFINED] DEFER! [IF]
27384 \ https://forth-standard.org/standard/core/DEFERStore
27385 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
27386 CODE DEFER!             \ xt2 xt1 --
27387 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
27388 MOV @PSP+,TOS           \ --
27389 MOV @IP+,PC
27390 ENDCODE
27391 [THEN]
27392
27393 [UNDEFINED] IS [IF]
27394 \ https://forth-standard.org/standard/core/IS
27395 \ IS <name>        xt --
27396 \ used as is :
27397 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
27398 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
27399 \ or in a definition : ... ['] U. IS DISPLAY ...
27400 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
27401 \
27402 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
27403 : IS
27404 STATE @
27405 IF  POSTPONE ['] POSTPONE DEFER! 
27406 ELSE ' DEFER! 
27407 THEN
27408 ; IMMEDIATE
27409 [THEN]
27410
27411 [UNDEFINED] >BODY [IF]
27412 \ https://forth-standard.org/standard/core/toBODY
27413 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
27414 CODE >BODY
27415 ADD #4,TOS
27416 MOV @IP+,PC
27417 ENDCODE
27418 [THEN]
27419
27420 \ CODE 20uS           \ n --      8MHz version
27421 \ BEGIN               \ 4 + 16 ~ loop
27422 \     MOV #39,rDOCON   \ 39
27423 \     BEGIN           \ 4 ~ loop
27424 \         NOP
27425 \         SUB #1,rDOCON
27426 \     0=  UNTIL
27427 \     SUB #1,TOS      \ 1
27428 \ 0= UNTIL
27429 \ MOV #XDOCON,rDOCON  \ 2
27430 \ MOV @PSP+,TOS
27431 \ MOV @RSP+,IP        \
27432 \ ENDCODE
27433
27434 CODE 20_US                      \ n --      n * 20 us
27435 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
27436     BEGIN
27437         BIT #1,&LCD_TIM_CTL     \ 3
27438     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
27439     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
27440     SUB #1,TOS                  \ 1
27441 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
27442 MOV @PSP+,TOS                   \ 2
27443 MOV @IP+,PC                     \ 4
27444 ENDCODE
27445
27446 CODE TOP_LCD                    \ LCD Sample
27447 \                               \ if write : %xxxx_WWWW --
27448 \                               \ if read  : -- %0000_RRRR
27449     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
27450     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
27451 0= IF                           \ write LCD bits pattern
27452     AND.B #LCD_DB,TOS           \ 
27453     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
27454     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
27455     MOV @PSP+,TOS               \
27456     MOV @IP+,PC
27457 THEN                            \ read LCD bits pattern
27458     SUB #2,PSP
27459     MOV TOS,0(PSP)
27460     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
27461     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
27462     AND.B #LCD_DB,TOS           \
27463     MOV @IP+,PC
27464 ENDCODE
27465
27466 CODE LCD_WRC                    \ char --         Write Char
27467     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
27468 BW1 SUB #2,PSP                  \
27469     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
27470     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
27471     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
27472     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
27473 COLON                           \ high level word starts here 
27474     TOP_LCD 2 20_US             \ write high nibble first
27475     TOP_LCD 2 20_US 
27476 ;
27477
27478 CODE LCD_WRF                    \ func --         Write Fonction
27479     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
27480     GOTO BW1
27481 ENDCODE
27482
27483 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
27484 : LCD_HOME $02 LCD_WRF 100 20_us ;
27485
27486 \ [UNDEFINED] OR [IF]
27487
27488 \ \ https://forth-standard.org/standard/core/OR
27489 \ \ C OR     x1 x2 -- x3           logical OR
27490 \ CODE OR
27491 \ BIS @PSP+,TOS
27492 \ MOV @IP+,PC
27493 \ ENDCODE
27494
27495 \ [THEN]
27496
27497 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
27498 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
27499 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
27500 \ : LCD_FN_SET        $20 OR LCD_WrF ;
27501 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
27502 \ : LCD_GOTO          $80 OR LCD_WrF ;
27503
27504
27505 \ CODE LCD_RDS                    \ -- status       Read Status
27506 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
27507 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
27508 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
27509 \ COLON                           \ starts a FORTH word
27510 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
27511 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
27512 \ HI2LO                           \ switch from FORTH to assembler
27513 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
27514 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
27515 \     MOV @RSP+,IP                \ restore IP saved by COLON
27516 \     MOV @IP+,PC                 \
27517 \ ENDCODE
27518
27519 \ CODE LCD_RDC                    \ -- char         Read Char
27520 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
27521 \     GOTO BW1
27522 \ ENDCODE
27523
27524
27525 \ ******************************\
27526 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
27527 \ ******************************\
27528 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
27529 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
27530 BIT.B #SW2,&SW2_IN              \ test switch S2
27531 0= IF                           \ case of switch S2 pressed
27532     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
27533     U< IF
27534         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
27535     THEN
27536 ELSE
27537     BIT.B #SW1,&SW1_IN          \ test switch S1 input
27538     0= IF                       \ case of Switch S1 pressed
27539         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
27540         U>= IF                  \
27541            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
27542         THEN                    \
27543     THEN                        \
27544 THEN                            \
27545 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
27546 RET                             \ 5
27547 ENDASM
27548
27549 \ ******************************\
27550 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
27551 \ ******************************\
27552 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
27553 \ ******************************\
27554 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
27555 \                               \       SMclock = 8|16|24 MHz
27556 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
27557 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
27558 \                               \       SR(9)=new Toggle bit memory (ADD on)
27559 \ ******************************\
27560 \ RC5_FirstStartBitHalfCycle:   \
27561 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
27562 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
27563 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
27564 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
27565 \ [THEN]
27566 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
27567     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
27568 [THEN]
27569 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
27570     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
27571 [THEN]
27572 MOV #1778,X                     \ RC5_Period * 1us
27573 MOV #14,W                       \ count of loop
27574 BEGIN                           \
27575 \ ******************************\
27576 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
27577 \ ******************************\                   |
27578 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
27579 \ RC5_Compute_3/4_Period:       \                   |
27580     RRUM    #1,X                \ X=1/2 cycle       |
27581     MOV     X,Y                 \                   ^
27582     RRUM    #1,Y                \ Y=1/4
27583     ADD     X,Y                 \ Y=3/4 cycle
27584     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
27585     U>= UNTIL                   \ 2
27586 \ ******************************\
27587 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
27588 \ ******************************\
27589     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
27590     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
27591     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
27592     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
27593     SUB     #1,W                \ decrement count loop
27594 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
27595 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
27596 0<> WHILE                       \ ----> out of loop ----+
27597     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
27598     BEGIN                       \                       |
27599         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
27600         CMP Y,X                 \ 1                     |   cycle time out of bound ?
27601         U>= IF                  \ 2                 ^   |   yes:
27602         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
27603         GOTO BW1                \                   |   |      quit on truncated RC5 message
27604         THEN                    \                   |   |
27605         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
27606     0<> UNTIL                   \ 2                 |   |
27607 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
27608 \ ******************************\                       |
27609 \ RC5_SampleEndOf:              \ <---------------------+
27610 \ ******************************\
27611 BIC #$30,&RC5_TIM_CTL           \   stop timer
27612 \ ******************************\
27613 \ RC5_ComputeNewRC5word         \
27614 \ ******************************\
27615 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
27616 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
27617 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
27618 \ ******************************\
27619 \ RC5_ComputeC6bit              \
27620 \ ******************************\
27621 BIT     #BIT14,T                \ test /C6 bit in T
27622 0= IF   BIS #BIT6,X             \ set C6 bit in X
27623 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
27624 \ ******************************\
27625 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
27626 \ ******************************\
27627 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
27628 \ ******************************\
27629 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
27630 XOR     @RSP,T                  \ (new XOR old) Toggle bits
27631 BIT     #UF10,T                 \ repeated RC5_command ?
27632 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
27633 XOR #UF10,0(RSP)                \ 5 toggle bit memory
27634 \ ******************************\
27635 \ Display IR_RC5 code           \
27636 \ ******************************\
27637 SUB #8,PSP                      \ TOS -- x x x x TOS
27638 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
27639 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
27640 MOV #$10,&BASEADR               \                                               set hexadecimal base
27641 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
27642 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
27643 LO2HI                           \                                               switch from assembler to FORTH
27644     LCD_CLEAR                   \                                               set LCD cursor at home
27645     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
27646     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
27647     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
27648     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
27649 HI2LO                           \     --                                        switch from FORTH to assembler
27650 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
27651 MOV @PSP+,TOS                   \     -- TOS
27652 RET
27653 ENDASM
27654
27655 \ ******************************\
27656 ASM BACKGROUND                  \
27657 \ ******************************\
27658 BEGIN
27659 \     ...                         \ insert here your background task
27660 \     ...                         \
27661 \     ...                         \
27662     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
27663     BIS &LPM_MODE,SR            \
27664 \ ******************************\
27665 \ here start all interrupts     \
27666 \ ******************************\
27667 \ here return all interrupts    \
27668 \ ******************************\
27669 AGAIN                           \
27670 ENDASM                          \
27671 \ ******************************\
27672
27673 \ ------------------------------\
27674 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
27675 \ ------------------------------\
27676 \     ...                         \ init specific I/O sys as you want
27677 \     ...                         \ before executing default WARM
27678     MOV #WARM,X                 \ ['] WARM 
27679     ADD #4,X                    \ >BODY
27680     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
27681 ENDASM
27682 \ ------------------------------\
27683
27684 \ ------------------------------\
27685 CODE STOP                       \ stops multitasking, must to be used before downloading app
27686 \ ------------------------------\
27687 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
27688     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
27689     MOV X,-2(X)                 \ restore the default background: SLEEP
27690     MOV #WARM,X
27691     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
27692     BIC.B #RC5,&IR_IE           \ clear RC5_Int
27693     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
27694     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
27695     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
27696     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
27697     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
27698 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
27699 ECHO                            \
27700 ." RC5toLCD is removed,"
27701 ."  type START to restart"
27702  WARM                           \ performs reset to reset all interrupt vectors.    
27703 ;
27704 \ ------------------------------\
27705
27706 \ ------------------------------\
27707 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
27708 \ ------------------------------\
27709 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
27710 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
27711 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
27712 \                           --       \ID input divider \ 10 = /4
27713 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
27714 \                                 -  \TBCLR TimerB Clear
27715 \                                  - \TBIE
27716 \                                   -\TBIFG
27717 \ -------------------------------\
27718 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
27719 \                  --                 \CM Capture Mode
27720 \                    --               \CCIS
27721 \                       -             \SCS
27722 \                        --           \CLLD
27723 \                          -          \CAP
27724 \                            ---      \OUTMOD \ 011 = set/reset
27725 \                               -     \CCIE
27726 \                                 -   \CCI
27727 \                                  -  \OUT
27728 \                                   - \COV
27729 \                                    -\CCIFG
27730 \ -------------------------------\
27731 \ LCD_TIM_CCRx                   \
27732 \ -------------------------------\
27733 \ LCD_TIM_EX0                    \ 
27734 \ ------------------------------\
27735 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
27736 \ ------------------------------\
27737 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
27738 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
27739 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
27740     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
27741 [THEN]
27742 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
27743     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
27744 [THEN]
27745     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
27746 \ ------------------------------\
27747 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
27748 \ ------------------------------\
27749 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
27750     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
27751 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
27752 \ ------------------------------\
27753     BIS.B #LCDVo,&LCDVo_DIR     \
27754     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
27755 \ ------------------------------\
27756     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
27757     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
27758 \ ------------------------------\
27759     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
27760     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
27761 \ ******************************\
27762 \ init RC5_Int                  \
27763 \ ******************************\
27764     BIS.B #RC5,&IR_IE           \ enable RC5_Int
27765     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
27766     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
27767 \ ******************************\
27768 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
27769 \ ******************************\
27770 \              %01 0001 0100    \ TAxCTL
27771 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
27772 \                  --           \ ID        divided by 1
27773 \                    --         \ MC        MODE = up to TAxCCRn
27774 \                        -      \ TACLR     clear timer count
27775 \                         -     \ TAIE
27776 \                          -    \ TAIFG
27777 \ ------------------------------\
27778 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
27779 \ ------------------------------\
27780 \                        000    \ TAxEX0
27781 \                        ---    \ TAIDEX    pre divisor
27782 \ ------------------------------\
27783 \          %0000 0000 0000 0101 \ TAxCCR0
27784     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
27785 \ ------------------------------\
27786 \          %0000 0000 0001 0000 \ TAxCCTL0
27787 \                   -           \ CAP capture/compare mode = compare
27788 \                        -      \ CCIEn
27789 \                             - \ CCIFGn
27790     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
27791 \ ------------------------------\
27792     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
27793 \ ------------------------------\
27794 \ define LPM mode for ACCEPT    \
27795 \ ------------------------------\
27796 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
27797 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
27798 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
27799 \ ------------------------------\
27800 \ activate I/O                  \
27801 \ ------------------------------\
27802 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
27803 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
27804 \ ------------------------------\
27805 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
27806 \ ------------------------------\
27807 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
27808 \ CMP #2,Y                        \ Power_ON event
27809 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
27810 CMP #4,Y                        \
27811 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
27812 \ CMP #6,Y                        \
27813 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
27814 \ CMP #$0A,Y                      \
27815 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
27816 \ CMP #$16,Y                      \
27817 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
27818 \ ------------------------------\
27819 COLON                           \
27820 \ ------------------------------\
27821 \ Init LCD 2x20                 \
27822 \ ------------------------------\
27823     #1000 20_US                 \ 1- wait 20 ms
27824     %011 TOP_LCD                \ 2- send DB5=DB4=1
27825     #205 20_US                  \ 3- wait 4,1 ms
27826     %011 TOP_LCD                \ 4- send again DB5=DB4=1
27827     #5 20_US                    \ 5- wait 0,1 ms
27828     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
27829     #2 20_US                    \    wait 40 us = LCD cycle
27830     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
27831     #2 20_US                    \    wait 40 us = LCD cycle
27832     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
27833     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
27834     LCD_CLEAR                   \ 10- "LCD_Clear"
27835     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
27836     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
27837     LCD_CLEAR                   \ 10- "LCD_Clear"
27838     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
27839     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
27840     CR ." I love you"           \ display message on LCD
27841     ['] CR >BODY IS CR          \ CR executes its default value
27842     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
27843     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
27844     PWR_STATE ABORT             \ init DP and continues with ABORT
27845 ;                               \
27846 \ ------------------------------\
27847
27848 \ ------------------------------\
27849 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
27850 \ ------------------------------\
27851 MOV #SLEEP,X                    \ replace default background process SLEEP
27852 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
27853 MOV #WARM,X                     \ replace default WARM
27854 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
27855 MOV X,PC                        \ then execute new WARM
27856 ENDCODE 
27857 \ ------------------------------\
27858
27859 ECHO
27860             ; downloading RC5toLCD.4th is done
27861 RST_HERE    ; this app is protected against <reset>
27862
27863
27864 RST_STATE
27865
27866 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
27867
27868 [UNDEFINED] MARKER [IF]
27869 \  https://forth-standard.org/standard/core/MARKER
27870 \  MARKER
27871 \ ( "<spaces>name" -- )
27872 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
27873 \ with the execution semantics defined below.
27874
27875 \ name Execution: ( -- )
27876 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
27877 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
27878 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
27879 \ not necessarily provided. No other contextual information such as numeric base is affected
27880 \
27881 : MARKER
27882 CREATE
27883 HI2LO
27884 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
27885 SUB #2,Y            \ 1 Y = LFA
27886 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
27887 ADD #4,&DP          \ 3 add 2 cells
27888 LO2HI
27889 DOES>
27890 HI2LO
27891 MOV @RSP+,IP        \ -- PFA
27892 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
27893 MOV @TOS,&INIDP     \       set DP value for RST_STATE
27894 MOV @PSP+,TOS       \ --
27895 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
27896 ENDCODE
27897 [THEN]
27898
27899 MARKER {RC5TOLCD}
27900
27901 [UNDEFINED] @ [IF]
27902 \ https://forth-standard.org/standard/core/Fetch
27903 \ @     c-addr -- char   fetch char from memory
27904 CODE @
27905 MOV @TOS,TOS
27906 MOV @IP+,PC
27907 ENDCODE
27908 [THEN]
27909
27910 [UNDEFINED] CONSTANT [IF]
27911 \ https://forth-standard.org/standard/core/CONSTANT
27912 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
27913 : CONSTANT 
27914 CREATE
27915 HI2LO
27916 MOV TOS,-2(W)           \   PFA = n
27917 MOV @PSP+,TOS
27918 MOV @RSP+,IP
27919 MOV @IP+,PC
27920 ENDCODE
27921 [THEN]
27922
27923 [UNDEFINED] STATE [IF]
27924 \ https://forth-standard.org/standard/core/STATE
27925 \ STATE   -- a-addr       holds compiler state
27926 STATEADR CONSTANT STATE
27927 [THEN]
27928
27929 [UNDEFINED] = [IF]
27930 \ https://forth-standard.org/standard/core/Equal
27931 \ =      x1 x2 -- flag         test x1=x2
27932 CODE =
27933 SUB @PSP+,TOS   \ 2
27934 0<> IF          \ 2
27935     AND #0,TOS  \ 1
27936     MOV @IP+,PC \ 4
27937 THEN
27938 XOR #-1,TOS     \ 1 flag Z = 1
27939 MOV @IP+,PC     \ 4
27940 ENDCODE
27941 [THEN]
27942
27943 [UNDEFINED] IF [IF]
27944 \ https://forth-standard.org/standard/core/IF
27945 \ IF       -- IFadr    initialize conditional forward branch
27946 CODE IF       \ immediate
27947 SUB #2,PSP              \
27948 MOV TOS,0(PSP)          \
27949 MOV &DP,TOS             \ -- HERE
27950 ADD #4,&DP            \           compile one word, reserve one word
27951 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
27952 ADD #2,TOS              \ -- HERE+2=IFadr
27953 MOV @IP+,PC
27954 ENDCODE IMMEDIATE
27955 [THEN]
27956
27957 [UNDEFINED] THEN [IF]
27958 \ https://forth-standard.org/standard/core/THEN
27959 \ THEN     IFadr --                resolve forward branch
27960 CODE THEN               \ immediate
27961 MOV &DP,0(TOS)          \ -- IFadr
27962 MOV @PSP+,TOS           \ --
27963 MOV @IP+,PC
27964 ENDCODE IMMEDIATE
27965 [THEN]
27966
27967 [UNDEFINED] ELSE [IF]
27968 \ https://forth-standard.org/standard/core/ELSE
27969 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
27970 CODE ELSE     \ immediate
27971 ADD #4,&DP              \ make room to compile two words
27972 MOV &DP,W               \ W=HERE+4
27973 MOV #BRAN,-4(W)
27974 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
27975 SUB #2,W                \ HERE+2
27976 MOV W,TOS               \ -- ELSEadr
27977 MOV @IP+,PC
27978 ENDCODE IMMEDIATE
27979 [THEN]
27980
27981 [UNDEFINED] DEFER [IF]
27982 \ https://forth-standard.org/standard/core/DEFER
27983 \ DEFER "<spaces>name"   --
27984 \ Skip leading space delimiters. Parse name delimited by a space.
27985 \ Create a definition for name with the execution semantics defined below.
27986
27987 \ name Execution:   --
27988 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
27989 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
27990 : DEFER
27991 CREATE
27992 HI2LO
27993 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
27994 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
27995 MOV @RSP+,IP
27996 MOV @IP+,PC
27997 ENDCODE
27998 [THEN]
27999
28000 [UNDEFINED] DEFER! [IF]
28001 \ https://forth-standard.org/standard/core/DEFERStore
28002 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
28003 CODE DEFER!             \ xt2 xt1 --
28004 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
28005 MOV @PSP+,TOS           \ --
28006 MOV @IP+,PC
28007 ENDCODE
28008 [THEN]
28009
28010 [UNDEFINED] IS [IF]
28011 \ https://forth-standard.org/standard/core/IS
28012 \ IS <name>        xt --
28013 \ used as is :
28014 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
28015 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
28016 \ or in a definition : ... ['] U. IS DISPLAY ...
28017 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
28018 \
28019 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
28020 : IS
28021 STATE @
28022 IF  POSTPONE ['] POSTPONE DEFER! 
28023 ELSE ' DEFER! 
28024 THEN
28025 ; IMMEDIATE
28026 [THEN]
28027
28028 [UNDEFINED] >BODY [IF]
28029 \ https://forth-standard.org/standard/core/toBODY
28030 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
28031 CODE >BODY
28032 ADD #4,TOS
28033 MOV @IP+,PC
28034 ENDCODE
28035 [THEN]
28036
28037 \ CODE 20uS           \ n --      8MHz version
28038 \ BEGIN               \ 4 + 16 ~ loop
28039 \     MOV #39,rDOCON   \ 39
28040 \     BEGIN           \ 4 ~ loop
28041 \         NOP
28042 \         SUB #1,rDOCON
28043 \     0=  UNTIL
28044 \     SUB #1,TOS      \ 1
28045 \ 0= UNTIL
28046 \ MOV #XDOCON,rDOCON  \ 2
28047 \ MOV @PSP+,TOS
28048 \ MOV @RSP+,IP        \
28049 \ ENDCODE
28050
28051 CODE 20_US                      \ n --      n * 20 us
28052 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
28053     BEGIN
28054         BIT #1,&LCD_TIM_CTL     \ 3
28055     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
28056     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
28057     SUB #1,TOS                  \ 1
28058 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
28059 MOV @PSP+,TOS                   \ 2
28060 MOV @IP+,PC                     \ 4
28061 ENDCODE
28062
28063 CODE TOP_LCD                    \ LCD Sample
28064 \                               \ if write : %xxxx_WWWW --
28065 \                               \ if read  : -- %0000_RRRR
28066     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
28067     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
28068 0= IF                           \ write LCD bits pattern
28069     AND.B #LCD_DB,TOS           \ 
28070     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
28071     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
28072     MOV @PSP+,TOS               \
28073     MOV @IP+,PC
28074 THEN                            \ read LCD bits pattern
28075     SUB #2,PSP
28076     MOV TOS,0(PSP)
28077     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
28078     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
28079     AND.B #LCD_DB,TOS           \
28080     MOV @IP+,PC
28081 ENDCODE
28082
28083 CODE LCD_WRC                    \ char --         Write Char
28084     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
28085 BW1 SUB #2,PSP                  \
28086     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
28087     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
28088     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
28089     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
28090 COLON                           \ high level word starts here 
28091     TOP_LCD 2 20_US             \ write high nibble first
28092     TOP_LCD 2 20_US 
28093 ;
28094
28095 CODE LCD_WRF                    \ func --         Write Fonction
28096     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
28097     GOTO BW1
28098 ENDCODE
28099
28100 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
28101 : LCD_HOME $02 LCD_WRF 100 20_us ;
28102
28103 \ [UNDEFINED] OR [IF]
28104
28105 \ \ https://forth-standard.org/standard/core/OR
28106 \ \ C OR     x1 x2 -- x3           logical OR
28107 \ CODE OR
28108 \ BIS @PSP+,TOS
28109 \ MOV @IP+,PC
28110 \ ENDCODE
28111
28112 \ [THEN]
28113
28114 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
28115 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
28116 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
28117 \ : LCD_FN_SET        $20 OR LCD_WrF ;
28118 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
28119 \ : LCD_GOTO          $80 OR LCD_WrF ;
28120
28121
28122 \ CODE LCD_RDS                    \ -- status       Read Status
28123 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
28124 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
28125 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
28126 \ COLON                           \ starts a FORTH word
28127 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
28128 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
28129 \ HI2LO                           \ switch from FORTH to assembler
28130 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
28131 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
28132 \     MOV @RSP+,IP                \ restore IP saved by COLON
28133 \     MOV @IP+,PC                 \
28134 \ ENDCODE
28135
28136 \ CODE LCD_RDC                    \ -- char         Read Char
28137 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
28138 \     GOTO BW1
28139 \ ENDCODE
28140
28141
28142 \ ******************************\
28143 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
28144 \ ******************************\
28145 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
28146 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
28147 BIT.B #SW2,&SW2_IN              \ test switch S2
28148 0= IF                           \ case of switch S2 pressed
28149     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
28150     U< IF
28151         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
28152     THEN
28153 ELSE
28154     BIT.B #SW1,&SW1_IN          \ test switch S1 input
28155     0= IF                       \ case of Switch S1 pressed
28156         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
28157         U>= IF                  \
28158            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
28159         THEN                    \
28160     THEN                        \
28161 THEN                            \
28162 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
28163 RET                             \ 5
28164 ENDASM
28165
28166 \ ******************************\
28167 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
28168 \ ******************************\
28169 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
28170 \ ******************************\
28171 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
28172 \                               \       SMclock = 8|16|24 MHz
28173 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
28174 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
28175 \                               \       SR(9)=new Toggle bit memory (ADD on)
28176 \ ******************************\
28177 \ RC5_FirstStartBitHalfCycle:   \
28178 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
28179 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
28180 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
28181 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
28182 \ [THEN]
28183 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
28184     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
28185 [THEN]
28186 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
28187     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
28188 [THEN]
28189 MOV #1778,X                     \ RC5_Period * 1us
28190 MOV #14,W                       \ count of loop
28191 BEGIN                           \
28192 \ ******************************\
28193 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
28194 \ ******************************\                   |
28195 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
28196 \ RC5_Compute_3/4_Period:       \                   |
28197     RRUM    #1,X                \ X=1/2 cycle       |
28198     MOV     X,Y                 \                   ^
28199     RRUM    #1,Y                \ Y=1/4
28200     ADD     X,Y                 \ Y=3/4 cycle
28201     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
28202     U>= UNTIL                   \ 2
28203 \ ******************************\
28204 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
28205 \ ******************************\
28206     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
28207     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
28208     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
28209     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
28210     SUB     #1,W                \ decrement count loop
28211 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
28212 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
28213 0<> WHILE                       \ ----> out of loop ----+
28214     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
28215     BEGIN                       \                       |
28216         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
28217         CMP Y,X                 \ 1                     |   cycle time out of bound ?
28218         U>= IF                  \ 2                 ^   |   yes:
28219         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
28220         GOTO BW1                \                   |   |      quit on truncated RC5 message
28221         THEN                    \                   |   |
28222         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
28223     0<> UNTIL                   \ 2                 |   |
28224 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
28225 \ ******************************\                       |
28226 \ RC5_SampleEndOf:              \ <---------------------+
28227 \ ******************************\
28228 BIC #$30,&RC5_TIM_CTL           \   stop timer
28229 \ ******************************\
28230 \ RC5_ComputeNewRC5word         \
28231 \ ******************************\
28232 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
28233 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
28234 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
28235 \ ******************************\
28236 \ RC5_ComputeC6bit              \
28237 \ ******************************\
28238 BIT     #BIT14,T                \ test /C6 bit in T
28239 0= IF   BIS #BIT6,X             \ set C6 bit in X
28240 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
28241 \ ******************************\
28242 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
28243 \ ******************************\
28244 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
28245 \ ******************************\
28246 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
28247 XOR     @RSP,T                  \ (new XOR old) Toggle bits
28248 BIT     #UF10,T                 \ repeated RC5_command ?
28249 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
28250 XOR #UF10,0(RSP)                \ 5 toggle bit memory
28251 \ ******************************\
28252 \ Display IR_RC5 code           \
28253 \ ******************************\
28254 SUB #8,PSP                      \ TOS -- x x x x TOS
28255 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
28256 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
28257 MOV #$10,&BASEADR               \                                               set hexadecimal base
28258 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
28259 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
28260 LO2HI                           \                                               switch from assembler to FORTH
28261     LCD_CLEAR                   \                                               set LCD cursor at home
28262     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
28263     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
28264     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
28265     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
28266 HI2LO                           \     --                                        switch from FORTH to assembler
28267 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
28268 MOV @PSP+,TOS                   \     -- TOS
28269 RET
28270 ENDASM
28271
28272 \ ******************************\
28273 ASM BACKGROUND                  \
28274 \ ******************************\
28275 BEGIN
28276 \     ...                         \ insert here your background task
28277 \     ...                         \
28278 \     ...                         \
28279     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
28280     BIS &LPM_MODE,SR            \
28281 \ ******************************\
28282 \ here start all interrupts     \
28283 \ ******************************\
28284 \ here return all interrupts    \
28285 \ ******************************\
28286 AGAIN                           \
28287 ENDASM                          \
28288 \ ******************************\
28289
28290 \ ------------------------------\
28291 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
28292 \ ------------------------------\
28293 \     ...                         \ init specific I/O sys as you want
28294 \     ...                         \ before executing default WARM
28295     MOV #WARM,X                 \ ['] WARM 
28296     ADD #4,X                    \ >BODY
28297     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
28298 ENDASM
28299 \ ------------------------------\
28300
28301 \ ------------------------------\
28302 CODE STOP                       \ stops multitasking, must to be used before downloading app
28303 \ ------------------------------\
28304 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
28305     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
28306     MOV X,-2(X)                 \ restore the default background: SLEEP
28307     MOV #WARM,X
28308     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
28309     BIC.B #RC5,&IR_IE           \ clear RC5_Int
28310     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
28311     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
28312     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
28313     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
28314     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
28315 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
28316 ECHO                            \
28317 ." RC5toLCD is removed,"
28318 ."  type START to restart"
28319  WARM                           \ performs reset to reset all interrupt vectors.    
28320 ;
28321 \ ------------------------------\
28322
28323 \ ------------------------------\
28324 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
28325 \ ------------------------------\
28326 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
28327 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
28328 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
28329 \                           --       \ID input divider \ 10 = /4
28330 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
28331 \                                 -  \TBCLR TimerB Clear
28332 \                                  - \TBIE
28333 \                                   -\TBIFG
28334 \ -------------------------------\
28335 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
28336 \                  --                 \CM Capture Mode
28337 \                    --               \CCIS
28338 \                       -             \SCS
28339 \                        --           \CLLD
28340 \                          -          \CAP
28341 \                            ---      \OUTMOD \ 011 = set/reset
28342 \                               -     \CCIE
28343 \                                 -   \CCI
28344 \                                  -  \OUT
28345 \                                   - \COV
28346 \                                    -\CCIFG
28347 \ -------------------------------\
28348 \ LCD_TIM_CCRx                   \
28349 \ -------------------------------\
28350 \ LCD_TIM_EX0                    \ 
28351 \ ------------------------------\
28352 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
28353 \ ------------------------------\
28354 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
28355 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
28356 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
28357     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
28358 [THEN]
28359 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
28360     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
28361 [THEN]
28362     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
28363 \ ------------------------------\
28364 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
28365 \ ------------------------------\
28366 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
28367     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
28368 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
28369 \ ------------------------------\
28370     BIS.B #LCDVo,&LCDVo_DIR     \
28371     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
28372 \ ------------------------------\
28373     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
28374     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
28375 \ ------------------------------\
28376     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
28377     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
28378 \ ******************************\
28379 \ init RC5_Int                  \
28380 \ ******************************\
28381     BIS.B #RC5,&IR_IE           \ enable RC5_Int
28382     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
28383     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
28384 \ ******************************\
28385 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
28386 \ ******************************\
28387 \              %01 0001 0100    \ TAxCTL
28388 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
28389 \                  --           \ ID        divided by 1
28390 \                    --         \ MC        MODE = up to TAxCCRn
28391 \                        -      \ TACLR     clear timer count
28392 \                         -     \ TAIE
28393 \                          -    \ TAIFG
28394 \ ------------------------------\
28395 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
28396 \ ------------------------------\
28397 \                        000    \ TAxEX0
28398 \                        ---    \ TAIDEX    pre divisor
28399 \ ------------------------------\
28400 \          %0000 0000 0000 0101 \ TAxCCR0
28401     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
28402 \ ------------------------------\
28403 \          %0000 0000 0001 0000 \ TAxCCTL0
28404 \                   -           \ CAP capture/compare mode = compare
28405 \                        -      \ CCIEn
28406 \                             - \ CCIFGn
28407     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
28408 \ ------------------------------\
28409     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
28410 \ ------------------------------\
28411 \ define LPM mode for ACCEPT    \
28412 \ ------------------------------\
28413 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
28414 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
28415 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
28416 \ ------------------------------\
28417 \ activate I/O                  \
28418 \ ------------------------------\
28419 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
28420 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
28421 \ ------------------------------\
28422 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
28423 \ ------------------------------\
28424 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
28425 \ CMP #2,Y                        \ Power_ON event
28426 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
28427 CMP #4,Y                        \
28428 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
28429 \ CMP #6,Y                        \
28430 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
28431 \ CMP #$0A,Y                      \
28432 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
28433 \ CMP #$16,Y                      \
28434 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
28435 \ ------------------------------\
28436 COLON                           \
28437 \ ------------------------------\
28438 \ Init LCD 2x20                 \
28439 \ ------------------------------\
28440     #1000 20_US                 \ 1- wait 20 ms
28441     %011 TOP_LCD                \ 2- send DB5=DB4=1
28442     #205 20_US                  \ 3- wait 4,1 ms
28443     %011 TOP_LCD                \ 4- send again DB5=DB4=1
28444     #5 20_US                    \ 5- wait 0,1 ms
28445     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
28446     #2 20_US                    \    wait 40 us = LCD cycle
28447     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
28448     #2 20_US                    \    wait 40 us = LCD cycle
28449     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
28450     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
28451     LCD_CLEAR                   \ 10- "LCD_Clear"
28452     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
28453     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
28454     LCD_CLEAR                   \ 10- "LCD_Clear"
28455     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
28456     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
28457     CR ." I love you"           \ display message on LCD
28458     ['] CR >BODY IS CR          \ CR executes its default value
28459     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
28460     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
28461     PWR_STATE ABORT             \ init DP and continues with ABORT
28462 ;                               \
28463 \ ------------------------------\
28464
28465 \ ------------------------------\
28466 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
28467 \ ------------------------------\
28468 MOV #SLEEP,X                    \ replace default background process SLEEP
28469 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
28470 MOV #WARM,X                     \ replace default WARM
28471 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
28472 MOV X,PC                        \ then execute new WARM
28473 ENDCODE 
28474 \ ------------------------------\
28475
28476 ECHO
28477             ; downloading RC5toLCD.4th is done
28478 RST_HERE    ; this app is protected against <reset>
28479
28480
28481 RST_STATE
28482
28483 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
28484
28485 [UNDEFINED] MARKER [IF]
28486 \  https://forth-standard.org/standard/core/MARKER
28487 \  MARKER
28488 \ ( "<spaces>name" -- )
28489 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
28490 \ with the execution semantics defined below.
28491
28492 \ name Execution: ( -- )
28493 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
28494 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
28495 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
28496 \ not necessarily provided. No other contextual information such as numeric base is affected
28497 \
28498 : MARKER
28499 CREATE
28500 HI2LO
28501 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
28502 SUB #2,Y            \ 1 Y = LFA
28503 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
28504 ADD #4,&DP          \ 3 add 2 cells
28505 LO2HI
28506 DOES>
28507 HI2LO
28508 MOV @RSP+,IP        \ -- PFA
28509 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
28510 MOV @TOS,&INIDP     \       set DP value for RST_STATE
28511 MOV @PSP+,TOS       \ --
28512 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
28513 ENDCODE
28514 [THEN]
28515
28516 MARKER {RC5TOLCD}
28517
28518 [UNDEFINED] @ [IF]
28519 \ https://forth-standard.org/standard/core/Fetch
28520 \ @     c-addr -- char   fetch char from memory
28521 CODE @
28522 MOV @TOS,TOS
28523 MOV @IP+,PC
28524 ENDCODE
28525 [THEN]
28526
28527 [UNDEFINED] CONSTANT [IF]
28528 \ https://forth-standard.org/standard/core/CONSTANT
28529 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
28530 : CONSTANT 
28531 CREATE
28532 HI2LO
28533 MOV TOS,-2(W)           \   PFA = n
28534 MOV @PSP+,TOS
28535 MOV @RSP+,IP
28536 MOV @IP+,PC
28537 ENDCODE
28538 [THEN]
28539
28540 [UNDEFINED] STATE [IF]
28541 \ https://forth-standard.org/standard/core/STATE
28542 \ STATE   -- a-addr       holds compiler state
28543 STATEADR CONSTANT STATE
28544 [THEN]
28545
28546 [UNDEFINED] = [IF]
28547 \ https://forth-standard.org/standard/core/Equal
28548 \ =      x1 x2 -- flag         test x1=x2
28549 CODE =
28550 SUB @PSP+,TOS   \ 2
28551 0<> IF          \ 2
28552     AND #0,TOS  \ 1
28553     MOV @IP+,PC \ 4
28554 THEN
28555 XOR #-1,TOS     \ 1 flag Z = 1
28556 MOV @IP+,PC     \ 4
28557 ENDCODE
28558 [THEN]
28559
28560 [UNDEFINED] IF [IF]
28561 \ https://forth-standard.org/standard/core/IF
28562 \ IF       -- IFadr    initialize conditional forward branch
28563 CODE IF       \ immediate
28564 SUB #2,PSP              \
28565 MOV TOS,0(PSP)          \
28566 MOV &DP,TOS             \ -- HERE
28567 ADD #4,&DP            \           compile one word, reserve one word
28568 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
28569 ADD #2,TOS              \ -- HERE+2=IFadr
28570 MOV @IP+,PC
28571 ENDCODE IMMEDIATE
28572 [THEN]
28573
28574 [UNDEFINED] THEN [IF]
28575 \ https://forth-standard.org/standard/core/THEN
28576 \ THEN     IFadr --                resolve forward branch
28577 CODE THEN               \ immediate
28578 MOV &DP,0(TOS)          \ -- IFadr
28579 MOV @PSP+,TOS           \ --
28580 MOV @IP+,PC
28581 ENDCODE IMMEDIATE
28582 [THEN]
28583
28584 [UNDEFINED] ELSE [IF]
28585 \ https://forth-standard.org/standard/core/ELSE
28586 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
28587 CODE ELSE     \ immediate
28588 ADD #4,&DP              \ make room to compile two words
28589 MOV &DP,W               \ W=HERE+4
28590 MOV #BRAN,-4(W)
28591 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
28592 SUB #2,W                \ HERE+2
28593 MOV W,TOS               \ -- ELSEadr
28594 MOV @IP+,PC
28595 ENDCODE IMMEDIATE
28596 [THEN]
28597
28598 [UNDEFINED] DEFER [IF]
28599 \ https://forth-standard.org/standard/core/DEFER
28600 \ DEFER "<spaces>name"   --
28601 \ Skip leading space delimiters. Parse name delimited by a space.
28602 \ Create a definition for name with the execution semantics defined below.
28603
28604 \ name Execution:   --
28605 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
28606 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
28607 : DEFER
28608 CREATE
28609 HI2LO
28610 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
28611 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
28612 MOV @RSP+,IP
28613 MOV @IP+,PC
28614 ENDCODE
28615 [THEN]
28616
28617 [UNDEFINED] DEFER! [IF]
28618 \ https://forth-standard.org/standard/core/DEFERStore
28619 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
28620 CODE DEFER!             \ xt2 xt1 --
28621 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
28622 MOV @PSP+,TOS           \ --
28623 MOV @IP+,PC
28624 ENDCODE
28625 [THEN]
28626
28627 [UNDEFINED] IS [IF]
28628 \ https://forth-standard.org/standard/core/IS
28629 \ IS <name>        xt --
28630 \ used as is :
28631 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
28632 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
28633 \ or in a definition : ... ['] U. IS DISPLAY ...
28634 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
28635 \
28636 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
28637 : IS
28638 STATE @
28639 IF  POSTPONE ['] POSTPONE DEFER! 
28640 ELSE ' DEFER! 
28641 THEN
28642 ; IMMEDIATE
28643 [THEN]
28644
28645 [UNDEFINED] >BODY [IF]
28646 \ https://forth-standard.org/standard/core/toBODY
28647 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
28648 CODE >BODY
28649 ADD #4,TOS
28650 MOV @IP+,PC
28651 ENDCODE
28652 [THEN]
28653
28654 \ CODE 20uS           \ n --      8MHz version
28655 \ BEGIN               \ 4 + 16 ~ loop
28656 \     MOV #39,rDOCON   \ 39
28657 \     BEGIN           \ 4 ~ loop
28658 \         NOP
28659 \         SUB #1,rDOCON
28660 \     0=  UNTIL
28661 \     SUB #1,TOS      \ 1
28662 \ 0= UNTIL
28663 \ MOV #XDOCON,rDOCON  \ 2
28664 \ MOV @PSP+,TOS
28665 \ MOV @RSP+,IP        \
28666 \ ENDCODE
28667
28668 CODE 20_US                      \ n --      n * 20 us
28669 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
28670     BEGIN
28671         BIT #1,&LCD_TIM_CTL     \ 3
28672     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
28673     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
28674     SUB #1,TOS                  \ 1
28675 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
28676 MOV @PSP+,TOS                   \ 2
28677 MOV @IP+,PC                     \ 4
28678 ENDCODE
28679
28680 CODE TOP_LCD                    \ LCD Sample
28681 \                               \ if write : %xxxx_WWWW --
28682 \                               \ if read  : -- %0000_RRRR
28683     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
28684     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
28685 0= IF                           \ write LCD bits pattern
28686     AND.B #LCD_DB,TOS           \ 
28687     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
28688     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
28689     MOV @PSP+,TOS               \
28690     MOV @IP+,PC
28691 THEN                            \ read LCD bits pattern
28692     SUB #2,PSP
28693     MOV TOS,0(PSP)
28694     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
28695     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
28696     AND.B #LCD_DB,TOS           \
28697     MOV @IP+,PC
28698 ENDCODE
28699
28700 CODE LCD_WRC                    \ char --         Write Char
28701     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
28702 BW1 SUB #2,PSP                  \
28703     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
28704     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
28705     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
28706     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
28707 COLON                           \ high level word starts here 
28708     TOP_LCD 2 20_US             \ write high nibble first
28709     TOP_LCD 2 20_US 
28710 ;
28711
28712 CODE LCD_WRF                    \ func --         Write Fonction
28713     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
28714     GOTO BW1
28715 ENDCODE
28716
28717 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
28718 : LCD_HOME $02 LCD_WRF 100 20_us ;
28719
28720 \ [UNDEFINED] OR [IF]
28721
28722 \ \ https://forth-standard.org/standard/core/OR
28723 \ \ C OR     x1 x2 -- x3           logical OR
28724 \ CODE OR
28725 \ BIS @PSP+,TOS
28726 \ MOV @IP+,PC
28727 \ ENDCODE
28728
28729 \ [THEN]
28730
28731 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
28732 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
28733 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
28734 \ : LCD_FN_SET        $20 OR LCD_WrF ;
28735 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
28736 \ : LCD_GOTO          $80 OR LCD_WrF ;
28737
28738
28739 \ CODE LCD_RDS                    \ -- status       Read Status
28740 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
28741 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
28742 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
28743 \ COLON                           \ starts a FORTH word
28744 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
28745 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
28746 \ HI2LO                           \ switch from FORTH to assembler
28747 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
28748 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
28749 \     MOV @RSP+,IP                \ restore IP saved by COLON
28750 \     MOV @IP+,PC                 \
28751 \ ENDCODE
28752
28753 \ CODE LCD_RDC                    \ -- char         Read Char
28754 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
28755 \     GOTO BW1
28756 \ ENDCODE
28757
28758
28759 \ ******************************\
28760 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
28761 \ ******************************\
28762 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
28763 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
28764 BIT.B #SW2,&SW2_IN              \ test switch S2
28765 0= IF                           \ case of switch S2 pressed
28766     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
28767     U< IF
28768         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
28769     THEN
28770 ELSE
28771     BIT.B #SW1,&SW1_IN          \ test switch S1 input
28772     0= IF                       \ case of Switch S1 pressed
28773         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
28774         U>= IF                  \
28775            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
28776         THEN                    \
28777     THEN                        \
28778 THEN                            \
28779 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
28780 RET                             \ 5
28781 ENDASM
28782
28783 \ ******************************\
28784 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
28785 \ ******************************\
28786 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
28787 \ ******************************\
28788 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
28789 \                               \       SMclock = 8|16|24 MHz
28790 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
28791 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
28792 \                               \       SR(9)=new Toggle bit memory (ADD on)
28793 \ ******************************\
28794 \ RC5_FirstStartBitHalfCycle:   \
28795 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
28796 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
28797 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
28798 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
28799 \ [THEN]
28800 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
28801     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
28802 [THEN]
28803 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
28804     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
28805 [THEN]
28806 MOV #1778,X                     \ RC5_Period * 1us
28807 MOV #14,W                       \ count of loop
28808 BEGIN                           \
28809 \ ******************************\
28810 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
28811 \ ******************************\                   |
28812 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
28813 \ RC5_Compute_3/4_Period:       \                   |
28814     RRUM    #1,X                \ X=1/2 cycle       |
28815     MOV     X,Y                 \                   ^
28816     RRUM    #1,Y                \ Y=1/4
28817     ADD     X,Y                 \ Y=3/4 cycle
28818     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
28819     U>= UNTIL                   \ 2
28820 \ ******************************\
28821 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
28822 \ ******************************\
28823     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
28824     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
28825     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
28826     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
28827     SUB     #1,W                \ decrement count loop
28828 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
28829 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
28830 0<> WHILE                       \ ----> out of loop ----+
28831     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
28832     BEGIN                       \                       |
28833         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
28834         CMP Y,X                 \ 1                     |   cycle time out of bound ?
28835         U>= IF                  \ 2                 ^   |   yes:
28836         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
28837         GOTO BW1                \                   |   |      quit on truncated RC5 message
28838         THEN                    \                   |   |
28839         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
28840     0<> UNTIL                   \ 2                 |   |
28841 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
28842 \ ******************************\                       |
28843 \ RC5_SampleEndOf:              \ <---------------------+
28844 \ ******************************\
28845 BIC #$30,&RC5_TIM_CTL           \   stop timer
28846 \ ******************************\
28847 \ RC5_ComputeNewRC5word         \
28848 \ ******************************\
28849 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
28850 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
28851 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
28852 \ ******************************\
28853 \ RC5_ComputeC6bit              \
28854 \ ******************************\
28855 BIT     #BIT14,T                \ test /C6 bit in T
28856 0= IF   BIS #BIT6,X             \ set C6 bit in X
28857 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
28858 \ ******************************\
28859 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
28860 \ ******************************\
28861 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
28862 \ ******************************\
28863 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
28864 XOR     @RSP,T                  \ (new XOR old) Toggle bits
28865 BIT     #UF10,T                 \ repeated RC5_command ?
28866 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
28867 XOR #UF10,0(RSP)                \ 5 toggle bit memory
28868 \ ******************************\
28869 \ Display IR_RC5 code           \
28870 \ ******************************\
28871 SUB #8,PSP                      \ TOS -- x x x x TOS
28872 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
28873 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
28874 MOV #$10,&BASEADR               \                                               set hexadecimal base
28875 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
28876 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
28877 LO2HI                           \                                               switch from assembler to FORTH
28878     LCD_CLEAR                   \                                               set LCD cursor at home
28879     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
28880     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
28881     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
28882     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
28883 HI2LO                           \     --                                        switch from FORTH to assembler
28884 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
28885 MOV @PSP+,TOS                   \     -- TOS
28886 RET
28887 ENDASM
28888
28889 \ ******************************\
28890 ASM BACKGROUND                  \
28891 \ ******************************\
28892 BEGIN
28893 \     ...                         \ insert here your background task
28894 \     ...                         \
28895 \     ...                         \
28896     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
28897     BIS &LPM_MODE,SR            \
28898 \ ******************************\
28899 \ here start all interrupts     \
28900 \ ******************************\
28901 \ here return all interrupts    \
28902 \ ******************************\
28903 AGAIN                           \
28904 ENDASM                          \
28905 \ ******************************\
28906
28907 \ ------------------------------\
28908 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
28909 \ ------------------------------\
28910 \     ...                         \ init specific I/O sys as you want
28911 \     ...                         \ before executing default WARM
28912     MOV #WARM,X                 \ ['] WARM 
28913     ADD #4,X                    \ >BODY
28914     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
28915 ENDASM
28916 \ ------------------------------\
28917
28918 \ ------------------------------\
28919 CODE STOP                       \ stops multitasking, must to be used before downloading app
28920 \ ------------------------------\
28921 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
28922     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
28923     MOV X,-2(X)                 \ restore the default background: SLEEP
28924     MOV #WARM,X
28925     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
28926     BIC.B #RC5,&IR_IE           \ clear RC5_Int
28927     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
28928     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
28929     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
28930     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
28931     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
28932 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
28933 ECHO                            \
28934 ." RC5toLCD is removed,"
28935 ."  type START to restart"
28936  WARM                           \ performs reset to reset all interrupt vectors.    
28937 ;
28938 \ ------------------------------\
28939
28940 \ ------------------------------\
28941 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
28942 \ ------------------------------\
28943 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
28944 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
28945 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
28946 \                           --       \ID input divider \ 10 = /4
28947 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
28948 \                                 -  \TBCLR TimerB Clear
28949 \                                  - \TBIE
28950 \                                   -\TBIFG
28951 \ -------------------------------\
28952 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
28953 \                  --                 \CM Capture Mode
28954 \                    --               \CCIS
28955 \                       -             \SCS
28956 \                        --           \CLLD
28957 \                          -          \CAP
28958 \                            ---      \OUTMOD \ 011 = set/reset
28959 \                               -     \CCIE
28960 \                                 -   \CCI
28961 \                                  -  \OUT
28962 \                                   - \COV
28963 \                                    -\CCIFG
28964 \ -------------------------------\
28965 \ LCD_TIM_CCRx                   \
28966 \ -------------------------------\
28967 \ LCD_TIM_EX0                    \ 
28968 \ ------------------------------\
28969 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
28970 \ ------------------------------\
28971 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
28972 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
28973 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
28974     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
28975 [THEN]
28976 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
28977     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
28978 [THEN]
28979     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
28980 \ ------------------------------\
28981 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
28982 \ ------------------------------\
28983 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
28984     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
28985 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
28986 \ ------------------------------\
28987     BIS.B #LCDVo,&LCDVo_DIR     \
28988     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
28989 \ ------------------------------\
28990     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
28991     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
28992 \ ------------------------------\
28993     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
28994     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
28995 \ ******************************\
28996 \ init RC5_Int                  \
28997 \ ******************************\
28998     BIS.B #RC5,&IR_IE           \ enable RC5_Int
28999     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
29000     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
29001 \ ******************************\
29002 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
29003 \ ******************************\
29004 \              %01 0001 0100    \ TAxCTL
29005 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
29006 \                  --           \ ID        divided by 1
29007 \                    --         \ MC        MODE = up to TAxCCRn
29008 \                        -      \ TACLR     clear timer count
29009 \                         -     \ TAIE
29010 \                          -    \ TAIFG
29011 \ ------------------------------\
29012 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
29013 \ ------------------------------\
29014 \                        000    \ TAxEX0
29015 \                        ---    \ TAIDEX    pre divisor
29016 \ ------------------------------\
29017 \          %0000 0000 0000 0101 \ TAxCCR0
29018     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
29019 \ ------------------------------\
29020 \          %0000 0000 0001 0000 \ TAxCCTL0
29021 \                   -           \ CAP capture/compare mode = compare
29022 \                        -      \ CCIEn
29023 \                             - \ CCIFGn
29024     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
29025 \ ------------------------------\
29026     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
29027 \ ------------------------------\
29028 \ define LPM mode for ACCEPT    \
29029 \ ------------------------------\
29030 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
29031 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
29032 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
29033 \ ------------------------------\
29034 \ activate I/O                  \
29035 \ ------------------------------\
29036 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
29037 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
29038 \ ------------------------------\
29039 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
29040 \ ------------------------------\
29041 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
29042 \ CMP #2,Y                        \ Power_ON event
29043 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
29044 CMP #4,Y                        \
29045 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
29046 \ CMP #6,Y                        \
29047 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
29048 \ CMP #$0A,Y                      \
29049 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
29050 \ CMP #$16,Y                      \
29051 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
29052 \ ------------------------------\
29053 COLON                           \
29054 \ ------------------------------\
29055 \ Init LCD 2x20                 \
29056 \ ------------------------------\
29057     #1000 20_US                 \ 1- wait 20 ms
29058     %011 TOP_LCD                \ 2- send DB5=DB4=1
29059     #205 20_US                  \ 3- wait 4,1 ms
29060     %011 TOP_LCD                \ 4- send again DB5=DB4=1
29061     #5 20_US                    \ 5- wait 0,1 ms
29062     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
29063     #2 20_US                    \    wait 40 us = LCD cycle
29064     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
29065     #2 20_US                    \    wait 40 us = LCD cycle
29066     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
29067     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
29068     LCD_CLEAR                   \ 10- "LCD_Clear"
29069     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
29070     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
29071     LCD_CLEAR                   \ 10- "LCD_Clear"
29072     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
29073     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
29074     CR ." I love you"           \ display message on LCD
29075     ['] CR >BODY IS CR          \ CR executes its default value
29076     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
29077     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
29078     PWR_STATE ABORT             \ init DP and continues with ABORT
29079 ;                               \
29080 \ ------------------------------\
29081
29082 \ ------------------------------\
29083 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
29084 \ ------------------------------\
29085 MOV #SLEEP,X                    \ replace default background process SLEEP
29086 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
29087 MOV #WARM,X                     \ replace default WARM
29088 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
29089 MOV X,PC                        \ then execute new WARM
29090 ENDCODE 
29091 \ ------------------------------\
29092
29093 ECHO
29094             ; downloading RC5toLCD.4th is done
29095 RST_HERE    ; this app is protected against <reset>
29096
29097
29098 RST_STATE
29099
29100 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
29101
29102 [UNDEFINED] MARKER [IF]
29103 \  https://forth-standard.org/standard/core/MARKER
29104 \  MARKER
29105 \ ( "<spaces>name" -- )
29106 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
29107 \ with the execution semantics defined below.
29108
29109 \ name Execution: ( -- )
29110 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
29111 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
29112 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
29113 \ not necessarily provided. No other contextual information such as numeric base is affected
29114 \
29115 : MARKER
29116 CREATE
29117 HI2LO
29118 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
29119 SUB #2,Y            \ 1 Y = LFA
29120 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
29121 ADD #4,&DP          \ 3 add 2 cells
29122 LO2HI
29123 DOES>
29124 HI2LO
29125 MOV @RSP+,IP        \ -- PFA
29126 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
29127 MOV @TOS,&INIDP     \       set DP value for RST_STATE
29128 MOV @PSP+,TOS       \ --
29129 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
29130 ENDCODE
29131 [THEN]
29132
29133 MARKER {RC5TOLCD}
29134
29135 [UNDEFINED] @ [IF]
29136 \ https://forth-standard.org/standard/core/Fetch
29137 \ @     c-addr -- char   fetch char from memory
29138 CODE @
29139 MOV @TOS,TOS
29140 MOV @IP+,PC
29141 ENDCODE
29142 [THEN]
29143
29144 [UNDEFINED] CONSTANT [IF]
29145 \ https://forth-standard.org/standard/core/CONSTANT
29146 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
29147 : CONSTANT 
29148 CREATE
29149 HI2LO
29150 MOV TOS,-2(W)           \   PFA = n
29151 MOV @PSP+,TOS
29152 MOV @RSP+,IP
29153 MOV @IP+,PC
29154 ENDCODE
29155 [THEN]
29156
29157 [UNDEFINED] STATE [IF]
29158 \ https://forth-standard.org/standard/core/STATE
29159 \ STATE   -- a-addr       holds compiler state
29160 STATEADR CONSTANT STATE
29161 [THEN]
29162
29163 [UNDEFINED] = [IF]
29164 \ https://forth-standard.org/standard/core/Equal
29165 \ =      x1 x2 -- flag         test x1=x2
29166 CODE =
29167 SUB @PSP+,TOS   \ 2
29168 0<> IF          \ 2
29169     AND #0,TOS  \ 1
29170     MOV @IP+,PC \ 4
29171 THEN
29172 XOR #-1,TOS     \ 1 flag Z = 1
29173 MOV @IP+,PC     \ 4
29174 ENDCODE
29175 [THEN]
29176
29177 [UNDEFINED] IF [IF]
29178 \ https://forth-standard.org/standard/core/IF
29179 \ IF       -- IFadr    initialize conditional forward branch
29180 CODE IF       \ immediate
29181 SUB #2,PSP              \
29182 MOV TOS,0(PSP)          \
29183 MOV &DP,TOS             \ -- HERE
29184 ADD #4,&DP            \           compile one word, reserve one word
29185 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
29186 ADD #2,TOS              \ -- HERE+2=IFadr
29187 MOV @IP+,PC
29188 ENDCODE IMMEDIATE
29189 [THEN]
29190
29191 [UNDEFINED] THEN [IF]
29192 \ https://forth-standard.org/standard/core/THEN
29193 \ THEN     IFadr --                resolve forward branch
29194 CODE THEN               \ immediate
29195 MOV &DP,0(TOS)          \ -- IFadr
29196 MOV @PSP+,TOS           \ --
29197 MOV @IP+,PC
29198 ENDCODE IMMEDIATE
29199 [THEN]
29200
29201 [UNDEFINED] ELSE [IF]
29202 \ https://forth-standard.org/standard/core/ELSE
29203 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
29204 CODE ELSE     \ immediate
29205 ADD #4,&DP              \ make room to compile two words
29206 MOV &DP,W               \ W=HERE+4
29207 MOV #BRAN,-4(W)
29208 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
29209 SUB #2,W                \ HERE+2
29210 MOV W,TOS               \ -- ELSEadr
29211 MOV @IP+,PC
29212 ENDCODE IMMEDIATE
29213 [THEN]
29214
29215 [UNDEFINED] DEFER [IF]
29216 \ https://forth-standard.org/standard/core/DEFER
29217 \ DEFER "<spaces>name"   --
29218 \ Skip leading space delimiters. Parse name delimited by a space.
29219 \ Create a definition for name with the execution semantics defined below.
29220
29221 \ name Execution:   --
29222 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
29223 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
29224 : DEFER
29225 CREATE
29226 HI2LO
29227 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
29228 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
29229 MOV @RSP+,IP
29230 MOV @IP+,PC
29231 ENDCODE
29232 [THEN]
29233
29234 [UNDEFINED] DEFER! [IF]
29235 \ https://forth-standard.org/standard/core/DEFERStore
29236 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
29237 CODE DEFER!             \ xt2 xt1 --
29238 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
29239 MOV @PSP+,TOS           \ --
29240 MOV @IP+,PC
29241 ENDCODE
29242 [THEN]
29243
29244 [UNDEFINED] IS [IF]
29245 \ https://forth-standard.org/standard/core/IS
29246 \ IS <name>        xt --
29247 \ used as is :
29248 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
29249 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
29250 \ or in a definition : ... ['] U. IS DISPLAY ...
29251 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
29252 \
29253 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
29254 : IS
29255 STATE @
29256 IF  POSTPONE ['] POSTPONE DEFER! 
29257 ELSE ' DEFER! 
29258 THEN
29259 ; IMMEDIATE
29260 [THEN]
29261
29262 [UNDEFINED] >BODY [IF]
29263 \ https://forth-standard.org/standard/core/toBODY
29264 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
29265 CODE >BODY
29266 ADD #4,TOS
29267 MOV @IP+,PC
29268 ENDCODE
29269 [THEN]
29270
29271 \ CODE 20uS           \ n --      8MHz version
29272 \ BEGIN               \ 4 + 16 ~ loop
29273 \     MOV #39,rDOCON   \ 39
29274 \     BEGIN           \ 4 ~ loop
29275 \         NOP
29276 \         SUB #1,rDOCON
29277 \     0=  UNTIL
29278 \     SUB #1,TOS      \ 1
29279 \ 0= UNTIL
29280 \ MOV #XDOCON,rDOCON  \ 2
29281 \ MOV @PSP+,TOS
29282 \ MOV @RSP+,IP        \
29283 \ ENDCODE
29284
29285 CODE 20_US                      \ n --      n * 20 us
29286 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
29287     BEGIN
29288         BIT #1,&LCD_TIM_CTL     \ 3
29289     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
29290     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
29291     SUB #1,TOS                  \ 1
29292 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
29293 MOV @PSP+,TOS                   \ 2
29294 MOV @IP+,PC                     \ 4
29295 ENDCODE
29296
29297 CODE TOP_LCD                    \ LCD Sample
29298 \                               \ if write : %xxxx_WWWW --
29299 \                               \ if read  : -- %0000_RRRR
29300     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
29301     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
29302 0= IF                           \ write LCD bits pattern
29303     AND.B #LCD_DB,TOS           \ 
29304     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
29305     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
29306     MOV @PSP+,TOS               \
29307     MOV @IP+,PC
29308 THEN                            \ read LCD bits pattern
29309     SUB #2,PSP
29310     MOV TOS,0(PSP)
29311     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
29312     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
29313     AND.B #LCD_DB,TOS           \
29314     MOV @IP+,PC
29315 ENDCODE
29316
29317 CODE LCD_WRC                    \ char --         Write Char
29318     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
29319 BW1 SUB #2,PSP                  \
29320     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
29321     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
29322     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
29323     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
29324 COLON                           \ high level word starts here 
29325     TOP_LCD 2 20_US             \ write high nibble first
29326     TOP_LCD 2 20_US 
29327 ;
29328
29329 CODE LCD_WRF                    \ func --         Write Fonction
29330     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
29331     GOTO BW1
29332 ENDCODE
29333
29334 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
29335 : LCD_HOME $02 LCD_WRF 100 20_us ;
29336
29337 \ [UNDEFINED] OR [IF]
29338
29339 \ \ https://forth-standard.org/standard/core/OR
29340 \ \ C OR     x1 x2 -- x3           logical OR
29341 \ CODE OR
29342 \ BIS @PSP+,TOS
29343 \ MOV @IP+,PC
29344 \ ENDCODE
29345
29346 \ [THEN]
29347
29348 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
29349 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
29350 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
29351 \ : LCD_FN_SET        $20 OR LCD_WrF ;
29352 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
29353 \ : LCD_GOTO          $80 OR LCD_WrF ;
29354
29355
29356 \ CODE LCD_RDS                    \ -- status       Read Status
29357 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
29358 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
29359 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
29360 \ COLON                           \ starts a FORTH word
29361 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
29362 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
29363 \ HI2LO                           \ switch from FORTH to assembler
29364 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
29365 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
29366 \     MOV @RSP+,IP                \ restore IP saved by COLON
29367 \     MOV @IP+,PC                 \
29368 \ ENDCODE
29369
29370 \ CODE LCD_RDC                    \ -- char         Read Char
29371 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
29372 \     GOTO BW1
29373 \ ENDCODE
29374
29375
29376 \ ******************************\
29377 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
29378 \ ******************************\
29379 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
29380 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
29381 BIT.B #SW2,&SW2_IN              \ test switch S2
29382 0= IF                           \ case of switch S2 pressed
29383     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
29384     U< IF
29385         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
29386     THEN
29387 ELSE
29388     BIT.B #SW1,&SW1_IN          \ test switch S1 input
29389     0= IF                       \ case of Switch S1 pressed
29390         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
29391         U>= IF                  \
29392            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
29393         THEN                    \
29394     THEN                        \
29395 THEN                            \
29396 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
29397 RET                             \ 5
29398 ENDASM
29399
29400 \ ******************************\
29401 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
29402 \ ******************************\
29403 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
29404 \ ******************************\
29405 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
29406 \                               \       SMclock = 8|16|24 MHz
29407 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
29408 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
29409 \                               \       SR(9)=new Toggle bit memory (ADD on)
29410 \ ******************************\
29411 \ RC5_FirstStartBitHalfCycle:   \
29412 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
29413 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
29414 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
29415 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
29416 \ [THEN]
29417 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
29418     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
29419 [THEN]
29420 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
29421     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
29422 [THEN]
29423 MOV #1778,X                     \ RC5_Period * 1us
29424 MOV #14,W                       \ count of loop
29425 BEGIN                           \
29426 \ ******************************\
29427 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
29428 \ ******************************\                   |
29429 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
29430 \ RC5_Compute_3/4_Period:       \                   |
29431     RRUM    #1,X                \ X=1/2 cycle       |
29432     MOV     X,Y                 \                   ^
29433     RRUM    #1,Y                \ Y=1/4
29434     ADD     X,Y                 \ Y=3/4 cycle
29435     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
29436     U>= UNTIL                   \ 2
29437 \ ******************************\
29438 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
29439 \ ******************************\
29440     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
29441     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
29442     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
29443     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
29444     SUB     #1,W                \ decrement count loop
29445 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
29446 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
29447 0<> WHILE                       \ ----> out of loop ----+
29448     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
29449     BEGIN                       \                       |
29450         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
29451         CMP Y,X                 \ 1                     |   cycle time out of bound ?
29452         U>= IF                  \ 2                 ^   |   yes:
29453         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
29454         GOTO BW1                \                   |   |      quit on truncated RC5 message
29455         THEN                    \                   |   |
29456         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
29457     0<> UNTIL                   \ 2                 |   |
29458 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
29459 \ ******************************\                       |
29460 \ RC5_SampleEndOf:              \ <---------------------+
29461 \ ******************************\
29462 BIC #$30,&RC5_TIM_CTL           \   stop timer
29463 \ ******************************\
29464 \ RC5_ComputeNewRC5word         \
29465 \ ******************************\
29466 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
29467 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
29468 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
29469 \ ******************************\
29470 \ RC5_ComputeC6bit              \
29471 \ ******************************\
29472 BIT     #BIT14,T                \ test /C6 bit in T
29473 0= IF   BIS #BIT6,X             \ set C6 bit in X
29474 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
29475 \ ******************************\
29476 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
29477 \ ******************************\
29478 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
29479 \ ******************************\
29480 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
29481 XOR     @RSP,T                  \ (new XOR old) Toggle bits
29482 BIT     #UF10,T                 \ repeated RC5_command ?
29483 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
29484 XOR #UF10,0(RSP)                \ 5 toggle bit memory
29485 \ ******************************\
29486 \ Display IR_RC5 code           \
29487 \ ******************************\
29488 SUB #8,PSP                      \ TOS -- x x x x TOS
29489 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
29490 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
29491 MOV #$10,&BASEADR               \                                               set hexadecimal base
29492 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
29493 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
29494 LO2HI                           \                                               switch from assembler to FORTH
29495     LCD_CLEAR                   \                                               set LCD cursor at home
29496     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
29497     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
29498     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
29499     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
29500 HI2LO                           \     --                                        switch from FORTH to assembler
29501 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
29502 MOV @PSP+,TOS                   \     -- TOS
29503 RET
29504 ENDASM
29505
29506 \ ******************************\
29507 ASM BACKGROUND                  \
29508 \ ******************************\
29509 BEGIN
29510 \     ...                         \ insert here your background task
29511 \     ...                         \
29512 \     ...                         \
29513     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
29514     BIS &LPM_MODE,SR            \
29515 \ ******************************\
29516 \ here start all interrupts     \
29517 \ ******************************\
29518 \ here return all interrupts    \
29519 \ ******************************\
29520 AGAIN                           \
29521 ENDASM                          \
29522 \ ******************************\
29523
29524 \ ------------------------------\
29525 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
29526 \ ------------------------------\
29527 \     ...                         \ init specific I/O sys as you want
29528 \     ...                         \ before executing default WARM
29529     MOV #WARM,X                 \ ['] WARM 
29530     ADD #4,X                    \ >BODY
29531     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
29532 ENDASM
29533 \ ------------------------------\
29534
29535 \ ------------------------------\
29536 CODE STOP                       \ stops multitasking, must to be used before downloading app
29537 \ ------------------------------\
29538 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
29539     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
29540     MOV X,-2(X)                 \ restore the default background: SLEEP
29541     MOV #WARM,X
29542     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
29543     BIC.B #RC5,&IR_IE           \ clear RC5_Int
29544     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
29545     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
29546     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
29547     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
29548     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
29549 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
29550 ECHO                            \
29551 ." RC5toLCD is removed,"
29552 ."  type START to restart"
29553  WARM                           \ performs reset to reset all interrupt vectors.    
29554 ;
29555 \ ------------------------------\
29556
29557 \ ------------------------------\
29558 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
29559 \ ------------------------------\
29560 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
29561 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
29562 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
29563 \                           --       \ID input divider \ 10 = /4
29564 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
29565 \                                 -  \TBCLR TimerB Clear
29566 \                                  - \TBIE
29567 \                                   -\TBIFG
29568 \ -------------------------------\
29569 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
29570 \                  --                 \CM Capture Mode
29571 \                    --               \CCIS
29572 \                       -             \SCS
29573 \                        --           \CLLD
29574 \                          -          \CAP
29575 \                            ---      \OUTMOD \ 011 = set/reset
29576 \                               -     \CCIE
29577 \                                 -   \CCI
29578 \                                  -  \OUT
29579 \                                   - \COV
29580 \                                    -\CCIFG
29581 \ -------------------------------\
29582 \ LCD_TIM_CCRx                   \
29583 \ -------------------------------\
29584 \ LCD_TIM_EX0                    \ 
29585 \ ------------------------------\
29586 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
29587 \ ------------------------------\
29588 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
29589 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
29590 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
29591     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
29592 [THEN]
29593 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
29594     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
29595 [THEN]
29596     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
29597 \ ------------------------------\
29598 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
29599 \ ------------------------------\
29600 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
29601     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
29602 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
29603 \ ------------------------------\
29604     BIS.B #LCDVo,&LCDVo_DIR     \
29605     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
29606 \ ------------------------------\
29607     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
29608     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
29609 \ ------------------------------\
29610     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
29611     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
29612 \ ******************************\
29613 \ init RC5_Int                  \
29614 \ ******************************\
29615     BIS.B #RC5,&IR_IE           \ enable RC5_Int
29616     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
29617     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
29618 \ ******************************\
29619 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
29620 \ ******************************\
29621 \              %01 0001 0100    \ TAxCTL
29622 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
29623 \                  --           \ ID        divided by 1
29624 \                    --         \ MC        MODE = up to TAxCCRn
29625 \                        -      \ TACLR     clear timer count
29626 \                         -     \ TAIE
29627 \                          -    \ TAIFG
29628 \ ------------------------------\
29629 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
29630 \ ------------------------------\
29631 \                        000    \ TAxEX0
29632 \                        ---    \ TAIDEX    pre divisor
29633 \ ------------------------------\
29634 \          %0000 0000 0000 0101 \ TAxCCR0
29635     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
29636 \ ------------------------------\
29637 \          %0000 0000 0001 0000 \ TAxCCTL0
29638 \                   -           \ CAP capture/compare mode = compare
29639 \                        -      \ CCIEn
29640 \                             - \ CCIFGn
29641     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
29642 \ ------------------------------\
29643     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
29644 \ ------------------------------\
29645 \ define LPM mode for ACCEPT    \
29646 \ ------------------------------\
29647 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
29648 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
29649 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
29650 \ ------------------------------\
29651 \ activate I/O                  \
29652 \ ------------------------------\
29653 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
29654 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
29655 \ ------------------------------\
29656 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
29657 \ ------------------------------\
29658 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
29659 \ CMP #2,Y                        \ Power_ON event
29660 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
29661 CMP #4,Y                        \
29662 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
29663 \ CMP #6,Y                        \
29664 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
29665 \ CMP #$0A,Y                      \
29666 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
29667 \ CMP #$16,Y                      \
29668 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
29669 \ ------------------------------\
29670 COLON                           \
29671 \ ------------------------------\
29672 \ Init LCD 2x20                 \
29673 \ ------------------------------\
29674     #1000 20_US                 \ 1- wait 20 ms
29675     %011 TOP_LCD                \ 2- send DB5=DB4=1
29676     #205 20_US                  \ 3- wait 4,1 ms
29677     %011 TOP_LCD                \ 4- send again DB5=DB4=1
29678     #5 20_US                    \ 5- wait 0,1 ms
29679     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
29680     #2 20_US                    \    wait 40 us = LCD cycle
29681     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
29682     #2 20_US                    \    wait 40 us = LCD cycle
29683     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
29684     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
29685     LCD_CLEAR                   \ 10- "LCD_Clear"
29686     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
29687     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
29688     LCD_CLEAR                   \ 10- "LCD_Clear"
29689     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
29690     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
29691     CR ." I love you"           \ display message on LCD
29692     ['] CR >BODY IS CR          \ CR executes its default value
29693     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
29694     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
29695     PWR_STATE ABORT             \ init DP and continues with ABORT
29696 ;                               \
29697 \ ------------------------------\
29698
29699 \ ------------------------------\
29700 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
29701 \ ------------------------------\
29702 MOV #SLEEP,X                    \ replace default background process SLEEP
29703 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
29704 MOV #WARM,X                     \ replace default WARM
29705 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
29706 MOV X,PC                        \ then execute new WARM
29707 ENDCODE 
29708 \ ------------------------------\
29709
29710 ECHO
29711             ; downloading RC5toLCD.4th is done
29712 RST_HERE    ; this app is protected against <reset>
29713
29714
29715 RST_STATE
29716
29717 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
29718
29719 [UNDEFINED] MARKER [IF]
29720 \  https://forth-standard.org/standard/core/MARKER
29721 \  MARKER
29722 \ ( "<spaces>name" -- )
29723 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
29724 \ with the execution semantics defined below.
29725
29726 \ name Execution: ( -- )
29727 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
29728 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
29729 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
29730 \ not necessarily provided. No other contextual information such as numeric base is affected
29731 \
29732 : MARKER
29733 CREATE
29734 HI2LO
29735 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
29736 SUB #2,Y            \ 1 Y = LFA
29737 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
29738 ADD #4,&DP          \ 3 add 2 cells
29739 LO2HI
29740 DOES>
29741 HI2LO
29742 MOV @RSP+,IP        \ -- PFA
29743 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
29744 MOV @TOS,&INIDP     \       set DP value for RST_STATE
29745 MOV @PSP+,TOS       \ --
29746 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
29747 ENDCODE
29748 [THEN]
29749
29750 MARKER {RC5TOLCD}
29751
29752 [UNDEFINED] @ [IF]
29753 \ https://forth-standard.org/standard/core/Fetch
29754 \ @     c-addr -- char   fetch char from memory
29755 CODE @
29756 MOV @TOS,TOS
29757 MOV @IP+,PC
29758 ENDCODE
29759 [THEN]
29760
29761 [UNDEFINED] CONSTANT [IF]
29762 \ https://forth-standard.org/standard/core/CONSTANT
29763 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
29764 : CONSTANT 
29765 CREATE
29766 HI2LO
29767 MOV TOS,-2(W)           \   PFA = n
29768 MOV @PSP+,TOS
29769 MOV @RSP+,IP
29770 MOV @IP+,PC
29771 ENDCODE
29772 [THEN]
29773
29774 [UNDEFINED] STATE [IF]
29775 \ https://forth-standard.org/standard/core/STATE
29776 \ STATE   -- a-addr       holds compiler state
29777 STATEADR CONSTANT STATE
29778 [THEN]
29779
29780 [UNDEFINED] = [IF]
29781 \ https://forth-standard.org/standard/core/Equal
29782 \ =      x1 x2 -- flag         test x1=x2
29783 CODE =
29784 SUB @PSP+,TOS   \ 2
29785 0<> IF          \ 2
29786     AND #0,TOS  \ 1
29787     MOV @IP+,PC \ 4
29788 THEN
29789 XOR #-1,TOS     \ 1 flag Z = 1
29790 MOV @IP+,PC     \ 4
29791 ENDCODE
29792 [THEN]
29793
29794 [UNDEFINED] IF [IF]
29795 \ https://forth-standard.org/standard/core/IF
29796 \ IF       -- IFadr    initialize conditional forward branch
29797 CODE IF       \ immediate
29798 SUB #2,PSP              \
29799 MOV TOS,0(PSP)          \
29800 MOV &DP,TOS             \ -- HERE
29801 ADD #4,&DP            \           compile one word, reserve one word
29802 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
29803 ADD #2,TOS              \ -- HERE+2=IFadr
29804 MOV @IP+,PC
29805 ENDCODE IMMEDIATE
29806 [THEN]
29807
29808 [UNDEFINED] THEN [IF]
29809 \ https://forth-standard.org/standard/core/THEN
29810 \ THEN     IFadr --                resolve forward branch
29811 CODE THEN               \ immediate
29812 MOV &DP,0(TOS)          \ -- IFadr
29813 MOV @PSP+,TOS           \ --
29814 MOV @IP+,PC
29815 ENDCODE IMMEDIATE
29816 [THEN]
29817
29818 [UNDEFINED] ELSE [IF]
29819 \ https://forth-standard.org/standard/core/ELSE
29820 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
29821 CODE ELSE     \ immediate
29822 ADD #4,&DP              \ make room to compile two words
29823 MOV &DP,W               \ W=HERE+4
29824 MOV #BRAN,-4(W)
29825 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
29826 SUB #2,W                \ HERE+2
29827 MOV W,TOS               \ -- ELSEadr
29828 MOV @IP+,PC
29829 ENDCODE IMMEDIATE
29830 [THEN]
29831
29832 [UNDEFINED] DEFER [IF]
29833 \ https://forth-standard.org/standard/core/DEFER
29834 \ DEFER "<spaces>name"   --
29835 \ Skip leading space delimiters. Parse name delimited by a space.
29836 \ Create a definition for name with the execution semantics defined below.
29837
29838 \ name Execution:   --
29839 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
29840 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
29841 : DEFER
29842 CREATE
29843 HI2LO
29844 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
29845 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
29846 MOV @RSP+,IP
29847 MOV @IP+,PC
29848 ENDCODE
29849 [THEN]
29850
29851 [UNDEFINED] DEFER! [IF]
29852 \ https://forth-standard.org/standard/core/DEFERStore
29853 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
29854 CODE DEFER!             \ xt2 xt1 --
29855 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
29856 MOV @PSP+,TOS           \ --
29857 MOV @IP+,PC
29858 ENDCODE
29859 [THEN]
29860
29861 [UNDEFINED] IS [IF]
29862 \ https://forth-standard.org/standard/core/IS
29863 \ IS <name>        xt --
29864 \ used as is :
29865 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
29866 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
29867 \ or in a definition : ... ['] U. IS DISPLAY ...
29868 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
29869 \
29870 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
29871 : IS
29872 STATE @
29873 IF  POSTPONE ['] POSTPONE DEFER! 
29874 ELSE ' DEFER! 
29875 THEN
29876 ; IMMEDIATE
29877 [THEN]
29878
29879 [UNDEFINED] >BODY [IF]
29880 \ https://forth-standard.org/standard/core/toBODY
29881 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
29882 CODE >BODY
29883 ADD #4,TOS
29884 MOV @IP+,PC
29885 ENDCODE
29886 [THEN]
29887
29888 \ CODE 20uS           \ n --      8MHz version
29889 \ BEGIN               \ 4 + 16 ~ loop
29890 \     MOV #39,rDOCON   \ 39
29891 \     BEGIN           \ 4 ~ loop
29892 \         NOP
29893 \         SUB #1,rDOCON
29894 \     0=  UNTIL
29895 \     SUB #1,TOS      \ 1
29896 \ 0= UNTIL
29897 \ MOV #XDOCON,rDOCON  \ 2
29898 \ MOV @PSP+,TOS
29899 \ MOV @RSP+,IP        \
29900 \ ENDCODE
29901
29902 CODE 20_US                      \ n --      n * 20 us
29903 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
29904     BEGIN
29905         BIT #1,&LCD_TIM_CTL     \ 3
29906     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
29907     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
29908     SUB #1,TOS                  \ 1
29909 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
29910 MOV @PSP+,TOS                   \ 2
29911 MOV @IP+,PC                     \ 4
29912 ENDCODE
29913
29914 CODE TOP_LCD                    \ LCD Sample
29915 \                               \ if write : %xxxx_WWWW --
29916 \                               \ if read  : -- %0000_RRRR
29917     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
29918     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
29919 0= IF                           \ write LCD bits pattern
29920     AND.B #LCD_DB,TOS           \ 
29921     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
29922     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
29923     MOV @PSP+,TOS               \
29924     MOV @IP+,PC
29925 THEN                            \ read LCD bits pattern
29926     SUB #2,PSP
29927     MOV TOS,0(PSP)
29928     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
29929     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
29930     AND.B #LCD_DB,TOS           \
29931     MOV @IP+,PC
29932 ENDCODE
29933
29934 CODE LCD_WRC                    \ char --         Write Char
29935     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
29936 BW1 SUB #2,PSP                  \
29937     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
29938     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
29939     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
29940     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
29941 COLON                           \ high level word starts here 
29942     TOP_LCD 2 20_US             \ write high nibble first
29943     TOP_LCD 2 20_US 
29944 ;
29945
29946 CODE LCD_WRF                    \ func --         Write Fonction
29947     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
29948     GOTO BW1
29949 ENDCODE
29950
29951 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
29952 : LCD_HOME $02 LCD_WRF 100 20_us ;
29953
29954 \ [UNDEFINED] OR [IF]
29955
29956 \ \ https://forth-standard.org/standard/core/OR
29957 \ \ C OR     x1 x2 -- x3           logical OR
29958 \ CODE OR
29959 \ BIS @PSP+,TOS
29960 \ MOV @IP+,PC
29961 \ ENDCODE
29962
29963 \ [THEN]
29964
29965 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
29966 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
29967 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
29968 \ : LCD_FN_SET        $20 OR LCD_WrF ;
29969 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
29970 \ : LCD_GOTO          $80 OR LCD_WrF ;
29971
29972
29973 \ CODE LCD_RDS                    \ -- status       Read Status
29974 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
29975 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
29976 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
29977 \ COLON                           \ starts a FORTH word
29978 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
29979 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
29980 \ HI2LO                           \ switch from FORTH to assembler
29981 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
29982 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
29983 \     MOV @RSP+,IP                \ restore IP saved by COLON
29984 \     MOV @IP+,PC                 \
29985 \ ENDCODE
29986
29987 \ CODE LCD_RDC                    \ -- char         Read Char
29988 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
29989 \     GOTO BW1
29990 \ ENDCODE
29991
29992
29993 \ ******************************\
29994 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
29995 \ ******************************\
29996 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
29997 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
29998 BIT.B #SW2,&SW2_IN              \ test switch S2
29999 0= IF                           \ case of switch S2 pressed
30000     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
30001     U< IF
30002         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
30003     THEN
30004 ELSE
30005     BIT.B #SW1,&SW1_IN          \ test switch S1 input
30006     0= IF                       \ case of Switch S1 pressed
30007         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
30008         U>= IF                  \
30009            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
30010         THEN                    \
30011     THEN                        \
30012 THEN                            \
30013 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
30014 RET                             \ 5
30015 ENDASM
30016
30017 \ ******************************\
30018 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
30019 \ ******************************\
30020 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
30021 \ ******************************\
30022 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
30023 \                               \       SMclock = 8|16|24 MHz
30024 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
30025 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
30026 \                               \       SR(9)=new Toggle bit memory (ADD on)
30027 \ ******************************\
30028 \ RC5_FirstStartBitHalfCycle:   \
30029 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
30030 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
30031 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
30032 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
30033 \ [THEN]
30034 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
30035     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
30036 [THEN]
30037 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
30038     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
30039 [THEN]
30040 MOV #1778,X                     \ RC5_Period * 1us
30041 MOV #14,W                       \ count of loop
30042 BEGIN                           \
30043 \ ******************************\
30044 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
30045 \ ******************************\                   |
30046 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
30047 \ RC5_Compute_3/4_Period:       \                   |
30048     RRUM    #1,X                \ X=1/2 cycle       |
30049     MOV     X,Y                 \                   ^
30050     RRUM    #1,Y                \ Y=1/4
30051     ADD     X,Y                 \ Y=3/4 cycle
30052     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
30053     U>= UNTIL                   \ 2
30054 \ ******************************\
30055 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
30056 \ ******************************\
30057     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
30058     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
30059     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
30060     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
30061     SUB     #1,W                \ decrement count loop
30062 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
30063 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
30064 0<> WHILE                       \ ----> out of loop ----+
30065     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
30066     BEGIN                       \                       |
30067         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
30068         CMP Y,X                 \ 1                     |   cycle time out of bound ?
30069         U>= IF                  \ 2                 ^   |   yes:
30070         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
30071         GOTO BW1                \                   |   |      quit on truncated RC5 message
30072         THEN                    \                   |   |
30073         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
30074     0<> UNTIL                   \ 2                 |   |
30075 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
30076 \ ******************************\                       |
30077 \ RC5_SampleEndOf:              \ <---------------------+
30078 \ ******************************\
30079 BIC #$30,&RC5_TIM_CTL           \   stop timer
30080 \ ******************************\
30081 \ RC5_ComputeNewRC5word         \
30082 \ ******************************\
30083 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
30084 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
30085 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
30086 \ ******************************\
30087 \ RC5_ComputeC6bit              \
30088 \ ******************************\
30089 BIT     #BIT14,T                \ test /C6 bit in T
30090 0= IF   BIS #BIT6,X             \ set C6 bit in X
30091 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
30092 \ ******************************\
30093 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
30094 \ ******************************\
30095 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
30096 \ ******************************\
30097 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
30098 XOR     @RSP,T                  \ (new XOR old) Toggle bits
30099 BIT     #UF10,T                 \ repeated RC5_command ?
30100 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
30101 XOR #UF10,0(RSP)                \ 5 toggle bit memory
30102 \ ******************************\
30103 \ Display IR_RC5 code           \
30104 \ ******************************\
30105 SUB #8,PSP                      \ TOS -- x x x x TOS
30106 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
30107 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
30108 MOV #$10,&BASEADR               \                                               set hexadecimal base
30109 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
30110 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
30111 LO2HI                           \                                               switch from assembler to FORTH
30112     LCD_CLEAR                   \                                               set LCD cursor at home
30113     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
30114     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
30115     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
30116     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
30117 HI2LO                           \     --                                        switch from FORTH to assembler
30118 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
30119 MOV @PSP+,TOS                   \     -- TOS
30120 RET
30121 ENDASM
30122
30123 \ ******************************\
30124 ASM BACKGROUND                  \
30125 \ ******************************\
30126 BEGIN
30127 \     ...                         \ insert here your background task
30128 \     ...                         \
30129 \     ...                         \
30130     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
30131     BIS &LPM_MODE,SR            \
30132 \ ******************************\
30133 \ here start all interrupts     \
30134 \ ******************************\
30135 \ here return all interrupts    \
30136 \ ******************************\
30137 AGAIN                           \
30138 ENDASM                          \
30139 \ ******************************\
30140
30141 \ ------------------------------\
30142 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
30143 \ ------------------------------\
30144 \     ...                         \ init specific I/O sys as you want
30145 \     ...                         \ before executing default WARM
30146     MOV #WARM,X                 \ ['] WARM 
30147     ADD #4,X                    \ >BODY
30148     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
30149 ENDASM
30150 \ ------------------------------\
30151
30152 \ ------------------------------\
30153 CODE STOP                       \ stops multitasking, must to be used before downloading app
30154 \ ------------------------------\
30155 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
30156     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
30157     MOV X,-2(X)                 \ restore the default background: SLEEP
30158     MOV #WARM,X
30159     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
30160     BIC.B #RC5,&IR_IE           \ clear RC5_Int
30161     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
30162     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
30163     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
30164     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
30165     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
30166 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
30167 ECHO                            \
30168 ." RC5toLCD is removed,"
30169 ."  type START to restart"
30170  WARM                           \ performs reset to reset all interrupt vectors.    
30171 ;
30172 \ ------------------------------\
30173
30174 \ ------------------------------\
30175 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
30176 \ ------------------------------\
30177 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
30178 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
30179 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
30180 \                           --       \ID input divider \ 10 = /4
30181 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
30182 \                                 -  \TBCLR TimerB Clear
30183 \                                  - \TBIE
30184 \                                   -\TBIFG
30185 \ -------------------------------\
30186 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
30187 \                  --                 \CM Capture Mode
30188 \                    --               \CCIS
30189 \                       -             \SCS
30190 \                        --           \CLLD
30191 \                          -          \CAP
30192 \                            ---      \OUTMOD \ 011 = set/reset
30193 \                               -     \CCIE
30194 \                                 -   \CCI
30195 \                                  -  \OUT
30196 \                                   - \COV
30197 \                                    -\CCIFG
30198 \ -------------------------------\
30199 \ LCD_TIM_CCRx                   \
30200 \ -------------------------------\
30201 \ LCD_TIM_EX0                    \ 
30202 \ ------------------------------\
30203 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
30204 \ ------------------------------\
30205 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
30206 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
30207 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
30208     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
30209 [THEN]
30210 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
30211     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
30212 [THEN]
30213     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
30214 \ ------------------------------\
30215 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
30216 \ ------------------------------\
30217 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
30218     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
30219 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
30220 \ ------------------------------\
30221     BIS.B #LCDVo,&LCDVo_DIR     \
30222     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
30223 \ ------------------------------\
30224     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
30225     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
30226 \ ------------------------------\
30227     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
30228     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
30229 \ ******************************\
30230 \ init RC5_Int                  \
30231 \ ******************************\
30232     BIS.B #RC5,&IR_IE           \ enable RC5_Int
30233     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
30234     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
30235 \ ******************************\
30236 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
30237 \ ******************************\
30238 \              %01 0001 0100    \ TAxCTL
30239 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
30240 \                  --           \ ID        divided by 1
30241 \                    --         \ MC        MODE = up to TAxCCRn
30242 \                        -      \ TACLR     clear timer count
30243 \                         -     \ TAIE
30244 \                          -    \ TAIFG
30245 \ ------------------------------\
30246 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
30247 \ ------------------------------\
30248 \                        000    \ TAxEX0
30249 \                        ---    \ TAIDEX    pre divisor
30250 \ ------------------------------\
30251 \          %0000 0000 0000 0101 \ TAxCCR0
30252     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
30253 \ ------------------------------\
30254 \          %0000 0000 0001 0000 \ TAxCCTL0
30255 \                   -           \ CAP capture/compare mode = compare
30256 \                        -      \ CCIEn
30257 \                             - \ CCIFGn
30258     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
30259 \ ------------------------------\
30260     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
30261 \ ------------------------------\
30262 \ define LPM mode for ACCEPT    \
30263 \ ------------------------------\
30264 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
30265 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
30266 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
30267 \ ------------------------------\
30268 \ activate I/O                  \
30269 \ ------------------------------\
30270 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
30271 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
30272 \ ------------------------------\
30273 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
30274 \ ------------------------------\
30275 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
30276 \ CMP #2,Y                        \ Power_ON event
30277 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
30278 CMP #4,Y                        \
30279 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
30280 \ CMP #6,Y                        \
30281 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
30282 \ CMP #$0A,Y                      \
30283 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
30284 \ CMP #$16,Y                      \
30285 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
30286 \ ------------------------------\
30287 COLON                           \
30288 \ ------------------------------\
30289 \ Init LCD 2x20                 \
30290 \ ------------------------------\
30291     #1000 20_US                 \ 1- wait 20 ms
30292     %011 TOP_LCD                \ 2- send DB5=DB4=1
30293     #205 20_US                  \ 3- wait 4,1 ms
30294     %011 TOP_LCD                \ 4- send again DB5=DB4=1
30295     #5 20_US                    \ 5- wait 0,1 ms
30296     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
30297     #2 20_US                    \    wait 40 us = LCD cycle
30298     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
30299     #2 20_US                    \    wait 40 us = LCD cycle
30300     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
30301     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
30302     LCD_CLEAR                   \ 10- "LCD_Clear"
30303     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
30304     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
30305     LCD_CLEAR                   \ 10- "LCD_Clear"
30306     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
30307     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
30308     CR ." I love you"           \ display message on LCD
30309     ['] CR >BODY IS CR          \ CR executes its default value
30310     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
30311     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
30312     PWR_STATE ABORT             \ init DP and continues with ABORT
30313 ;                               \
30314 \ ------------------------------\
30315
30316 \ ------------------------------\
30317 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
30318 \ ------------------------------\
30319 MOV #SLEEP,X                    \ replace default background process SLEEP
30320 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
30321 MOV #WARM,X                     \ replace default WARM
30322 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
30323 MOV X,PC                        \ then execute new WARM
30324 ENDCODE 
30325 \ ------------------------------\
30326
30327 ECHO
30328             ; downloading RC5toLCD.4th is done
30329 RST_HERE    ; this app is protected against <reset>
30330
30331
30332 RST_STATE
30333
30334 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
30335
30336 [UNDEFINED] MARKER [IF]
30337 \  https://forth-standard.org/standard/core/MARKER
30338 \  MARKER
30339 \ ( "<spaces>name" -- )
30340 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
30341 \ with the execution semantics defined below.
30342
30343 \ name Execution: ( -- )
30344 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
30345 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
30346 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
30347 \ not necessarily provided. No other contextual information such as numeric base is affected
30348 \
30349 : MARKER
30350 CREATE
30351 HI2LO
30352 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
30353 SUB #2,Y            \ 1 Y = LFA
30354 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
30355 ADD #4,&DP          \ 3 add 2 cells
30356 LO2HI
30357 DOES>
30358 HI2LO
30359 MOV @RSP+,IP        \ -- PFA
30360 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
30361 MOV @TOS,&INIDP     \       set DP value for RST_STATE
30362 MOV @PSP+,TOS       \ --
30363 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
30364 ENDCODE
30365 [THEN]
30366
30367 MARKER {RC5TOLCD}
30368
30369 [UNDEFINED] @ [IF]
30370 \ https://forth-standard.org/standard/core/Fetch
30371 \ @     c-addr -- char   fetch char from memory
30372 CODE @
30373 MOV @TOS,TOS
30374 MOV @IP+,PC
30375 ENDCODE
30376 [THEN]
30377
30378 [UNDEFINED] CONSTANT [IF]
30379 \ https://forth-standard.org/standard/core/CONSTANT
30380 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
30381 : CONSTANT 
30382 CREATE
30383 HI2LO
30384 MOV TOS,-2(W)           \   PFA = n
30385 MOV @PSP+,TOS
30386 MOV @RSP+,IP
30387 MOV @IP+,PC
30388 ENDCODE
30389 [THEN]
30390
30391 [UNDEFINED] STATE [IF]
30392 \ https://forth-standard.org/standard/core/STATE
30393 \ STATE   -- a-addr       holds compiler state
30394 STATEADR CONSTANT STATE
30395 [THEN]
30396
30397 [UNDEFINED] = [IF]
30398 \ https://forth-standard.org/standard/core/Equal
30399 \ =      x1 x2 -- flag         test x1=x2
30400 CODE =
30401 SUB @PSP+,TOS   \ 2
30402 0<> IF          \ 2
30403     AND #0,TOS  \ 1
30404     MOV @IP+,PC \ 4
30405 THEN
30406 XOR #-1,TOS     \ 1 flag Z = 1
30407 MOV @IP+,PC     \ 4
30408 ENDCODE
30409 [THEN]
30410
30411 [UNDEFINED] IF [IF]
30412 \ https://forth-standard.org/standard/core/IF
30413 \ IF       -- IFadr    initialize conditional forward branch
30414 CODE IF       \ immediate
30415 SUB #2,PSP              \
30416 MOV TOS,0(PSP)          \
30417 MOV &DP,TOS             \ -- HERE
30418 ADD #4,&DP            \           compile one word, reserve one word
30419 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
30420 ADD #2,TOS              \ -- HERE+2=IFadr
30421 MOV @IP+,PC
30422 ENDCODE IMMEDIATE
30423 [THEN]
30424
30425 [UNDEFINED] THEN [IF]
30426 \ https://forth-standard.org/standard/core/THEN
30427 \ THEN     IFadr --                resolve forward branch
30428 CODE THEN               \ immediate
30429 MOV &DP,0(TOS)          \ -- IFadr
30430 MOV @PSP+,TOS           \ --
30431 MOV @IP+,PC
30432 ENDCODE IMMEDIATE
30433 [THEN]
30434
30435 [UNDEFINED] ELSE [IF]
30436 \ https://forth-standard.org/standard/core/ELSE
30437 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
30438 CODE ELSE     \ immediate
30439 ADD #4,&DP              \ make room to compile two words
30440 MOV &DP,W               \ W=HERE+4
30441 MOV #BRAN,-4(W)
30442 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
30443 SUB #2,W                \ HERE+2
30444 MOV W,TOS               \ -- ELSEadr
30445 MOV @IP+,PC
30446 ENDCODE IMMEDIATE
30447 [THEN]
30448
30449 [UNDEFINED] DEFER [IF]
30450 \ https://forth-standard.org/standard/core/DEFER
30451 \ DEFER "<spaces>name"   --
30452 \ Skip leading space delimiters. Parse name delimited by a space.
30453 \ Create a definition for name with the execution semantics defined below.
30454
30455 \ name Execution:   --
30456 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
30457 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
30458 : DEFER
30459 CREATE
30460 HI2LO
30461 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
30462 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
30463 MOV @RSP+,IP
30464 MOV @IP+,PC
30465 ENDCODE
30466 [THEN]
30467
30468 [UNDEFINED] DEFER! [IF]
30469 \ https://forth-standard.org/standard/core/DEFERStore
30470 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
30471 CODE DEFER!             \ xt2 xt1 --
30472 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
30473 MOV @PSP+,TOS           \ --
30474 MOV @IP+,PC
30475 ENDCODE
30476 [THEN]
30477
30478 [UNDEFINED] IS [IF]
30479 \ https://forth-standard.org/standard/core/IS
30480 \ IS <name>        xt --
30481 \ used as is :
30482 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
30483 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
30484 \ or in a definition : ... ['] U. IS DISPLAY ...
30485 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
30486 \
30487 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
30488 : IS
30489 STATE @
30490 IF  POSTPONE ['] POSTPONE DEFER! 
30491 ELSE ' DEFER! 
30492 THEN
30493 ; IMMEDIATE
30494 [THEN]
30495
30496 [UNDEFINED] >BODY [IF]
30497 \ https://forth-standard.org/standard/core/toBODY
30498 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
30499 CODE >BODY
30500 ADD #4,TOS
30501 MOV @IP+,PC
30502 ENDCODE
30503 [THEN]
30504
30505 \ CODE 20uS           \ n --      8MHz version
30506 \ BEGIN               \ 4 + 16 ~ loop
30507 \     MOV #39,rDOCON   \ 39
30508 \     BEGIN           \ 4 ~ loop
30509 \         NOP
30510 \         SUB #1,rDOCON
30511 \     0=  UNTIL
30512 \     SUB #1,TOS      \ 1
30513 \ 0= UNTIL
30514 \ MOV #XDOCON,rDOCON  \ 2
30515 \ MOV @PSP+,TOS
30516 \ MOV @RSP+,IP        \
30517 \ ENDCODE
30518
30519 CODE 20_US                      \ n --      n * 20 us
30520 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
30521     BEGIN
30522         BIT #1,&LCD_TIM_CTL     \ 3
30523     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
30524     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
30525     SUB #1,TOS                  \ 1
30526 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
30527 MOV @PSP+,TOS                   \ 2
30528 MOV @IP+,PC                     \ 4
30529 ENDCODE
30530
30531 CODE TOP_LCD                    \ LCD Sample
30532 \                               \ if write : %xxxx_WWWW --
30533 \                               \ if read  : -- %0000_RRRR
30534     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
30535     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
30536 0= IF                           \ write LCD bits pattern
30537     AND.B #LCD_DB,TOS           \ 
30538     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
30539     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
30540     MOV @PSP+,TOS               \
30541     MOV @IP+,PC
30542 THEN                            \ read LCD bits pattern
30543     SUB #2,PSP
30544     MOV TOS,0(PSP)
30545     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
30546     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
30547     AND.B #LCD_DB,TOS           \
30548     MOV @IP+,PC
30549 ENDCODE
30550
30551 CODE LCD_WRC                    \ char --         Write Char
30552     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
30553 BW1 SUB #2,PSP                  \
30554     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
30555     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
30556     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
30557     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
30558 COLON                           \ high level word starts here 
30559     TOP_LCD 2 20_US             \ write high nibble first
30560     TOP_LCD 2 20_US 
30561 ;
30562
30563 CODE LCD_WRF                    \ func --         Write Fonction
30564     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
30565     GOTO BW1
30566 ENDCODE
30567
30568 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
30569 : LCD_HOME $02 LCD_WRF 100 20_us ;
30570
30571 \ [UNDEFINED] OR [IF]
30572
30573 \ \ https://forth-standard.org/standard/core/OR
30574 \ \ C OR     x1 x2 -- x3           logical OR
30575 \ CODE OR
30576 \ BIS @PSP+,TOS
30577 \ MOV @IP+,PC
30578 \ ENDCODE
30579
30580 \ [THEN]
30581
30582 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
30583 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
30584 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
30585 \ : LCD_FN_SET        $20 OR LCD_WrF ;
30586 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
30587 \ : LCD_GOTO          $80 OR LCD_WrF ;
30588
30589
30590 \ CODE LCD_RDS                    \ -- status       Read Status
30591 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
30592 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
30593 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
30594 \ COLON                           \ starts a FORTH word
30595 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
30596 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
30597 \ HI2LO                           \ switch from FORTH to assembler
30598 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
30599 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
30600 \     MOV @RSP+,IP                \ restore IP saved by COLON
30601 \     MOV @IP+,PC                 \
30602 \ ENDCODE
30603
30604 \ CODE LCD_RDC                    \ -- char         Read Char
30605 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
30606 \     GOTO BW1
30607 \ ENDCODE
30608
30609
30610 \ ******************************\
30611 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
30612 \ ******************************\
30613 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
30614 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
30615 BIT.B #SW2,&SW2_IN              \ test switch S2
30616 0= IF                           \ case of switch S2 pressed
30617     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
30618     U< IF
30619         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
30620     THEN
30621 ELSE
30622     BIT.B #SW1,&SW1_IN          \ test switch S1 input
30623     0= IF                       \ case of Switch S1 pressed
30624         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
30625         U>= IF                  \
30626            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
30627         THEN                    \
30628     THEN                        \
30629 THEN                            \
30630 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
30631 RET                             \ 5
30632 ENDASM
30633
30634 \ ******************************\
30635 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
30636 \ ******************************\
30637 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
30638 \ ******************************\
30639 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
30640 \                               \       SMclock = 8|16|24 MHz
30641 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
30642 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
30643 \                               \       SR(9)=new Toggle bit memory (ADD on)
30644 \ ******************************\
30645 \ RC5_FirstStartBitHalfCycle:   \
30646 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
30647 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
30648 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
30649 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
30650 \ [THEN]
30651 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
30652     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
30653 [THEN]
30654 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
30655     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
30656 [THEN]
30657 MOV #1778,X                     \ RC5_Period * 1us
30658 MOV #14,W                       \ count of loop
30659 BEGIN                           \
30660 \ ******************************\
30661 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
30662 \ ******************************\                   |
30663 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
30664 \ RC5_Compute_3/4_Period:       \                   |
30665     RRUM    #1,X                \ X=1/2 cycle       |
30666     MOV     X,Y                 \                   ^
30667     RRUM    #1,Y                \ Y=1/4
30668     ADD     X,Y                 \ Y=3/4 cycle
30669     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
30670     U>= UNTIL                   \ 2
30671 \ ******************************\
30672 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
30673 \ ******************************\
30674     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
30675     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
30676     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
30677     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
30678     SUB     #1,W                \ decrement count loop
30679 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
30680 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
30681 0<> WHILE                       \ ----> out of loop ----+
30682     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
30683     BEGIN                       \                       |
30684         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
30685         CMP Y,X                 \ 1                     |   cycle time out of bound ?
30686         U>= IF                  \ 2                 ^   |   yes:
30687         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
30688         GOTO BW1                \                   |   |      quit on truncated RC5 message
30689         THEN                    \                   |   |
30690         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
30691     0<> UNTIL                   \ 2                 |   |
30692 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
30693 \ ******************************\                       |
30694 \ RC5_SampleEndOf:              \ <---------------------+
30695 \ ******************************\
30696 BIC #$30,&RC5_TIM_CTL           \   stop timer
30697 \ ******************************\
30698 \ RC5_ComputeNewRC5word         \
30699 \ ******************************\
30700 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
30701 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
30702 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
30703 \ ******************************\
30704 \ RC5_ComputeC6bit              \
30705 \ ******************************\
30706 BIT     #BIT14,T                \ test /C6 bit in T
30707 0= IF   BIS #BIT6,X             \ set C6 bit in X
30708 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
30709 \ ******************************\
30710 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
30711 \ ******************************\
30712 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
30713 \ ******************************\
30714 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
30715 XOR     @RSP,T                  \ (new XOR old) Toggle bits
30716 BIT     #UF10,T                 \ repeated RC5_command ?
30717 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
30718 XOR #UF10,0(RSP)                \ 5 toggle bit memory
30719 \ ******************************\
30720 \ Display IR_RC5 code           \
30721 \ ******************************\
30722 SUB #8,PSP                      \ TOS -- x x x x TOS
30723 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
30724 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
30725 MOV #$10,&BASEADR               \                                               set hexadecimal base
30726 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
30727 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
30728 LO2HI                           \                                               switch from assembler to FORTH
30729     LCD_CLEAR                   \                                               set LCD cursor at home
30730     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
30731     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
30732     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
30733     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
30734 HI2LO                           \     --                                        switch from FORTH to assembler
30735 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
30736 MOV @PSP+,TOS                   \     -- TOS
30737 RET
30738 ENDASM
30739
30740 \ ******************************\
30741 ASM BACKGROUND                  \
30742 \ ******************************\
30743 BEGIN
30744 \     ...                         \ insert here your background task
30745 \     ...                         \
30746 \     ...                         \
30747     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
30748     BIS &LPM_MODE,SR            \
30749 \ ******************************\
30750 \ here start all interrupts     \
30751 \ ******************************\
30752 \ here return all interrupts    \
30753 \ ******************************\
30754 AGAIN                           \
30755 ENDASM                          \
30756 \ ******************************\
30757
30758 \ ------------------------------\
30759 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
30760 \ ------------------------------\
30761 \     ...                         \ init specific I/O sys as you want
30762 \     ...                         \ before executing default WARM
30763     MOV #WARM,X                 \ ['] WARM 
30764     ADD #4,X                    \ >BODY
30765     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
30766 ENDASM
30767 \ ------------------------------\
30768
30769 \ ------------------------------\
30770 CODE STOP                       \ stops multitasking, must to be used before downloading app
30771 \ ------------------------------\
30772 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
30773     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
30774     MOV X,-2(X)                 \ restore the default background: SLEEP
30775     MOV #WARM,X
30776     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
30777     BIC.B #RC5,&IR_IE           \ clear RC5_Int
30778     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
30779     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
30780     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
30781     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
30782     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
30783 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
30784 ECHO                            \
30785 ." RC5toLCD is removed,"
30786 ."  type START to restart"
30787  WARM                           \ performs reset to reset all interrupt vectors.    
30788 ;
30789 \ ------------------------------\
30790
30791 \ ------------------------------\
30792 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
30793 \ ------------------------------\
30794 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
30795 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
30796 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
30797 \                           --       \ID input divider \ 10 = /4
30798 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
30799 \                                 -  \TBCLR TimerB Clear
30800 \                                  - \TBIE
30801 \                                   -\TBIFG
30802 \ -------------------------------\
30803 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
30804 \                  --                 \CM Capture Mode
30805 \                    --               \CCIS
30806 \                       -             \SCS
30807 \                        --           \CLLD
30808 \                          -          \CAP
30809 \                            ---      \OUTMOD \ 011 = set/reset
30810 \                               -     \CCIE
30811 \                                 -   \CCI
30812 \                                  -  \OUT
30813 \                                   - \COV
30814 \                                    -\CCIFG
30815 \ -------------------------------\
30816 \ LCD_TIM_CCRx                   \
30817 \ -------------------------------\
30818 \ LCD_TIM_EX0                    \ 
30819 \ ------------------------------\
30820 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
30821 \ ------------------------------\
30822 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
30823 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
30824 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
30825     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
30826 [THEN]
30827 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
30828     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
30829 [THEN]
30830     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
30831 \ ------------------------------\
30832 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
30833 \ ------------------------------\
30834 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
30835     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
30836 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
30837 \ ------------------------------\
30838     BIS.B #LCDVo,&LCDVo_DIR     \
30839     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
30840 \ ------------------------------\
30841     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
30842     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
30843 \ ------------------------------\
30844     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
30845     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
30846 \ ******************************\
30847 \ init RC5_Int                  \
30848 \ ******************************\
30849     BIS.B #RC5,&IR_IE           \ enable RC5_Int
30850     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
30851     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
30852 \ ******************************\
30853 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
30854 \ ******************************\
30855 \              %01 0001 0100    \ TAxCTL
30856 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
30857 \                  --           \ ID        divided by 1
30858 \                    --         \ MC        MODE = up to TAxCCRn
30859 \                        -      \ TACLR     clear timer count
30860 \                         -     \ TAIE
30861 \                          -    \ TAIFG
30862 \ ------------------------------\
30863 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
30864 \ ------------------------------\
30865 \                        000    \ TAxEX0
30866 \                        ---    \ TAIDEX    pre divisor
30867 \ ------------------------------\
30868 \          %0000 0000 0000 0101 \ TAxCCR0
30869     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
30870 \ ------------------------------\
30871 \          %0000 0000 0001 0000 \ TAxCCTL0
30872 \                   -           \ CAP capture/compare mode = compare
30873 \                        -      \ CCIEn
30874 \                             - \ CCIFGn
30875     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
30876 \ ------------------------------\
30877     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
30878 \ ------------------------------\
30879 \ define LPM mode for ACCEPT    \
30880 \ ------------------------------\
30881 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
30882 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
30883 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
30884 \ ------------------------------\
30885 \ activate I/O                  \
30886 \ ------------------------------\
30887 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
30888 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
30889 \ ------------------------------\
30890 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
30891 \ ------------------------------\
30892 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
30893 \ CMP #2,Y                        \ Power_ON event
30894 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
30895 CMP #4,Y                        \
30896 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
30897 \ CMP #6,Y                        \
30898 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
30899 \ CMP #$0A,Y                      \
30900 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
30901 \ CMP #$16,Y                      \
30902 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
30903 \ ------------------------------\
30904 COLON                           \
30905 \ ------------------------------\
30906 \ Init LCD 2x20                 \
30907 \ ------------------------------\
30908     #1000 20_US                 \ 1- wait 20 ms
30909     %011 TOP_LCD                \ 2- send DB5=DB4=1
30910     #205 20_US                  \ 3- wait 4,1 ms
30911     %011 TOP_LCD                \ 4- send again DB5=DB4=1
30912     #5 20_US                    \ 5- wait 0,1 ms
30913     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
30914     #2 20_US                    \    wait 40 us = LCD cycle
30915     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
30916     #2 20_US                    \    wait 40 us = LCD cycle
30917     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
30918     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
30919     LCD_CLEAR                   \ 10- "LCD_Clear"
30920     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
30921     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
30922     LCD_CLEAR                   \ 10- "LCD_Clear"
30923     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
30924     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
30925     CR ." I love you"           \ display message on LCD
30926     ['] CR >BODY IS CR          \ CR executes its default value
30927     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
30928     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
30929     PWR_STATE ABORT             \ init DP and continues with ABORT
30930 ;                               \
30931 \ ------------------------------\
30932
30933 \ ------------------------------\
30934 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
30935 \ ------------------------------\
30936 MOV #SLEEP,X                    \ replace default background process SLEEP
30937 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
30938 MOV #WARM,X                     \ replace default WARM
30939 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
30940 MOV X,PC                        \ then execute new WARM
30941 ENDCODE 
30942 \ ------------------------------\
30943
30944 ECHO
30945             ; downloading RC5toLCD.4th is done
30946 RST_HERE    ; this app is protected against <reset>
30947
30948
30949 RST_STATE
30950
30951 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
30952
30953 [UNDEFINED] MARKER [IF]
30954 \  https://forth-standard.org/standard/core/MARKER
30955 \  MARKER
30956 \ ( "<spaces>name" -- )
30957 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
30958 \ with the execution semantics defined below.
30959
30960 \ name Execution: ( -- )
30961 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
30962 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
30963 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
30964 \ not necessarily provided. No other contextual information such as numeric base is affected
30965 \
30966 : MARKER
30967 CREATE
30968 HI2LO
30969 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
30970 SUB #2,Y            \ 1 Y = LFA
30971 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
30972 ADD #4,&DP          \ 3 add 2 cells
30973 LO2HI
30974 DOES>
30975 HI2LO
30976 MOV @RSP+,IP        \ -- PFA
30977 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
30978 MOV @TOS,&INIDP     \       set DP value for RST_STATE
30979 MOV @PSP+,TOS       \ --
30980 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
30981 ENDCODE
30982 [THEN]
30983
30984 MARKER {RC5TOLCD}
30985
30986 [UNDEFINED] @ [IF]
30987 \ https://forth-standard.org/standard/core/Fetch
30988 \ @     c-addr -- char   fetch char from memory
30989 CODE @
30990 MOV @TOS,TOS
30991 MOV @IP+,PC
30992 ENDCODE
30993 [THEN]
30994
30995 [UNDEFINED] CONSTANT [IF]
30996 \ https://forth-standard.org/standard/core/CONSTANT
30997 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
30998 : CONSTANT 
30999 CREATE
31000 HI2LO
31001 MOV TOS,-2(W)           \   PFA = n
31002 MOV @PSP+,TOS
31003 MOV @RSP+,IP
31004 MOV @IP+,PC
31005 ENDCODE
31006 [THEN]
31007
31008 [UNDEFINED] STATE [IF]
31009 \ https://forth-standard.org/standard/core/STATE
31010 \ STATE   -- a-addr       holds compiler state
31011 STATEADR CONSTANT STATE
31012 [THEN]
31013
31014 [UNDEFINED] = [IF]
31015 \ https://forth-standard.org/standard/core/Equal
31016 \ =      x1 x2 -- flag         test x1=x2
31017 CODE =
31018 SUB @PSP+,TOS   \ 2
31019 0<> IF          \ 2
31020     AND #0,TOS  \ 1
31021     MOV @IP+,PC \ 4
31022 THEN
31023 XOR #-1,TOS     \ 1 flag Z = 1
31024 MOV @IP+,PC     \ 4
31025 ENDCODE
31026 [THEN]
31027
31028 [UNDEFINED] IF [IF]
31029 \ https://forth-standard.org/standard/core/IF
31030 \ IF       -- IFadr    initialize conditional forward branch
31031 CODE IF       \ immediate
31032 SUB #2,PSP              \
31033 MOV TOS,0(PSP)          \
31034 MOV &DP,TOS             \ -- HERE
31035 ADD #4,&DP            \           compile one word, reserve one word
31036 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
31037 ADD #2,TOS              \ -- HERE+2=IFadr
31038 MOV @IP+,PC
31039 ENDCODE IMMEDIATE
31040 [THEN]
31041
31042 [UNDEFINED] THEN [IF]
31043 \ https://forth-standard.org/standard/core/THEN
31044 \ THEN     IFadr --                resolve forward branch
31045 CODE THEN               \ immediate
31046 MOV &DP,0(TOS)          \ -- IFadr
31047 MOV @PSP+,TOS           \ --
31048 MOV @IP+,PC
31049 ENDCODE IMMEDIATE
31050 [THEN]
31051
31052 [UNDEFINED] ELSE [IF]
31053 \ https://forth-standard.org/standard/core/ELSE
31054 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
31055 CODE ELSE     \ immediate
31056 ADD #4,&DP              \ make room to compile two words
31057 MOV &DP,W               \ W=HERE+4
31058 MOV #BRAN,-4(W)
31059 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
31060 SUB #2,W                \ HERE+2
31061 MOV W,TOS               \ -- ELSEadr
31062 MOV @IP+,PC
31063 ENDCODE IMMEDIATE
31064 [THEN]
31065
31066 [UNDEFINED] DEFER [IF]
31067 \ https://forth-standard.org/standard/core/DEFER
31068 \ DEFER "<spaces>name"   --
31069 \ Skip leading space delimiters. Parse name delimited by a space.
31070 \ Create a definition for name with the execution semantics defined below.
31071
31072 \ name Execution:   --
31073 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
31074 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
31075 : DEFER
31076 CREATE
31077 HI2LO
31078 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
31079 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
31080 MOV @RSP+,IP
31081 MOV @IP+,PC
31082 ENDCODE
31083 [THEN]
31084
31085 [UNDEFINED] DEFER! [IF]
31086 \ https://forth-standard.org/standard/core/DEFERStore
31087 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
31088 CODE DEFER!             \ xt2 xt1 --
31089 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
31090 MOV @PSP+,TOS           \ --
31091 MOV @IP+,PC
31092 ENDCODE
31093 [THEN]
31094
31095 [UNDEFINED] IS [IF]
31096 \ https://forth-standard.org/standard/core/IS
31097 \ IS <name>        xt --
31098 \ used as is :
31099 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
31100 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
31101 \ or in a definition : ... ['] U. IS DISPLAY ...
31102 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
31103 \
31104 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
31105 : IS
31106 STATE @
31107 IF  POSTPONE ['] POSTPONE DEFER! 
31108 ELSE ' DEFER! 
31109 THEN
31110 ; IMMEDIATE
31111 [THEN]
31112
31113 [UNDEFINED] >BODY [IF]
31114 \ https://forth-standard.org/standard/core/toBODY
31115 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
31116 CODE >BODY
31117 ADD #4,TOS
31118 MOV @IP+,PC
31119 ENDCODE
31120 [THEN]
31121
31122 \ CODE 20uS           \ n --      8MHz version
31123 \ BEGIN               \ 4 + 16 ~ loop
31124 \     MOV #39,rDOCON   \ 39
31125 \     BEGIN           \ 4 ~ loop
31126 \         NOP
31127 \         SUB #1,rDOCON
31128 \     0=  UNTIL
31129 \     SUB #1,TOS      \ 1
31130 \ 0= UNTIL
31131 \ MOV #XDOCON,rDOCON  \ 2
31132 \ MOV @PSP+,TOS
31133 \ MOV @RSP+,IP        \
31134 \ ENDCODE
31135
31136 CODE 20_US                      \ n --      n * 20 us
31137 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
31138     BEGIN
31139         BIT #1,&LCD_TIM_CTL     \ 3
31140     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
31141     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
31142     SUB #1,TOS                  \ 1
31143 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
31144 MOV @PSP+,TOS                   \ 2
31145 MOV @IP+,PC                     \ 4
31146 ENDCODE
31147
31148 CODE TOP_LCD                    \ LCD Sample
31149 \                               \ if write : %xxxx_WWWW --
31150 \                               \ if read  : -- %0000_RRRR
31151     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
31152     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
31153 0= IF                           \ write LCD bits pattern
31154     AND.B #LCD_DB,TOS           \ 
31155     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
31156     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
31157     MOV @PSP+,TOS               \
31158     MOV @IP+,PC
31159 THEN                            \ read LCD bits pattern
31160     SUB #2,PSP
31161     MOV TOS,0(PSP)
31162     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
31163     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
31164     AND.B #LCD_DB,TOS           \
31165     MOV @IP+,PC
31166 ENDCODE
31167
31168 CODE LCD_WRC                    \ char --         Write Char
31169     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
31170 BW1 SUB #2,PSP                  \
31171     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
31172     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
31173     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
31174     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
31175 COLON                           \ high level word starts here 
31176     TOP_LCD 2 20_US             \ write high nibble first
31177     TOP_LCD 2 20_US 
31178 ;
31179
31180 CODE LCD_WRF                    \ func --         Write Fonction
31181     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
31182     GOTO BW1
31183 ENDCODE
31184
31185 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
31186 : LCD_HOME $02 LCD_WRF 100 20_us ;
31187
31188 \ [UNDEFINED] OR [IF]
31189
31190 \ \ https://forth-standard.org/standard/core/OR
31191 \ \ C OR     x1 x2 -- x3           logical OR
31192 \ CODE OR
31193 \ BIS @PSP+,TOS
31194 \ MOV @IP+,PC
31195 \ ENDCODE
31196
31197 \ [THEN]
31198
31199 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
31200 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
31201 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
31202 \ : LCD_FN_SET        $20 OR LCD_WrF ;
31203 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
31204 \ : LCD_GOTO          $80 OR LCD_WrF ;
31205
31206
31207 \ CODE LCD_RDS                    \ -- status       Read Status
31208 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
31209 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
31210 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
31211 \ COLON                           \ starts a FORTH word
31212 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
31213 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
31214 \ HI2LO                           \ switch from FORTH to assembler
31215 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
31216 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
31217 \     MOV @RSP+,IP                \ restore IP saved by COLON
31218 \     MOV @IP+,PC                 \
31219 \ ENDCODE
31220
31221 \ CODE LCD_RDC                    \ -- char         Read Char
31222 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
31223 \     GOTO BW1
31224 \ ENDCODE
31225
31226
31227 \ ******************************\
31228 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
31229 \ ******************************\
31230 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
31231 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
31232 BIT.B #SW2,&SW2_IN              \ test switch S2
31233 0= IF                           \ case of switch S2 pressed
31234     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
31235     U< IF
31236         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
31237     THEN
31238 ELSE
31239     BIT.B #SW1,&SW1_IN          \ test switch S1 input
31240     0= IF                       \ case of Switch S1 pressed
31241         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
31242         U>= IF                  \
31243            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
31244         THEN                    \
31245     THEN                        \
31246 THEN                            \
31247 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
31248 RET                             \ 5
31249 ENDASM
31250
31251 \ ******************************\
31252 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
31253 \ ******************************\
31254 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
31255 \ ******************************\
31256 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
31257 \                               \       SMclock = 8|16|24 MHz
31258 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
31259 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
31260 \                               \       SR(9)=new Toggle bit memory (ADD on)
31261 \ ******************************\
31262 \ RC5_FirstStartBitHalfCycle:   \
31263 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
31264 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
31265 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
31266 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
31267 \ [THEN]
31268 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
31269     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
31270 [THEN]
31271 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
31272     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
31273 [THEN]
31274 MOV #1778,X                     \ RC5_Period * 1us
31275 MOV #14,W                       \ count of loop
31276 BEGIN                           \
31277 \ ******************************\
31278 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
31279 \ ******************************\                   |
31280 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
31281 \ RC5_Compute_3/4_Period:       \                   |
31282     RRUM    #1,X                \ X=1/2 cycle       |
31283     MOV     X,Y                 \                   ^
31284     RRUM    #1,Y                \ Y=1/4
31285     ADD     X,Y                 \ Y=3/4 cycle
31286     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
31287     U>= UNTIL                   \ 2
31288 \ ******************************\
31289 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
31290 \ ******************************\
31291     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
31292     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
31293     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
31294     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
31295     SUB     #1,W                \ decrement count loop
31296 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
31297 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
31298 0<> WHILE                       \ ----> out of loop ----+
31299     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
31300     BEGIN                       \                       |
31301         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
31302         CMP Y,X                 \ 1                     |   cycle time out of bound ?
31303         U>= IF                  \ 2                 ^   |   yes:
31304         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
31305         GOTO BW1                \                   |   |      quit on truncated RC5 message
31306         THEN                    \                   |   |
31307         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
31308     0<> UNTIL                   \ 2                 |   |
31309 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
31310 \ ******************************\                       |
31311 \ RC5_SampleEndOf:              \ <---------------------+
31312 \ ******************************\
31313 BIC #$30,&RC5_TIM_CTL           \   stop timer
31314 \ ******************************\
31315 \ RC5_ComputeNewRC5word         \
31316 \ ******************************\
31317 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
31318 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
31319 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
31320 \ ******************************\
31321 \ RC5_ComputeC6bit              \
31322 \ ******************************\
31323 BIT     #BIT14,T                \ test /C6 bit in T
31324 0= IF   BIS #BIT6,X             \ set C6 bit in X
31325 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
31326 \ ******************************\
31327 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
31328 \ ******************************\
31329 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
31330 \ ******************************\
31331 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
31332 XOR     @RSP,T                  \ (new XOR old) Toggle bits
31333 BIT     #UF10,T                 \ repeated RC5_command ?
31334 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
31335 XOR #UF10,0(RSP)                \ 5 toggle bit memory
31336 \ ******************************\
31337 \ Display IR_RC5 code           \
31338 \ ******************************\
31339 SUB #8,PSP                      \ TOS -- x x x x TOS
31340 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
31341 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
31342 MOV #$10,&BASEADR               \                                               set hexadecimal base
31343 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
31344 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
31345 LO2HI                           \                                               switch from assembler to FORTH
31346     LCD_CLEAR                   \                                               set LCD cursor at home
31347     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
31348     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
31349     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
31350     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
31351 HI2LO                           \     --                                        switch from FORTH to assembler
31352 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
31353 MOV @PSP+,TOS                   \     -- TOS
31354 RET
31355 ENDASM
31356
31357 \ ******************************\
31358 ASM BACKGROUND                  \
31359 \ ******************************\
31360 BEGIN
31361 \     ...                         \ insert here your background task
31362 \     ...                         \
31363 \     ...                         \
31364     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
31365     BIS &LPM_MODE,SR            \
31366 \ ******************************\
31367 \ here start all interrupts     \
31368 \ ******************************\
31369 \ here return all interrupts    \
31370 \ ******************************\
31371 AGAIN                           \
31372 ENDASM                          \
31373 \ ******************************\
31374
31375 \ ------------------------------\
31376 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
31377 \ ------------------------------\
31378 \     ...                         \ init specific I/O sys as you want
31379 \     ...                         \ before executing default WARM
31380     MOV #WARM,X                 \ ['] WARM 
31381     ADD #4,X                    \ >BODY
31382     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
31383 ENDASM
31384 \ ------------------------------\
31385
31386 \ ------------------------------\
31387 CODE STOP                       \ stops multitasking, must to be used before downloading app
31388 \ ------------------------------\
31389 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
31390     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
31391     MOV X,-2(X)                 \ restore the default background: SLEEP
31392     MOV #WARM,X
31393     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
31394     BIC.B #RC5,&IR_IE           \ clear RC5_Int
31395     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
31396     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
31397     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
31398     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
31399     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
31400 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
31401 ECHO                            \
31402 ." RC5toLCD is removed,"
31403 ."  type START to restart"
31404  WARM                           \ performs reset to reset all interrupt vectors.    
31405 ;
31406 \ ------------------------------\
31407
31408 \ ------------------------------\
31409 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
31410 \ ------------------------------\
31411 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
31412 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
31413 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
31414 \                           --       \ID input divider \ 10 = /4
31415 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
31416 \                                 -  \TBCLR TimerB Clear
31417 \                                  - \TBIE
31418 \                                   -\TBIFG
31419 \ -------------------------------\
31420 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
31421 \                  --                 \CM Capture Mode
31422 \                    --               \CCIS
31423 \                       -             \SCS
31424 \                        --           \CLLD
31425 \                          -          \CAP
31426 \                            ---      \OUTMOD \ 011 = set/reset
31427 \                               -     \CCIE
31428 \                                 -   \CCI
31429 \                                  -  \OUT
31430 \                                   - \COV
31431 \                                    -\CCIFG
31432 \ -------------------------------\
31433 \ LCD_TIM_CCRx                   \
31434 \ -------------------------------\
31435 \ LCD_TIM_EX0                    \ 
31436 \ ------------------------------\
31437 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
31438 \ ------------------------------\
31439 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
31440 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
31441 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
31442     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
31443 [THEN]
31444 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
31445     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
31446 [THEN]
31447     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
31448 \ ------------------------------\
31449 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
31450 \ ------------------------------\
31451 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
31452     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
31453 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
31454 \ ------------------------------\
31455     BIS.B #LCDVo,&LCDVo_DIR     \
31456     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
31457 \ ------------------------------\
31458     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
31459     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
31460 \ ------------------------------\
31461     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
31462     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
31463 \ ******************************\
31464 \ init RC5_Int                  \
31465 \ ******************************\
31466     BIS.B #RC5,&IR_IE           \ enable RC5_Int
31467     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
31468     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
31469 \ ******************************\
31470 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
31471 \ ******************************\
31472 \              %01 0001 0100    \ TAxCTL
31473 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
31474 \                  --           \ ID        divided by 1
31475 \                    --         \ MC        MODE = up to TAxCCRn
31476 \                        -      \ TACLR     clear timer count
31477 \                         -     \ TAIE
31478 \                          -    \ TAIFG
31479 \ ------------------------------\
31480 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
31481 \ ------------------------------\
31482 \                        000    \ TAxEX0
31483 \                        ---    \ TAIDEX    pre divisor
31484 \ ------------------------------\
31485 \          %0000 0000 0000 0101 \ TAxCCR0
31486     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
31487 \ ------------------------------\
31488 \          %0000 0000 0001 0000 \ TAxCCTL0
31489 \                   -           \ CAP capture/compare mode = compare
31490 \                        -      \ CCIEn
31491 \                             - \ CCIFGn
31492     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
31493 \ ------------------------------\
31494     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
31495 \ ------------------------------\
31496 \ define LPM mode for ACCEPT    \
31497 \ ------------------------------\
31498 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
31499 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
31500 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
31501 \ ------------------------------\
31502 \ activate I/O                  \
31503 \ ------------------------------\
31504 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
31505 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
31506 \ ------------------------------\
31507 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
31508 \ ------------------------------\
31509 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
31510 \ CMP #2,Y                        \ Power_ON event
31511 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
31512 CMP #4,Y                        \
31513 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
31514 \ CMP #6,Y                        \
31515 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
31516 \ CMP #$0A,Y                      \
31517 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
31518 \ CMP #$16,Y                      \
31519 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
31520 \ ------------------------------\
31521 COLON                           \
31522 \ ------------------------------\
31523 \ Init LCD 2x20                 \
31524 \ ------------------------------\
31525     #1000 20_US                 \ 1- wait 20 ms
31526     %011 TOP_LCD                \ 2- send DB5=DB4=1
31527     #205 20_US                  \ 3- wait 4,1 ms
31528     %011 TOP_LCD                \ 4- send again DB5=DB4=1
31529     #5 20_US                    \ 5- wait 0,1 ms
31530     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
31531     #2 20_US                    \    wait 40 us = LCD cycle
31532     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
31533     #2 20_US                    \    wait 40 us = LCD cycle
31534     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
31535     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
31536     LCD_CLEAR                   \ 10- "LCD_Clear"
31537     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
31538     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
31539     LCD_CLEAR                   \ 10- "LCD_Clear"
31540     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
31541     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
31542     CR ." I love you"           \ display message on LCD
31543     ['] CR >BODY IS CR          \ CR executes its default value
31544     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
31545     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
31546     PWR_STATE ABORT             \ init DP and continues with ABORT
31547 ;                               \
31548 \ ------------------------------\
31549
31550 \ ------------------------------\
31551 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
31552 \ ------------------------------\
31553 MOV #SLEEP,X                    \ replace default background process SLEEP
31554 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
31555 MOV #WARM,X                     \ replace default WARM
31556 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
31557 MOV X,PC                        \ then execute new WARM
31558 ENDCODE 
31559 \ ------------------------------\
31560
31561 ECHO
31562             ; downloading RC5toLCD.4th is done
31563 RST_HERE    ; this app is protected against <reset>
31564
31565
31566 RST_STATE
31567
31568 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
31569
31570 [UNDEFINED] MARKER [IF]
31571 \  https://forth-standard.org/standard/core/MARKER
31572 \  MARKER
31573 \ ( "<spaces>name" -- )
31574 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
31575 \ with the execution semantics defined below.
31576
31577 \ name Execution: ( -- )
31578 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
31579 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
31580 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
31581 \ not necessarily provided. No other contextual information such as numeric base is affected
31582 \
31583 : MARKER
31584 CREATE
31585 HI2LO
31586 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
31587 SUB #2,Y            \ 1 Y = LFA
31588 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
31589 ADD #4,&DP          \ 3 add 2 cells
31590 LO2HI
31591 DOES>
31592 HI2LO
31593 MOV @RSP+,IP        \ -- PFA
31594 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
31595 MOV @TOS,&INIDP     \       set DP value for RST_STATE
31596 MOV @PSP+,TOS       \ --
31597 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
31598 ENDCODE
31599 [THEN]
31600
31601 MARKER {RC5TOLCD}
31602
31603 [UNDEFINED] @ [IF]
31604 \ https://forth-standard.org/standard/core/Fetch
31605 \ @     c-addr -- char   fetch char from memory
31606 CODE @
31607 MOV @TOS,TOS
31608 MOV @IP+,PC
31609 ENDCODE
31610 [THEN]
31611
31612 [UNDEFINED] CONSTANT [IF]
31613 \ https://forth-standard.org/standard/core/CONSTANT
31614 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
31615 : CONSTANT 
31616 CREATE
31617 HI2LO
31618 MOV TOS,-2(W)           \   PFA = n
31619 MOV @PSP+,TOS
31620 MOV @RSP+,IP
31621 MOV @IP+,PC
31622 ENDCODE
31623 [THEN]
31624
31625 [UNDEFINED] STATE [IF]
31626 \ https://forth-standard.org/standard/core/STATE
31627 \ STATE   -- a-addr       holds compiler state
31628 STATEADR CONSTANT STATE
31629 [THEN]
31630
31631 [UNDEFINED] = [IF]
31632 \ https://forth-standard.org/standard/core/Equal
31633 \ =      x1 x2 -- flag         test x1=x2
31634 CODE =
31635 SUB @PSP+,TOS   \ 2
31636 0<> IF          \ 2
31637     AND #0,TOS  \ 1
31638     MOV @IP+,PC \ 4
31639 THEN
31640 XOR #-1,TOS     \ 1 flag Z = 1
31641 MOV @IP+,PC     \ 4
31642 ENDCODE
31643 [THEN]
31644
31645 [UNDEFINED] IF [IF]
31646 \ https://forth-standard.org/standard/core/IF
31647 \ IF       -- IFadr    initialize conditional forward branch
31648 CODE IF       \ immediate
31649 SUB #2,PSP              \
31650 MOV TOS,0(PSP)          \
31651 MOV &DP,TOS             \ -- HERE
31652 ADD #4,&DP            \           compile one word, reserve one word
31653 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
31654 ADD #2,TOS              \ -- HERE+2=IFadr
31655 MOV @IP+,PC
31656 ENDCODE IMMEDIATE
31657 [THEN]
31658
31659 [UNDEFINED] THEN [IF]
31660 \ https://forth-standard.org/standard/core/THEN
31661 \ THEN     IFadr --                resolve forward branch
31662 CODE THEN               \ immediate
31663 MOV &DP,0(TOS)          \ -- IFadr
31664 MOV @PSP+,TOS           \ --
31665 MOV @IP+,PC
31666 ENDCODE IMMEDIATE
31667 [THEN]
31668
31669 [UNDEFINED] ELSE [IF]
31670 \ https://forth-standard.org/standard/core/ELSE
31671 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
31672 CODE ELSE     \ immediate
31673 ADD #4,&DP              \ make room to compile two words
31674 MOV &DP,W               \ W=HERE+4
31675 MOV #BRAN,-4(W)
31676 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
31677 SUB #2,W                \ HERE+2
31678 MOV W,TOS               \ -- ELSEadr
31679 MOV @IP+,PC
31680 ENDCODE IMMEDIATE
31681 [THEN]
31682
31683 [UNDEFINED] DEFER [IF]
31684 \ https://forth-standard.org/standard/core/DEFER
31685 \ DEFER "<spaces>name"   --
31686 \ Skip leading space delimiters. Parse name delimited by a space.
31687 \ Create a definition for name with the execution semantics defined below.
31688
31689 \ name Execution:   --
31690 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
31691 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
31692 : DEFER
31693 CREATE
31694 HI2LO
31695 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
31696 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
31697 MOV @RSP+,IP
31698 MOV @IP+,PC
31699 ENDCODE
31700 [THEN]
31701
31702 [UNDEFINED] DEFER! [IF]
31703 \ https://forth-standard.org/standard/core/DEFERStore
31704 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
31705 CODE DEFER!             \ xt2 xt1 --
31706 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
31707 MOV @PSP+,TOS           \ --
31708 MOV @IP+,PC
31709 ENDCODE
31710 [THEN]
31711
31712 [UNDEFINED] IS [IF]
31713 \ https://forth-standard.org/standard/core/IS
31714 \ IS <name>        xt --
31715 \ used as is :
31716 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
31717 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
31718 \ or in a definition : ... ['] U. IS DISPLAY ...
31719 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
31720 \
31721 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
31722 : IS
31723 STATE @
31724 IF  POSTPONE ['] POSTPONE DEFER! 
31725 ELSE ' DEFER! 
31726 THEN
31727 ; IMMEDIATE
31728 [THEN]
31729
31730 [UNDEFINED] >BODY [IF]
31731 \ https://forth-standard.org/standard/core/toBODY
31732 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
31733 CODE >BODY
31734 ADD #4,TOS
31735 MOV @IP+,PC
31736 ENDCODE
31737 [THEN]
31738
31739 \ CODE 20uS           \ n --      8MHz version
31740 \ BEGIN               \ 4 + 16 ~ loop
31741 \     MOV #39,rDOCON   \ 39
31742 \     BEGIN           \ 4 ~ loop
31743 \         NOP
31744 \         SUB #1,rDOCON
31745 \     0=  UNTIL
31746 \     SUB #1,TOS      \ 1
31747 \ 0= UNTIL
31748 \ MOV #XDOCON,rDOCON  \ 2
31749 \ MOV @PSP+,TOS
31750 \ MOV @RSP+,IP        \
31751 \ ENDCODE
31752
31753 CODE 20_US                      \ n --      n * 20 us
31754 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
31755     BEGIN
31756         BIT #1,&LCD_TIM_CTL     \ 3
31757     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
31758     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
31759     SUB #1,TOS                  \ 1
31760 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
31761 MOV @PSP+,TOS                   \ 2
31762 MOV @IP+,PC                     \ 4
31763 ENDCODE
31764
31765 CODE TOP_LCD                    \ LCD Sample
31766 \                               \ if write : %xxxx_WWWW --
31767 \                               \ if read  : -- %0000_RRRR
31768     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
31769     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
31770 0= IF                           \ write LCD bits pattern
31771     AND.B #LCD_DB,TOS           \ 
31772     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
31773     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
31774     MOV @PSP+,TOS               \
31775     MOV @IP+,PC
31776 THEN                            \ read LCD bits pattern
31777     SUB #2,PSP
31778     MOV TOS,0(PSP)
31779     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
31780     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
31781     AND.B #LCD_DB,TOS           \
31782     MOV @IP+,PC
31783 ENDCODE
31784
31785 CODE LCD_WRC                    \ char --         Write Char
31786     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
31787 BW1 SUB #2,PSP                  \
31788     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
31789     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
31790     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
31791     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
31792 COLON                           \ high level word starts here 
31793     TOP_LCD 2 20_US             \ write high nibble first
31794     TOP_LCD 2 20_US 
31795 ;
31796
31797 CODE LCD_WRF                    \ func --         Write Fonction
31798     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
31799     GOTO BW1
31800 ENDCODE
31801
31802 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
31803 : LCD_HOME $02 LCD_WRF 100 20_us ;
31804
31805 \ [UNDEFINED] OR [IF]
31806
31807 \ \ https://forth-standard.org/standard/core/OR
31808 \ \ C OR     x1 x2 -- x3           logical OR
31809 \ CODE OR
31810 \ BIS @PSP+,TOS
31811 \ MOV @IP+,PC
31812 \ ENDCODE
31813
31814 \ [THEN]
31815
31816 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
31817 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
31818 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
31819 \ : LCD_FN_SET        $20 OR LCD_WrF ;
31820 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
31821 \ : LCD_GOTO          $80 OR LCD_WrF ;
31822
31823
31824 \ CODE LCD_RDS                    \ -- status       Read Status
31825 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
31826 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
31827 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
31828 \ COLON                           \ starts a FORTH word
31829 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
31830 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
31831 \ HI2LO                           \ switch from FORTH to assembler
31832 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
31833 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
31834 \     MOV @RSP+,IP                \ restore IP saved by COLON
31835 \     MOV @IP+,PC                 \
31836 \ ENDCODE
31837
31838 \ CODE LCD_RDC                    \ -- char         Read Char
31839 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
31840 \     GOTO BW1
31841 \ ENDCODE
31842
31843
31844 \ ******************************\
31845 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
31846 \ ******************************\
31847 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
31848 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
31849 BIT.B #SW2,&SW2_IN              \ test switch S2
31850 0= IF                           \ case of switch S2 pressed
31851     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
31852     U< IF
31853         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
31854     THEN
31855 ELSE
31856     BIT.B #SW1,&SW1_IN          \ test switch S1 input
31857     0= IF                       \ case of Switch S1 pressed
31858         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
31859         U>= IF                  \
31860            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
31861         THEN                    \
31862     THEN                        \
31863 THEN                            \
31864 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
31865 RET                             \ 5
31866 ENDASM
31867
31868 \ ******************************\
31869 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
31870 \ ******************************\
31871 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
31872 \ ******************************\
31873 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
31874 \                               \       SMclock = 8|16|24 MHz
31875 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
31876 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
31877 \                               \       SR(9)=new Toggle bit memory (ADD on)
31878 \ ******************************\
31879 \ RC5_FirstStartBitHalfCycle:   \
31880 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
31881 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
31882 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
31883 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
31884 \ [THEN]
31885 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
31886     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
31887 [THEN]
31888 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
31889     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
31890 [THEN]
31891 MOV #1778,X                     \ RC5_Period * 1us
31892 MOV #14,W                       \ count of loop
31893 BEGIN                           \
31894 \ ******************************\
31895 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
31896 \ ******************************\                   |
31897 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
31898 \ RC5_Compute_3/4_Period:       \                   |
31899     RRUM    #1,X                \ X=1/2 cycle       |
31900     MOV     X,Y                 \                   ^
31901     RRUM    #1,Y                \ Y=1/4
31902     ADD     X,Y                 \ Y=3/4 cycle
31903     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
31904     U>= UNTIL                   \ 2
31905 \ ******************************\
31906 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
31907 \ ******************************\
31908     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
31909     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
31910     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
31911     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
31912     SUB     #1,W                \ decrement count loop
31913 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
31914 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
31915 0<> WHILE                       \ ----> out of loop ----+
31916     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
31917     BEGIN                       \                       |
31918         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
31919         CMP Y,X                 \ 1                     |   cycle time out of bound ?
31920         U>= IF                  \ 2                 ^   |   yes:
31921         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
31922         GOTO BW1                \                   |   |      quit on truncated RC5 message
31923         THEN                    \                   |   |
31924         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
31925     0<> UNTIL                   \ 2                 |   |
31926 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
31927 \ ******************************\                       |
31928 \ RC5_SampleEndOf:              \ <---------------------+
31929 \ ******************************\
31930 BIC #$30,&RC5_TIM_CTL           \   stop timer
31931 \ ******************************\
31932 \ RC5_ComputeNewRC5word         \
31933 \ ******************************\
31934 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
31935 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
31936 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
31937 \ ******************************\
31938 \ RC5_ComputeC6bit              \
31939 \ ******************************\
31940 BIT     #BIT14,T                \ test /C6 bit in T
31941 0= IF   BIS #BIT6,X             \ set C6 bit in X
31942 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
31943 \ ******************************\
31944 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
31945 \ ******************************\
31946 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
31947 \ ******************************\
31948 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
31949 XOR     @RSP,T                  \ (new XOR old) Toggle bits
31950 BIT     #UF10,T                 \ repeated RC5_command ?
31951 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
31952 XOR #UF10,0(RSP)                \ 5 toggle bit memory
31953 \ ******************************\
31954 \ Display IR_RC5 code           \
31955 \ ******************************\
31956 SUB #8,PSP                      \ TOS -- x x x x TOS
31957 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
31958 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
31959 MOV #$10,&BASEADR               \                                               set hexadecimal base
31960 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
31961 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
31962 LO2HI                           \                                               switch from assembler to FORTH
31963     LCD_CLEAR                   \                                               set LCD cursor at home
31964     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
31965     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
31966     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
31967     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
31968 HI2LO                           \     --                                        switch from FORTH to assembler
31969 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
31970 MOV @PSP+,TOS                   \     -- TOS
31971 RET
31972 ENDASM
31973
31974 \ ******************************\
31975 ASM BACKGROUND                  \
31976 \ ******************************\
31977 BEGIN
31978 \     ...                         \ insert here your background task
31979 \     ...                         \
31980 \     ...                         \
31981     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
31982     BIS &LPM_MODE,SR            \
31983 \ ******************************\
31984 \ here start all interrupts     \
31985 \ ******************************\
31986 \ here return all interrupts    \
31987 \ ******************************\
31988 AGAIN                           \
31989 ENDASM                          \
31990 \ ******************************\
31991
31992 \ ------------------------------\
31993 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
31994 \ ------------------------------\
31995 \     ...                         \ init specific I/O sys as you want
31996 \     ...                         \ before executing default WARM
31997     MOV #WARM,X                 \ ['] WARM 
31998     ADD #4,X                    \ >BODY
31999     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
32000 ENDASM
32001 \ ------------------------------\
32002
32003 \ ------------------------------\
32004 CODE STOP                       \ stops multitasking, must to be used before downloading app
32005 \ ------------------------------\
32006 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
32007     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
32008     MOV X,-2(X)                 \ restore the default background: SLEEP
32009     MOV #WARM,X
32010     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
32011     BIC.B #RC5,&IR_IE           \ clear RC5_Int
32012     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
32013     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
32014     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
32015     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
32016     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
32017 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
32018 ECHO                            \
32019 ." RC5toLCD is removed,"
32020 ."  type START to restart"
32021  WARM                           \ performs reset to reset all interrupt vectors.    
32022 ;
32023 \ ------------------------------\
32024
32025 \ ------------------------------\
32026 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
32027 \ ------------------------------\
32028 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
32029 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
32030 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
32031 \                           --       \ID input divider \ 10 = /4
32032 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
32033 \                                 -  \TBCLR TimerB Clear
32034 \                                  - \TBIE
32035 \                                   -\TBIFG
32036 \ -------------------------------\
32037 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
32038 \                  --                 \CM Capture Mode
32039 \                    --               \CCIS
32040 \                       -             \SCS
32041 \                        --           \CLLD
32042 \                          -          \CAP
32043 \                            ---      \OUTMOD \ 011 = set/reset
32044 \                               -     \CCIE
32045 \                                 -   \CCI
32046 \                                  -  \OUT
32047 \                                   - \COV
32048 \                                    -\CCIFG
32049 \ -------------------------------\
32050 \ LCD_TIM_CCRx                   \
32051 \ -------------------------------\
32052 \ LCD_TIM_EX0                    \ 
32053 \ ------------------------------\
32054 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
32055 \ ------------------------------\
32056 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
32057 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
32058 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
32059     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
32060 [THEN]
32061 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
32062     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
32063 [THEN]
32064     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
32065 \ ------------------------------\
32066 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
32067 \ ------------------------------\
32068 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
32069     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
32070 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
32071 \ ------------------------------\
32072     BIS.B #LCDVo,&LCDVo_DIR     \
32073     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
32074 \ ------------------------------\
32075     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
32076     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
32077 \ ------------------------------\
32078     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
32079     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
32080 \ ******************************\
32081 \ init RC5_Int                  \
32082 \ ******************************\
32083     BIS.B #RC5,&IR_IE           \ enable RC5_Int
32084     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
32085     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
32086 \ ******************************\
32087 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
32088 \ ******************************\
32089 \              %01 0001 0100    \ TAxCTL
32090 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
32091 \                  --           \ ID        divided by 1
32092 \                    --         \ MC        MODE = up to TAxCCRn
32093 \                        -      \ TACLR     clear timer count
32094 \                         -     \ TAIE
32095 \                          -    \ TAIFG
32096 \ ------------------------------\
32097 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
32098 \ ------------------------------\
32099 \                        000    \ TAxEX0
32100 \                        ---    \ TAIDEX    pre divisor
32101 \ ------------------------------\
32102 \          %0000 0000 0000 0101 \ TAxCCR0
32103     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
32104 \ ------------------------------\
32105 \          %0000 0000 0001 0000 \ TAxCCTL0
32106 \                   -           \ CAP capture/compare mode = compare
32107 \                        -      \ CCIEn
32108 \                             - \ CCIFGn
32109     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
32110 \ ------------------------------\
32111     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
32112 \ ------------------------------\
32113 \ define LPM mode for ACCEPT    \
32114 \ ------------------------------\
32115 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
32116 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
32117 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
32118 \ ------------------------------\
32119 \ activate I/O                  \
32120 \ ------------------------------\
32121 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
32122 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
32123 \ ------------------------------\
32124 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
32125 \ ------------------------------\
32126 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
32127 \ CMP #2,Y                        \ Power_ON event
32128 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
32129 CMP #4,Y                        \
32130 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
32131 \ CMP #6,Y                        \
32132 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
32133 \ CMP #$0A,Y                      \
32134 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
32135 \ CMP #$16,Y                      \
32136 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
32137 \ ------------------------------\
32138 COLON                           \
32139 \ ------------------------------\
32140 \ Init LCD 2x20                 \
32141 \ ------------------------------\
32142     #1000 20_US                 \ 1- wait 20 ms
32143     %011 TOP_LCD                \ 2- send DB5=DB4=1
32144     #205 20_US                  \ 3- wait 4,1 ms
32145     %011 TOP_LCD                \ 4- send again DB5=DB4=1
32146     #5 20_US                    \ 5- wait 0,1 ms
32147     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
32148     #2 20_US                    \    wait 40 us = LCD cycle
32149     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
32150     #2 20_US                    \    wait 40 us = LCD cycle
32151     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
32152     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
32153     LCD_CLEAR                   \ 10- "LCD_Clear"
32154     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
32155     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
32156     LCD_CLEAR                   \ 10- "LCD_Clear"
32157     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
32158     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
32159     CR ." I love you"           \ display message on LCD
32160     ['] CR >BODY IS CR          \ CR executes its default value
32161     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
32162     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
32163     PWR_STATE ABORT             \ init DP and continues with ABORT
32164 ;                               \
32165 \ ------------------------------\
32166
32167 \ ------------------------------\
32168 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
32169 \ ------------------------------\
32170 MOV #SLEEP,X                    \ replace default background process SLEEP
32171 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
32172 MOV #WARM,X                     \ replace default WARM
32173 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
32174 MOV X,PC                        \ then execute new WARM
32175 ENDCODE 
32176 \ ------------------------------\
32177
32178 ECHO
32179             ; downloading RC5toLCD.4th is done
32180 RST_HERE    ; this app is protected against <reset>
32181
32182
32183 RST_STATE
32184
32185 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
32186
32187 [UNDEFINED] MARKER [IF]
32188 \  https://forth-standard.org/standard/core/MARKER
32189 \  MARKER
32190 \ ( "<spaces>name" -- )
32191 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
32192 \ with the execution semantics defined below.
32193
32194 \ name Execution: ( -- )
32195 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
32196 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
32197 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
32198 \ not necessarily provided. No other contextual information such as numeric base is affected
32199 \
32200 : MARKER
32201 CREATE
32202 HI2LO
32203 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
32204 SUB #2,Y            \ 1 Y = LFA
32205 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
32206 ADD #4,&DP          \ 3 add 2 cells
32207 LO2HI
32208 DOES>
32209 HI2LO
32210 MOV @RSP+,IP        \ -- PFA
32211 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
32212 MOV @TOS,&INIDP     \       set DP value for RST_STATE
32213 MOV @PSP+,TOS       \ --
32214 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
32215 ENDCODE
32216 [THEN]
32217
32218 MARKER {RC5TOLCD}
32219
32220 [UNDEFINED] @ [IF]
32221 \ https://forth-standard.org/standard/core/Fetch
32222 \ @     c-addr -- char   fetch char from memory
32223 CODE @
32224 MOV @TOS,TOS
32225 MOV @IP+,PC
32226 ENDCODE
32227 [THEN]
32228
32229 [UNDEFINED] CONSTANT [IF]
32230 \ https://forth-standard.org/standard/core/CONSTANT
32231 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
32232 : CONSTANT 
32233 CREATE
32234 HI2LO
32235 MOV TOS,-2(W)           \   PFA = n
32236 MOV @PSP+,TOS
32237 MOV @RSP+,IP
32238 MOV @IP+,PC
32239 ENDCODE
32240 [THEN]
32241
32242 [UNDEFINED] STATE [IF]
32243 \ https://forth-standard.org/standard/core/STATE
32244 \ STATE   -- a-addr       holds compiler state
32245 STATEADR CONSTANT STATE
32246 [THEN]
32247
32248 [UNDEFINED] = [IF]
32249 \ https://forth-standard.org/standard/core/Equal
32250 \ =      x1 x2 -- flag         test x1=x2
32251 CODE =
32252 SUB @PSP+,TOS   \ 2
32253 0<> IF          \ 2
32254     AND #0,TOS  \ 1
32255     MOV @IP+,PC \ 4
32256 THEN
32257 XOR #-1,TOS     \ 1 flag Z = 1
32258 MOV @IP+,PC     \ 4
32259 ENDCODE
32260 [THEN]
32261
32262 [UNDEFINED] IF [IF]
32263 \ https://forth-standard.org/standard/core/IF
32264 \ IF       -- IFadr    initialize conditional forward branch
32265 CODE IF       \ immediate
32266 SUB #2,PSP              \
32267 MOV TOS,0(PSP)          \
32268 MOV &DP,TOS             \ -- HERE
32269 ADD #4,&DP            \           compile one word, reserve one word
32270 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
32271 ADD #2,TOS              \ -- HERE+2=IFadr
32272 MOV @IP+,PC
32273 ENDCODE IMMEDIATE
32274 [THEN]
32275
32276 [UNDEFINED] THEN [IF]
32277 \ https://forth-standard.org/standard/core/THEN
32278 \ THEN     IFadr --                resolve forward branch
32279 CODE THEN               \ immediate
32280 MOV &DP,0(TOS)          \ -- IFadr
32281 MOV @PSP+,TOS           \ --
32282 MOV @IP+,PC
32283 ENDCODE IMMEDIATE
32284 [THEN]
32285
32286 [UNDEFINED] ELSE [IF]
32287 \ https://forth-standard.org/standard/core/ELSE
32288 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
32289 CODE ELSE     \ immediate
32290 ADD #4,&DP              \ make room to compile two words
32291 MOV &DP,W               \ W=HERE+4
32292 MOV #BRAN,-4(W)
32293 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
32294 SUB #2,W                \ HERE+2
32295 MOV W,TOS               \ -- ELSEadr
32296 MOV @IP+,PC
32297 ENDCODE IMMEDIATE
32298 [THEN]
32299
32300 [UNDEFINED] DEFER [IF]
32301 \ https://forth-standard.org/standard/core/DEFER
32302 \ DEFER "<spaces>name"   --
32303 \ Skip leading space delimiters. Parse name delimited by a space.
32304 \ Create a definition for name with the execution semantics defined below.
32305
32306 \ name Execution:   --
32307 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
32308 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
32309 : DEFER
32310 CREATE
32311 HI2LO
32312 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
32313 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
32314 MOV @RSP+,IP
32315 MOV @IP+,PC
32316 ENDCODE
32317 [THEN]
32318
32319 [UNDEFINED] DEFER! [IF]
32320 \ https://forth-standard.org/standard/core/DEFERStore
32321 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
32322 CODE DEFER!             \ xt2 xt1 --
32323 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
32324 MOV @PSP+,TOS           \ --
32325 MOV @IP+,PC
32326 ENDCODE
32327 [THEN]
32328
32329 [UNDEFINED] IS [IF]
32330 \ https://forth-standard.org/standard/core/IS
32331 \ IS <name>        xt --
32332 \ used as is :
32333 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
32334 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
32335 \ or in a definition : ... ['] U. IS DISPLAY ...
32336 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
32337 \
32338 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
32339 : IS
32340 STATE @
32341 IF  POSTPONE ['] POSTPONE DEFER! 
32342 ELSE ' DEFER! 
32343 THEN
32344 ; IMMEDIATE
32345 [THEN]
32346
32347 [UNDEFINED] >BODY [IF]
32348 \ https://forth-standard.org/standard/core/toBODY
32349 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
32350 CODE >BODY
32351 ADD #4,TOS
32352 MOV @IP+,PC
32353 ENDCODE
32354 [THEN]
32355
32356 \ CODE 20uS           \ n --      8MHz version
32357 \ BEGIN               \ 4 + 16 ~ loop
32358 \     MOV #39,rDOCON   \ 39
32359 \     BEGIN           \ 4 ~ loop
32360 \         NOP
32361 \         SUB #1,rDOCON
32362 \     0=  UNTIL
32363 \     SUB #1,TOS      \ 1
32364 \ 0= UNTIL
32365 \ MOV #XDOCON,rDOCON  \ 2
32366 \ MOV @PSP+,TOS
32367 \ MOV @RSP+,IP        \
32368 \ ENDCODE
32369
32370 CODE 20_US                      \ n --      n * 20 us
32371 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
32372     BEGIN
32373         BIT #1,&LCD_TIM_CTL     \ 3
32374     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
32375     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
32376     SUB #1,TOS                  \ 1
32377 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
32378 MOV @PSP+,TOS                   \ 2
32379 MOV @IP+,PC                     \ 4
32380 ENDCODE
32381
32382 CODE TOP_LCD                    \ LCD Sample
32383 \                               \ if write : %xxxx_WWWW --
32384 \                               \ if read  : -- %0000_RRRR
32385     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
32386     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
32387 0= IF                           \ write LCD bits pattern
32388     AND.B #LCD_DB,TOS           \ 
32389     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
32390     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
32391     MOV @PSP+,TOS               \
32392     MOV @IP+,PC
32393 THEN                            \ read LCD bits pattern
32394     SUB #2,PSP
32395     MOV TOS,0(PSP)
32396     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
32397     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
32398     AND.B #LCD_DB,TOS           \
32399     MOV @IP+,PC
32400 ENDCODE
32401
32402 CODE LCD_WRC                    \ char --         Write Char
32403     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
32404 BW1 SUB #2,PSP                  \
32405     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
32406     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
32407     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
32408     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
32409 COLON                           \ high level word starts here 
32410     TOP_LCD 2 20_US             \ write high nibble first
32411     TOP_LCD 2 20_US 
32412 ;
32413
32414 CODE LCD_WRF                    \ func --         Write Fonction
32415     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
32416     GOTO BW1
32417 ENDCODE
32418
32419 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
32420 : LCD_HOME $02 LCD_WRF 100 20_us ;
32421
32422 \ [UNDEFINED] OR [IF]
32423
32424 \ \ https://forth-standard.org/standard/core/OR
32425 \ \ C OR     x1 x2 -- x3           logical OR
32426 \ CODE OR
32427 \ BIS @PSP+,TOS
32428 \ MOV @IP+,PC
32429 \ ENDCODE
32430
32431 \ [THEN]
32432
32433 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
32434 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
32435 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
32436 \ : LCD_FN_SET        $20 OR LCD_WrF ;
32437 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
32438 \ : LCD_GOTO          $80 OR LCD_WrF ;
32439
32440
32441 \ CODE LCD_RDS                    \ -- status       Read Status
32442 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
32443 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
32444 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
32445 \ COLON                           \ starts a FORTH word
32446 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
32447 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
32448 \ HI2LO                           \ switch from FORTH to assembler
32449 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
32450 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
32451 \     MOV @RSP+,IP                \ restore IP saved by COLON
32452 \     MOV @IP+,PC                 \
32453 \ ENDCODE
32454
32455 \ CODE LCD_RDC                    \ -- char         Read Char
32456 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
32457 \     GOTO BW1
32458 \ ENDCODE
32459
32460
32461 \ ******************************\
32462 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
32463 \ ******************************\
32464 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
32465 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
32466 BIT.B #SW2,&SW2_IN              \ test switch S2
32467 0= IF                           \ case of switch S2 pressed
32468     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
32469     U< IF
32470         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
32471     THEN
32472 ELSE
32473     BIT.B #SW1,&SW1_IN          \ test switch S1 input
32474     0= IF                       \ case of Switch S1 pressed
32475         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
32476         U>= IF                  \
32477            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
32478         THEN                    \
32479     THEN                        \
32480 THEN                            \
32481 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
32482 RET                             \ 5
32483 ENDASM
32484
32485 \ ******************************\
32486 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
32487 \ ******************************\
32488 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
32489 \ ******************************\
32490 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
32491 \                               \       SMclock = 8|16|24 MHz
32492 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
32493 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
32494 \                               \       SR(9)=new Toggle bit memory (ADD on)
32495 \ ******************************\
32496 \ RC5_FirstStartBitHalfCycle:   \
32497 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
32498 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
32499 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
32500 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
32501 \ [THEN]
32502 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
32503     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
32504 [THEN]
32505 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
32506     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
32507 [THEN]
32508 MOV #1778,X                     \ RC5_Period * 1us
32509 MOV #14,W                       \ count of loop
32510 BEGIN                           \
32511 \ ******************************\
32512 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
32513 \ ******************************\                   |
32514 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
32515 \ RC5_Compute_3/4_Period:       \                   |
32516     RRUM    #1,X                \ X=1/2 cycle       |
32517     MOV     X,Y                 \                   ^
32518     RRUM    #1,Y                \ Y=1/4
32519     ADD     X,Y                 \ Y=3/4 cycle
32520     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
32521     U>= UNTIL                   \ 2
32522 \ ******************************\
32523 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
32524 \ ******************************\
32525     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
32526     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
32527     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
32528     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
32529     SUB     #1,W                \ decrement count loop
32530 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
32531 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
32532 0<> WHILE                       \ ----> out of loop ----+
32533     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
32534     BEGIN                       \                       |
32535         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
32536         CMP Y,X                 \ 1                     |   cycle time out of bound ?
32537         U>= IF                  \ 2                 ^   |   yes:
32538         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
32539         GOTO BW1                \                   |   |      quit on truncated RC5 message
32540         THEN                    \                   |   |
32541         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
32542     0<> UNTIL                   \ 2                 |   |
32543 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
32544 \ ******************************\                       |
32545 \ RC5_SampleEndOf:              \ <---------------------+
32546 \ ******************************\
32547 BIC #$30,&RC5_TIM_CTL           \   stop timer
32548 \ ******************************\
32549 \ RC5_ComputeNewRC5word         \
32550 \ ******************************\
32551 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
32552 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
32553 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
32554 \ ******************************\
32555 \ RC5_ComputeC6bit              \
32556 \ ******************************\
32557 BIT     #BIT14,T                \ test /C6 bit in T
32558 0= IF   BIS #BIT6,X             \ set C6 bit in X
32559 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
32560 \ ******************************\
32561 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
32562 \ ******************************\
32563 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
32564 \ ******************************\
32565 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
32566 XOR     @RSP,T                  \ (new XOR old) Toggle bits
32567 BIT     #UF10,T                 \ repeated RC5_command ?
32568 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
32569 XOR #UF10,0(RSP)                \ 5 toggle bit memory
32570 \ ******************************\
32571 \ Display IR_RC5 code           \
32572 \ ******************************\
32573 SUB #8,PSP                      \ TOS -- x x x x TOS
32574 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
32575 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
32576 MOV #$10,&BASEADR               \                                               set hexadecimal base
32577 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
32578 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
32579 LO2HI                           \                                               switch from assembler to FORTH
32580     LCD_CLEAR                   \                                               set LCD cursor at home
32581     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
32582     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
32583     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
32584     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
32585 HI2LO                           \     --                                        switch from FORTH to assembler
32586 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
32587 MOV @PSP+,TOS                   \     -- TOS
32588 RET
32589 ENDASM
32590
32591 \ ******************************\
32592 ASM BACKGROUND                  \
32593 \ ******************************\
32594 BEGIN
32595 \     ...                         \ insert here your background task
32596 \     ...                         \
32597 \     ...                         \
32598     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
32599     BIS &LPM_MODE,SR            \
32600 \ ******************************\
32601 \ here start all interrupts     \
32602 \ ******************************\
32603 \ here return all interrupts    \
32604 \ ******************************\
32605 AGAIN                           \
32606 ENDASM                          \
32607 \ ******************************\
32608
32609 \ ------------------------------\
32610 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
32611 \ ------------------------------\
32612 \     ...                         \ init specific I/O sys as you want
32613 \     ...                         \ before executing default WARM
32614     MOV #WARM,X                 \ ['] WARM 
32615     ADD #4,X                    \ >BODY
32616     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
32617 ENDASM
32618 \ ------------------------------\
32619
32620 \ ------------------------------\
32621 CODE STOP                       \ stops multitasking, must to be used before downloading app
32622 \ ------------------------------\
32623 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
32624     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
32625     MOV X,-2(X)                 \ restore the default background: SLEEP
32626     MOV #WARM,X
32627     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
32628     BIC.B #RC5,&IR_IE           \ clear RC5_Int
32629     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
32630     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
32631     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
32632     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
32633     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
32634 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
32635 ECHO                            \
32636 ." RC5toLCD is removed,"
32637 ."  type START to restart"
32638  WARM                           \ performs reset to reset all interrupt vectors.    
32639 ;
32640 \ ------------------------------\
32641
32642 \ ------------------------------\
32643 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
32644 \ ------------------------------\
32645 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
32646 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
32647 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
32648 \                           --       \ID input divider \ 10 = /4
32649 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
32650 \                                 -  \TBCLR TimerB Clear
32651 \                                  - \TBIE
32652 \                                   -\TBIFG
32653 \ -------------------------------\
32654 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
32655 \                  --                 \CM Capture Mode
32656 \                    --               \CCIS
32657 \                       -             \SCS
32658 \                        --           \CLLD
32659 \                          -          \CAP
32660 \                            ---      \OUTMOD \ 011 = set/reset
32661 \                               -     \CCIE
32662 \                                 -   \CCI
32663 \                                  -  \OUT
32664 \                                   - \COV
32665 \                                    -\CCIFG
32666 \ -------------------------------\
32667 \ LCD_TIM_CCRx                   \
32668 \ -------------------------------\
32669 \ LCD_TIM_EX0                    \ 
32670 \ ------------------------------\
32671 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
32672 \ ------------------------------\
32673 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
32674 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
32675 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
32676     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
32677 [THEN]
32678 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
32679     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
32680 [THEN]
32681     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
32682 \ ------------------------------\
32683 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
32684 \ ------------------------------\
32685 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
32686     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
32687 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
32688 \ ------------------------------\
32689     BIS.B #LCDVo,&LCDVo_DIR     \
32690     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
32691 \ ------------------------------\
32692     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
32693     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
32694 \ ------------------------------\
32695     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
32696     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
32697 \ ******************************\
32698 \ init RC5_Int                  \
32699 \ ******************************\
32700     BIS.B #RC5,&IR_IE           \ enable RC5_Int
32701     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
32702     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
32703 \ ******************************\
32704 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
32705 \ ******************************\
32706 \              %01 0001 0100    \ TAxCTL
32707 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
32708 \                  --           \ ID        divided by 1
32709 \                    --         \ MC        MODE = up to TAxCCRn
32710 \                        -      \ TACLR     clear timer count
32711 \                         -     \ TAIE
32712 \                          -    \ TAIFG
32713 \ ------------------------------\
32714 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
32715 \ ------------------------------\
32716 \                        000    \ TAxEX0
32717 \                        ---    \ TAIDEX    pre divisor
32718 \ ------------------------------\
32719 \          %0000 0000 0000 0101 \ TAxCCR0
32720     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
32721 \ ------------------------------\
32722 \          %0000 0000 0001 0000 \ TAxCCTL0
32723 \                   -           \ CAP capture/compare mode = compare
32724 \                        -      \ CCIEn
32725 \                             - \ CCIFGn
32726     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
32727 \ ------------------------------\
32728     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
32729 \ ------------------------------\
32730 \ define LPM mode for ACCEPT    \
32731 \ ------------------------------\
32732 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
32733 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
32734 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
32735 \ ------------------------------\
32736 \ activate I/O                  \
32737 \ ------------------------------\
32738 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
32739 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
32740 \ ------------------------------\
32741 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
32742 \ ------------------------------\
32743 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
32744 \ CMP #2,Y                        \ Power_ON event
32745 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
32746 CMP #4,Y                        \
32747 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
32748 \ CMP #6,Y                        \
32749 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
32750 \ CMP #$0A,Y                      \
32751 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
32752 \ CMP #$16,Y                      \
32753 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
32754 \ ------------------------------\
32755 COLON                           \
32756 \ ------------------------------\
32757 \ Init LCD 2x20                 \
32758 \ ------------------------------\
32759     #1000 20_US                 \ 1- wait 20 ms
32760     %011 TOP_LCD                \ 2- send DB5=DB4=1
32761     #205 20_US                  \ 3- wait 4,1 ms
32762     %011 TOP_LCD                \ 4- send again DB5=DB4=1
32763     #5 20_US                    \ 5- wait 0,1 ms
32764     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
32765     #2 20_US                    \    wait 40 us = LCD cycle
32766     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
32767     #2 20_US                    \    wait 40 us = LCD cycle
32768     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
32769     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
32770     LCD_CLEAR                   \ 10- "LCD_Clear"
32771     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
32772     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
32773     LCD_CLEAR                   \ 10- "LCD_Clear"
32774     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
32775     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
32776     CR ." I love you"           \ display message on LCD
32777     ['] CR >BODY IS CR          \ CR executes its default value
32778     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
32779     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
32780     PWR_STATE ABORT             \ init DP and continues with ABORT
32781 ;                               \
32782 \ ------------------------------\
32783
32784 \ ------------------------------\
32785 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
32786 \ ------------------------------\
32787 MOV #SLEEP,X                    \ replace default background process SLEEP
32788 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
32789 MOV #WARM,X                     \ replace default WARM
32790 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
32791 MOV X,PC                        \ then execute new WARM
32792 ENDCODE 
32793 \ ------------------------------\
32794
32795 ECHO
32796             ; downloading RC5toLCD.4th is done
32797 RST_HERE    ; this app is protected against <reset>
32798
32799
32800 RST_STATE
32801
32802 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
32803
32804 [UNDEFINED] MARKER [IF]
32805 \  https://forth-standard.org/standard/core/MARKER
32806 \  MARKER
32807 \ ( "<spaces>name" -- )
32808 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
32809 \ with the execution semantics defined below.
32810
32811 \ name Execution: ( -- )
32812 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
32813 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
32814 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
32815 \ not necessarily provided. No other contextual information such as numeric base is affected
32816 \
32817 : MARKER
32818 CREATE
32819 HI2LO
32820 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
32821 SUB #2,Y            \ 1 Y = LFA
32822 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
32823 ADD #4,&DP          \ 3 add 2 cells
32824 LO2HI
32825 DOES>
32826 HI2LO
32827 MOV @RSP+,IP        \ -- PFA
32828 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
32829 MOV @TOS,&INIDP     \       set DP value for RST_STATE
32830 MOV @PSP+,TOS       \ --
32831 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
32832 ENDCODE
32833 [THEN]
32834
32835 MARKER {RC5TOLCD}
32836
32837 [UNDEFINED] @ [IF]
32838 \ https://forth-standard.org/standard/core/Fetch
32839 \ @     c-addr -- char   fetch char from memory
32840 CODE @
32841 MOV @TOS,TOS
32842 MOV @IP+,PC
32843 ENDCODE
32844 [THEN]
32845
32846 [UNDEFINED] CONSTANT [IF]
32847 \ https://forth-standard.org/standard/core/CONSTANT
32848 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
32849 : CONSTANT 
32850 CREATE
32851 HI2LO
32852 MOV TOS,-2(W)           \   PFA = n
32853 MOV @PSP+,TOS
32854 MOV @RSP+,IP
32855 MOV @IP+,PC
32856 ENDCODE
32857 [THEN]
32858
32859 [UNDEFINED] STATE [IF]
32860 \ https://forth-standard.org/standard/core/STATE
32861 \ STATE   -- a-addr       holds compiler state
32862 STATEADR CONSTANT STATE
32863 [THEN]
32864
32865 [UNDEFINED] = [IF]
32866 \ https://forth-standard.org/standard/core/Equal
32867 \ =      x1 x2 -- flag         test x1=x2
32868 CODE =
32869 SUB @PSP+,TOS   \ 2
32870 0<> IF          \ 2
32871     AND #0,TOS  \ 1
32872     MOV @IP+,PC \ 4
32873 THEN
32874 XOR #-1,TOS     \ 1 flag Z = 1
32875 MOV @IP+,PC     \ 4
32876 ENDCODE
32877 [THEN]
32878
32879 [UNDEFINED] IF [IF]
32880 \ https://forth-standard.org/standard/core/IF
32881 \ IF       -- IFadr    initialize conditional forward branch
32882 CODE IF       \ immediate
32883 SUB #2,PSP              \
32884 MOV TOS,0(PSP)          \
32885 MOV &DP,TOS             \ -- HERE
32886 ADD #4,&DP            \           compile one word, reserve one word
32887 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
32888 ADD #2,TOS              \ -- HERE+2=IFadr
32889 MOV @IP+,PC
32890 ENDCODE IMMEDIATE
32891 [THEN]
32892
32893 [UNDEFINED] THEN [IF]
32894 \ https://forth-standard.org/standard/core/THEN
32895 \ THEN     IFadr --                resolve forward branch
32896 CODE THEN               \ immediate
32897 MOV &DP,0(TOS)          \ -- IFadr
32898 MOV @PSP+,TOS           \ --
32899 MOV @IP+,PC
32900 ENDCODE IMMEDIATE
32901 [THEN]
32902
32903 [UNDEFINED] ELSE [IF]
32904 \ https://forth-standard.org/standard/core/ELSE
32905 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
32906 CODE ELSE     \ immediate
32907 ADD #4,&DP              \ make room to compile two words
32908 MOV &DP,W               \ W=HERE+4
32909 MOV #BRAN,-4(W)
32910 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
32911 SUB #2,W                \ HERE+2
32912 MOV W,TOS               \ -- ELSEadr
32913 MOV @IP+,PC
32914 ENDCODE IMMEDIATE
32915 [THEN]
32916
32917 [UNDEFINED] DEFER [IF]
32918 \ https://forth-standard.org/standard/core/DEFER
32919 \ DEFER "<spaces>name"   --
32920 \ Skip leading space delimiters. Parse name delimited by a space.
32921 \ Create a definition for name with the execution semantics defined below.
32922
32923 \ name Execution:   --
32924 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
32925 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
32926 : DEFER
32927 CREATE
32928 HI2LO
32929 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
32930 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
32931 MOV @RSP+,IP
32932 MOV @IP+,PC
32933 ENDCODE
32934 [THEN]
32935
32936 [UNDEFINED] DEFER! [IF]
32937 \ https://forth-standard.org/standard/core/DEFERStore
32938 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
32939 CODE DEFER!             \ xt2 xt1 --
32940 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
32941 MOV @PSP+,TOS           \ --
32942 MOV @IP+,PC
32943 ENDCODE
32944 [THEN]
32945
32946 [UNDEFINED] IS [IF]
32947 \ https://forth-standard.org/standard/core/IS
32948 \ IS <name>        xt --
32949 \ used as is :
32950 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
32951 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
32952 \ or in a definition : ... ['] U. IS DISPLAY ...
32953 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
32954 \
32955 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
32956 : IS
32957 STATE @
32958 IF  POSTPONE ['] POSTPONE DEFER! 
32959 ELSE ' DEFER! 
32960 THEN
32961 ; IMMEDIATE
32962 [THEN]
32963
32964 [UNDEFINED] >BODY [IF]
32965 \ https://forth-standard.org/standard/core/toBODY
32966 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
32967 CODE >BODY
32968 ADD #4,TOS
32969 MOV @IP+,PC
32970 ENDCODE
32971 [THEN]
32972
32973 \ CODE 20uS           \ n --      8MHz version
32974 \ BEGIN               \ 4 + 16 ~ loop
32975 \     MOV #39,rDOCON   \ 39
32976 \     BEGIN           \ 4 ~ loop
32977 \         NOP
32978 \         SUB #1,rDOCON
32979 \     0=  UNTIL
32980 \     SUB #1,TOS      \ 1
32981 \ 0= UNTIL
32982 \ MOV #XDOCON,rDOCON  \ 2
32983 \ MOV @PSP+,TOS
32984 \ MOV @RSP+,IP        \
32985 \ ENDCODE
32986
32987 CODE 20_US                      \ n --      n * 20 us
32988 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
32989     BEGIN
32990         BIT #1,&LCD_TIM_CTL     \ 3
32991     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
32992     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
32993     SUB #1,TOS                  \ 1
32994 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
32995 MOV @PSP+,TOS                   \ 2
32996 MOV @IP+,PC                     \ 4
32997 ENDCODE
32998
32999 CODE TOP_LCD                    \ LCD Sample
33000 \                               \ if write : %xxxx_WWWW --
33001 \                               \ if read  : -- %0000_RRRR
33002     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
33003     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
33004 0= IF                           \ write LCD bits pattern
33005     AND.B #LCD_DB,TOS           \ 
33006     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
33007     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
33008     MOV @PSP+,TOS               \
33009     MOV @IP+,PC
33010 THEN                            \ read LCD bits pattern
33011     SUB #2,PSP
33012     MOV TOS,0(PSP)
33013     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
33014     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
33015     AND.B #LCD_DB,TOS           \
33016     MOV @IP+,PC
33017 ENDCODE
33018
33019 CODE LCD_WRC                    \ char --         Write Char
33020     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
33021 BW1 SUB #2,PSP                  \
33022     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
33023     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
33024     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
33025     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
33026 COLON                           \ high level word starts here 
33027     TOP_LCD 2 20_US             \ write high nibble first
33028     TOP_LCD 2 20_US 
33029 ;
33030
33031 CODE LCD_WRF                    \ func --         Write Fonction
33032     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
33033     GOTO BW1
33034 ENDCODE
33035
33036 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
33037 : LCD_HOME $02 LCD_WRF 100 20_us ;
33038
33039 \ [UNDEFINED] OR [IF]
33040
33041 \ \ https://forth-standard.org/standard/core/OR
33042 \ \ C OR     x1 x2 -- x3           logical OR
33043 \ CODE OR
33044 \ BIS @PSP+,TOS
33045 \ MOV @IP+,PC
33046 \ ENDCODE
33047
33048 \ [THEN]
33049
33050 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
33051 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
33052 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
33053 \ : LCD_FN_SET        $20 OR LCD_WrF ;
33054 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
33055 \ : LCD_GOTO          $80 OR LCD_WrF ;
33056
33057
33058 \ CODE LCD_RDS                    \ -- status       Read Status
33059 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
33060 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
33061 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
33062 \ COLON                           \ starts a FORTH word
33063 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
33064 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
33065 \ HI2LO                           \ switch from FORTH to assembler
33066 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
33067 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
33068 \     MOV @RSP+,IP                \ restore IP saved by COLON
33069 \     MOV @IP+,PC                 \
33070 \ ENDCODE
33071
33072 \ CODE LCD_RDC                    \ -- char         Read Char
33073 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
33074 \     GOTO BW1
33075 \ ENDCODE
33076
33077
33078 \ ******************************\
33079 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
33080 \ ******************************\
33081 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
33082 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
33083 BIT.B #SW2,&SW2_IN              \ test switch S2
33084 0= IF                           \ case of switch S2 pressed
33085     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
33086     U< IF
33087         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
33088     THEN
33089 ELSE
33090     BIT.B #SW1,&SW1_IN          \ test switch S1 input
33091     0= IF                       \ case of Switch S1 pressed
33092         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
33093         U>= IF                  \
33094            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
33095         THEN                    \
33096     THEN                        \
33097 THEN                            \
33098 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
33099 RET                             \ 5
33100 ENDASM
33101
33102 \ ******************************\
33103 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
33104 \ ******************************\
33105 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
33106 \ ******************************\
33107 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
33108 \                               \       SMclock = 8|16|24 MHz
33109 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
33110 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
33111 \                               \       SR(9)=new Toggle bit memory (ADD on)
33112 \ ******************************\
33113 \ RC5_FirstStartBitHalfCycle:   \
33114 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
33115 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
33116 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
33117 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
33118 \ [THEN]
33119 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
33120     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
33121 [THEN]
33122 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
33123     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
33124 [THEN]
33125 MOV #1778,X                     \ RC5_Period * 1us
33126 MOV #14,W                       \ count of loop
33127 BEGIN                           \
33128 \ ******************************\
33129 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
33130 \ ******************************\                   |
33131 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
33132 \ RC5_Compute_3/4_Period:       \                   |
33133     RRUM    #1,X                \ X=1/2 cycle       |
33134     MOV     X,Y                 \                   ^
33135     RRUM    #1,Y                \ Y=1/4
33136     ADD     X,Y                 \ Y=3/4 cycle
33137     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
33138     U>= UNTIL                   \ 2
33139 \ ******************************\
33140 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
33141 \ ******************************\
33142     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
33143     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
33144     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
33145     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
33146     SUB     #1,W                \ decrement count loop
33147 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
33148 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
33149 0<> WHILE                       \ ----> out of loop ----+
33150     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
33151     BEGIN                       \                       |
33152         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
33153         CMP Y,X                 \ 1                     |   cycle time out of bound ?
33154         U>= IF                  \ 2                 ^   |   yes:
33155         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
33156         GOTO BW1                \                   |   |      quit on truncated RC5 message
33157         THEN                    \                   |   |
33158         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
33159     0<> UNTIL                   \ 2                 |   |
33160 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
33161 \ ******************************\                       |
33162 \ RC5_SampleEndOf:              \ <---------------------+
33163 \ ******************************\
33164 BIC #$30,&RC5_TIM_CTL           \   stop timer
33165 \ ******************************\
33166 \ RC5_ComputeNewRC5word         \
33167 \ ******************************\
33168 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
33169 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
33170 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
33171 \ ******************************\
33172 \ RC5_ComputeC6bit              \
33173 \ ******************************\
33174 BIT     #BIT14,T                \ test /C6 bit in T
33175 0= IF   BIS #BIT6,X             \ set C6 bit in X
33176 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
33177 \ ******************************\
33178 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
33179 \ ******************************\
33180 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
33181 \ ******************************\
33182 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
33183 XOR     @RSP,T                  \ (new XOR old) Toggle bits
33184 BIT     #UF10,T                 \ repeated RC5_command ?
33185 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
33186 XOR #UF10,0(RSP)                \ 5 toggle bit memory
33187 \ ******************************\
33188 \ Display IR_RC5 code           \
33189 \ ******************************\
33190 SUB #8,PSP                      \ TOS -- x x x x TOS
33191 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
33192 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
33193 MOV #$10,&BASEADR               \                                               set hexadecimal base
33194 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
33195 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
33196 LO2HI                           \                                               switch from assembler to FORTH
33197     LCD_CLEAR                   \                                               set LCD cursor at home
33198     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
33199     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
33200     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
33201     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
33202 HI2LO                           \     --                                        switch from FORTH to assembler
33203 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
33204 MOV @PSP+,TOS                   \     -- TOS
33205 RET
33206 ENDASM
33207
33208 \ ******************************\
33209 ASM BACKGROUND                  \
33210 \ ******************************\
33211 BEGIN
33212 \     ...                         \ insert here your background task
33213 \     ...                         \
33214 \     ...                         \
33215     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
33216     BIS &LPM_MODE,SR            \
33217 \ ******************************\
33218 \ here start all interrupts     \
33219 \ ******************************\
33220 \ here return all interrupts    \
33221 \ ******************************\
33222 AGAIN                           \
33223 ENDASM                          \
33224 \ ******************************\
33225
33226 \ ------------------------------\
33227 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
33228 \ ------------------------------\
33229 \     ...                         \ init specific I/O sys as you want
33230 \     ...                         \ before executing default WARM
33231     MOV #WARM,X                 \ ['] WARM 
33232     ADD #4,X                    \ >BODY
33233     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
33234 ENDASM
33235 \ ------------------------------\
33236
33237 \ ------------------------------\
33238 CODE STOP                       \ stops multitasking, must to be used before downloading app
33239 \ ------------------------------\
33240 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
33241     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
33242     MOV X,-2(X)                 \ restore the default background: SLEEP
33243     MOV #WARM,X
33244     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
33245     BIC.B #RC5,&IR_IE           \ clear RC5_Int
33246     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
33247     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
33248     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
33249     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
33250     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
33251 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
33252 ECHO                            \
33253 ." RC5toLCD is removed,"
33254 ."  type START to restart"
33255  WARM                           \ performs reset to reset all interrupt vectors.    
33256 ;
33257 \ ------------------------------\
33258
33259 \ ------------------------------\
33260 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
33261 \ ------------------------------\
33262 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
33263 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
33264 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
33265 \                           --       \ID input divider \ 10 = /4
33266 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
33267 \                                 -  \TBCLR TimerB Clear
33268 \                                  - \TBIE
33269 \                                   -\TBIFG
33270 \ -------------------------------\
33271 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
33272 \                  --                 \CM Capture Mode
33273 \                    --               \CCIS
33274 \                       -             \SCS
33275 \                        --           \CLLD
33276 \                          -          \CAP
33277 \                            ---      \OUTMOD \ 011 = set/reset
33278 \                               -     \CCIE
33279 \                                 -   \CCI
33280 \                                  -  \OUT
33281 \                                   - \COV
33282 \                                    -\CCIFG
33283 \ -------------------------------\
33284 \ LCD_TIM_CCRx                   \
33285 \ -------------------------------\
33286 \ LCD_TIM_EX0                    \ 
33287 \ ------------------------------\
33288 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
33289 \ ------------------------------\
33290 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
33291 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
33292 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
33293     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
33294 [THEN]
33295 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
33296     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
33297 [THEN]
33298     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
33299 \ ------------------------------\
33300 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
33301 \ ------------------------------\
33302 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
33303     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
33304 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
33305 \ ------------------------------\
33306     BIS.B #LCDVo,&LCDVo_DIR     \
33307     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
33308 \ ------------------------------\
33309     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
33310     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
33311 \ ------------------------------\
33312     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
33313     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
33314 \ ******************************\
33315 \ init RC5_Int                  \
33316 \ ******************************\
33317     BIS.B #RC5,&IR_IE           \ enable RC5_Int
33318     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
33319     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
33320 \ ******************************\
33321 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
33322 \ ******************************\
33323 \              %01 0001 0100    \ TAxCTL
33324 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
33325 \                  --           \ ID        divided by 1
33326 \                    --         \ MC        MODE = up to TAxCCRn
33327 \                        -      \ TACLR     clear timer count
33328 \                         -     \ TAIE
33329 \                          -    \ TAIFG
33330 \ ------------------------------\
33331 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
33332 \ ------------------------------\
33333 \                        000    \ TAxEX0
33334 \                        ---    \ TAIDEX    pre divisor
33335 \ ------------------------------\
33336 \          %0000 0000 0000 0101 \ TAxCCR0
33337     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
33338 \ ------------------------------\
33339 \          %0000 0000 0001 0000 \ TAxCCTL0
33340 \                   -           \ CAP capture/compare mode = compare
33341 \                        -      \ CCIEn
33342 \                             - \ CCIFGn
33343     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
33344 \ ------------------------------\
33345     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
33346 \ ------------------------------\
33347 \ define LPM mode for ACCEPT    \
33348 \ ------------------------------\
33349 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
33350 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
33351 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
33352 \ ------------------------------\
33353 \ activate I/O                  \
33354 \ ------------------------------\
33355 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
33356 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
33357 \ ------------------------------\
33358 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
33359 \ ------------------------------\
33360 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
33361 \ CMP #2,Y                        \ Power_ON event
33362 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
33363 CMP #4,Y                        \
33364 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
33365 \ CMP #6,Y                        \
33366 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
33367 \ CMP #$0A,Y                      \
33368 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
33369 \ CMP #$16,Y                      \
33370 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
33371 \ ------------------------------\
33372 COLON                           \
33373 \ ------------------------------\
33374 \ Init LCD 2x20                 \
33375 \ ------------------------------\
33376     #1000 20_US                 \ 1- wait 20 ms
33377     %011 TOP_LCD                \ 2- send DB5=DB4=1
33378     #205 20_US                  \ 3- wait 4,1 ms
33379     %011 TOP_LCD                \ 4- send again DB5=DB4=1
33380     #5 20_US                    \ 5- wait 0,1 ms
33381     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
33382     #2 20_US                    \    wait 40 us = LCD cycle
33383     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
33384     #2 20_US                    \    wait 40 us = LCD cycle
33385     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
33386     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
33387     LCD_CLEAR                   \ 10- "LCD_Clear"
33388     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
33389     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
33390     LCD_CLEAR                   \ 10- "LCD_Clear"
33391     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
33392     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
33393     CR ." I love you"           \ display message on LCD
33394     ['] CR >BODY IS CR          \ CR executes its default value
33395     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
33396     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
33397     PWR_STATE ABORT             \ init DP and continues with ABORT
33398 ;                               \
33399 \ ------------------------------\
33400
33401 \ ------------------------------\
33402 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
33403 \ ------------------------------\
33404 MOV #SLEEP,X                    \ replace default background process SLEEP
33405 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
33406 MOV #WARM,X                     \ replace default WARM
33407 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
33408 MOV X,PC                        \ then execute new WARM
33409 ENDCODE 
33410 \ ------------------------------\
33411
33412 ECHO
33413             ; downloading RC5toLCD.4th is done
33414 RST_HERE    ; this app is protected against <reset>
33415
33416
33417 RST_STATE
33418
33419 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
33420
33421 [UNDEFINED] MARKER [IF]
33422 \  https://forth-standard.org/standard/core/MARKER
33423 \  MARKER
33424 \ ( "<spaces>name" -- )
33425 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
33426 \ with the execution semantics defined below.
33427
33428 \ name Execution: ( -- )
33429 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
33430 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
33431 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
33432 \ not necessarily provided. No other contextual information such as numeric base is affected
33433 \
33434 : MARKER
33435 CREATE
33436 HI2LO
33437 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
33438 SUB #2,Y            \ 1 Y = LFA
33439 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
33440 ADD #4,&DP          \ 3 add 2 cells
33441 LO2HI
33442 DOES>
33443 HI2LO
33444 MOV @RSP+,IP        \ -- PFA
33445 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
33446 MOV @TOS,&INIDP     \       set DP value for RST_STATE
33447 MOV @PSP+,TOS       \ --
33448 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
33449 ENDCODE
33450 [THEN]
33451
33452 MARKER {RC5TOLCD}
33453
33454 [UNDEFINED] @ [IF]
33455 \ https://forth-standard.org/standard/core/Fetch
33456 \ @     c-addr -- char   fetch char from memory
33457 CODE @
33458 MOV @TOS,TOS
33459 MOV @IP+,PC
33460 ENDCODE
33461 [THEN]
33462
33463 [UNDEFINED] CONSTANT [IF]
33464 \ https://forth-standard.org/standard/core/CONSTANT
33465 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
33466 : CONSTANT 
33467 CREATE
33468 HI2LO
33469 MOV TOS,-2(W)           \   PFA = n
33470 MOV @PSP+,TOS
33471 MOV @RSP+,IP
33472 MOV @IP+,PC
33473 ENDCODE
33474 [THEN]
33475
33476 [UNDEFINED] STATE [IF]
33477 \ https://forth-standard.org/standard/core/STATE
33478 \ STATE   -- a-addr       holds compiler state
33479 STATEADR CONSTANT STATE
33480 [THEN]
33481
33482 [UNDEFINED] = [IF]
33483 \ https://forth-standard.org/standard/core/Equal
33484 \ =      x1 x2 -- flag         test x1=x2
33485 CODE =
33486 SUB @PSP+,TOS   \ 2
33487 0<> IF          \ 2
33488     AND #0,TOS  \ 1
33489     MOV @IP+,PC \ 4
33490 THEN
33491 XOR #-1,TOS     \ 1 flag Z = 1
33492 MOV @IP+,PC     \ 4
33493 ENDCODE
33494 [THEN]
33495
33496 [UNDEFINED] IF [IF]
33497 \ https://forth-standard.org/standard/core/IF
33498 \ IF       -- IFadr    initialize conditional forward branch
33499 CODE IF       \ immediate
33500 SUB #2,PSP              \
33501 MOV TOS,0(PSP)          \
33502 MOV &DP,TOS             \ -- HERE
33503 ADD #4,&DP            \           compile one word, reserve one word
33504 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
33505 ADD #2,TOS              \ -- HERE+2=IFadr
33506 MOV @IP+,PC
33507 ENDCODE IMMEDIATE
33508 [THEN]
33509
33510 [UNDEFINED] THEN [IF]
33511 \ https://forth-standard.org/standard/core/THEN
33512 \ THEN     IFadr --                resolve forward branch
33513 CODE THEN               \ immediate
33514 MOV &DP,0(TOS)          \ -- IFadr
33515 MOV @PSP+,TOS           \ --
33516 MOV @IP+,PC
33517 ENDCODE IMMEDIATE
33518 [THEN]
33519
33520 [UNDEFINED] ELSE [IF]
33521 \ https://forth-standard.org/standard/core/ELSE
33522 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
33523 CODE ELSE     \ immediate
33524 ADD #4,&DP              \ make room to compile two words
33525 MOV &DP,W               \ W=HERE+4
33526 MOV #BRAN,-4(W)
33527 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
33528 SUB #2,W                \ HERE+2
33529 MOV W,TOS               \ -- ELSEadr
33530 MOV @IP+,PC
33531 ENDCODE IMMEDIATE
33532 [THEN]
33533
33534 [UNDEFINED] DEFER [IF]
33535 \ https://forth-standard.org/standard/core/DEFER
33536 \ DEFER "<spaces>name"   --
33537 \ Skip leading space delimiters. Parse name delimited by a space.
33538 \ Create a definition for name with the execution semantics defined below.
33539
33540 \ name Execution:   --
33541 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
33542 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
33543 : DEFER
33544 CREATE
33545 HI2LO
33546 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
33547 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
33548 MOV @RSP+,IP
33549 MOV @IP+,PC
33550 ENDCODE
33551 [THEN]
33552
33553 [UNDEFINED] DEFER! [IF]
33554 \ https://forth-standard.org/standard/core/DEFERStore
33555 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
33556 CODE DEFER!             \ xt2 xt1 --
33557 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
33558 MOV @PSP+,TOS           \ --
33559 MOV @IP+,PC
33560 ENDCODE
33561 [THEN]
33562
33563 [UNDEFINED] IS [IF]
33564 \ https://forth-standard.org/standard/core/IS
33565 \ IS <name>        xt --
33566 \ used as is :
33567 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
33568 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
33569 \ or in a definition : ... ['] U. IS DISPLAY ...
33570 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
33571 \
33572 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
33573 : IS
33574 STATE @
33575 IF  POSTPONE ['] POSTPONE DEFER! 
33576 ELSE ' DEFER! 
33577 THEN
33578 ; IMMEDIATE
33579 [THEN]
33580
33581 [UNDEFINED] >BODY [IF]
33582 \ https://forth-standard.org/standard/core/toBODY
33583 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
33584 CODE >BODY
33585 ADD #4,TOS
33586 MOV @IP+,PC
33587 ENDCODE
33588 [THEN]
33589
33590 \ CODE 20uS           \ n --      8MHz version
33591 \ BEGIN               \ 4 + 16 ~ loop
33592 \     MOV #39,rDOCON   \ 39
33593 \     BEGIN           \ 4 ~ loop
33594 \         NOP
33595 \         SUB #1,rDOCON
33596 \     0=  UNTIL
33597 \     SUB #1,TOS      \ 1
33598 \ 0= UNTIL
33599 \ MOV #XDOCON,rDOCON  \ 2
33600 \ MOV @PSP+,TOS
33601 \ MOV @RSP+,IP        \
33602 \ ENDCODE
33603
33604 CODE 20_US                      \ n --      n * 20 us
33605 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
33606     BEGIN
33607         BIT #1,&LCD_TIM_CTL     \ 3
33608     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
33609     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
33610     SUB #1,TOS                  \ 1
33611 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
33612 MOV @PSP+,TOS                   \ 2
33613 MOV @IP+,PC                     \ 4
33614 ENDCODE
33615
33616 CODE TOP_LCD                    \ LCD Sample
33617 \                               \ if write : %xxxx_WWWW --
33618 \                               \ if read  : -- %0000_RRRR
33619     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
33620     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
33621 0= IF                           \ write LCD bits pattern
33622     AND.B #LCD_DB,TOS           \ 
33623     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
33624     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
33625     MOV @PSP+,TOS               \
33626     MOV @IP+,PC
33627 THEN                            \ read LCD bits pattern
33628     SUB #2,PSP
33629     MOV TOS,0(PSP)
33630     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
33631     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
33632     AND.B #LCD_DB,TOS           \
33633     MOV @IP+,PC
33634 ENDCODE
33635
33636 CODE LCD_WRC                    \ char --         Write Char
33637     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
33638 BW1 SUB #2,PSP                  \
33639     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
33640     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
33641     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
33642     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
33643 COLON                           \ high level word starts here 
33644     TOP_LCD 2 20_US             \ write high nibble first
33645     TOP_LCD 2 20_US 
33646 ;
33647
33648 CODE LCD_WRF                    \ func --         Write Fonction
33649     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
33650     GOTO BW1
33651 ENDCODE
33652
33653 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
33654 : LCD_HOME $02 LCD_WRF 100 20_us ;
33655
33656 \ [UNDEFINED] OR [IF]
33657
33658 \ \ https://forth-standard.org/standard/core/OR
33659 \ \ C OR     x1 x2 -- x3           logical OR
33660 \ CODE OR
33661 \ BIS @PSP+,TOS
33662 \ MOV @IP+,PC
33663 \ ENDCODE
33664
33665 \ [THEN]
33666
33667 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
33668 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
33669 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
33670 \ : LCD_FN_SET        $20 OR LCD_WrF ;
33671 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
33672 \ : LCD_GOTO          $80 OR LCD_WrF ;
33673
33674
33675 \ CODE LCD_RDS                    \ -- status       Read Status
33676 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
33677 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
33678 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
33679 \ COLON                           \ starts a FORTH word
33680 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
33681 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
33682 \ HI2LO                           \ switch from FORTH to assembler
33683 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
33684 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
33685 \     MOV @RSP+,IP                \ restore IP saved by COLON
33686 \     MOV @IP+,PC                 \
33687 \ ENDCODE
33688
33689 \ CODE LCD_RDC                    \ -- char         Read Char
33690 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
33691 \     GOTO BW1
33692 \ ENDCODE
33693
33694
33695 \ ******************************\
33696 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
33697 \ ******************************\
33698 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
33699 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
33700 BIT.B #SW2,&SW2_IN              \ test switch S2
33701 0= IF                           \ case of switch S2 pressed
33702     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
33703     U< IF
33704         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
33705     THEN
33706 ELSE
33707     BIT.B #SW1,&SW1_IN          \ test switch S1 input
33708     0= IF                       \ case of Switch S1 pressed
33709         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
33710         U>= IF                  \
33711            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
33712         THEN                    \
33713     THEN                        \
33714 THEN                            \
33715 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
33716 RET                             \ 5
33717 ENDASM
33718
33719 \ ******************************\
33720 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
33721 \ ******************************\
33722 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
33723 \ ******************************\
33724 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
33725 \                               \       SMclock = 8|16|24 MHz
33726 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
33727 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
33728 \                               \       SR(9)=new Toggle bit memory (ADD on)
33729 \ ******************************\
33730 \ RC5_FirstStartBitHalfCycle:   \
33731 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
33732 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
33733 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
33734 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
33735 \ [THEN]
33736 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
33737     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
33738 [THEN]
33739 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
33740     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
33741 [THEN]
33742 MOV #1778,X                     \ RC5_Period * 1us
33743 MOV #14,W                       \ count of loop
33744 BEGIN                           \
33745 \ ******************************\
33746 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
33747 \ ******************************\                   |
33748 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
33749 \ RC5_Compute_3/4_Period:       \                   |
33750     RRUM    #1,X                \ X=1/2 cycle       |
33751     MOV     X,Y                 \                   ^
33752     RRUM    #1,Y                \ Y=1/4
33753     ADD     X,Y                 \ Y=3/4 cycle
33754     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
33755     U>= UNTIL                   \ 2
33756 \ ******************************\
33757 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
33758 \ ******************************\
33759     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
33760     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
33761     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
33762     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
33763     SUB     #1,W                \ decrement count loop
33764 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
33765 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
33766 0<> WHILE                       \ ----> out of loop ----+
33767     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
33768     BEGIN                       \                       |
33769         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
33770         CMP Y,X                 \ 1                     |   cycle time out of bound ?
33771         U>= IF                  \ 2                 ^   |   yes:
33772         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
33773         GOTO BW1                \                   |   |      quit on truncated RC5 message
33774         THEN                    \                   |   |
33775         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
33776     0<> UNTIL                   \ 2                 |   |
33777 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
33778 \ ******************************\                       |
33779 \ RC5_SampleEndOf:              \ <---------------------+
33780 \ ******************************\
33781 BIC #$30,&RC5_TIM_CTL           \   stop timer
33782 \ ******************************\
33783 \ RC5_ComputeNewRC5word         \
33784 \ ******************************\
33785 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
33786 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
33787 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
33788 \ ******************************\
33789 \ RC5_ComputeC6bit              \
33790 \ ******************************\
33791 BIT     #BIT14,T                \ test /C6 bit in T
33792 0= IF   BIS #BIT6,X             \ set C6 bit in X
33793 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
33794 \ ******************************\
33795 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
33796 \ ******************************\
33797 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
33798 \ ******************************\
33799 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
33800 XOR     @RSP,T                  \ (new XOR old) Toggle bits
33801 BIT     #UF10,T                 \ repeated RC5_command ?
33802 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
33803 XOR #UF10,0(RSP)                \ 5 toggle bit memory
33804 \ ******************************\
33805 \ Display IR_RC5 code           \
33806 \ ******************************\
33807 SUB #8,PSP                      \ TOS -- x x x x TOS
33808 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
33809 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
33810 MOV #$10,&BASEADR               \                                               set hexadecimal base
33811 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
33812 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
33813 LO2HI                           \                                               switch from assembler to FORTH
33814     LCD_CLEAR                   \                                               set LCD cursor at home
33815     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
33816     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
33817     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
33818     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
33819 HI2LO                           \     --                                        switch from FORTH to assembler
33820 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
33821 MOV @PSP+,TOS                   \     -- TOS
33822 RET
33823 ENDASM
33824
33825 \ ******************************\
33826 ASM BACKGROUND                  \
33827 \ ******************************\
33828 BEGIN
33829 \     ...                         \ insert here your background task
33830 \     ...                         \
33831 \     ...                         \
33832     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
33833     BIS &LPM_MODE,SR            \
33834 \ ******************************\
33835 \ here start all interrupts     \
33836 \ ******************************\
33837 \ here return all interrupts    \
33838 \ ******************************\
33839 AGAIN                           \
33840 ENDASM                          \
33841 \ ******************************\
33842
33843 \ ------------------------------\
33844 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
33845 \ ------------------------------\
33846 \     ...                         \ init specific I/O sys as you want
33847 \     ...                         \ before executing default WARM
33848     MOV #WARM,X                 \ ['] WARM 
33849     ADD #4,X                    \ >BODY
33850     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
33851 ENDASM
33852 \ ------------------------------\
33853
33854 \ ------------------------------\
33855 CODE STOP                       \ stops multitasking, must to be used before downloading app
33856 \ ------------------------------\
33857 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
33858     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
33859     MOV X,-2(X)                 \ restore the default background: SLEEP
33860     MOV #WARM,X
33861     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
33862     BIC.B #RC5,&IR_IE           \ clear RC5_Int
33863     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
33864     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
33865     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
33866     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
33867     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
33868 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
33869 ECHO                            \
33870 ." RC5toLCD is removed,"
33871 ."  type START to restart"
33872  WARM                           \ performs reset to reset all interrupt vectors.    
33873 ;
33874 \ ------------------------------\
33875
33876 \ ------------------------------\
33877 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
33878 \ ------------------------------\
33879 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
33880 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
33881 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
33882 \                           --       \ID input divider \ 10 = /4
33883 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
33884 \                                 -  \TBCLR TimerB Clear
33885 \                                  - \TBIE
33886 \                                   -\TBIFG
33887 \ -------------------------------\
33888 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
33889 \                  --                 \CM Capture Mode
33890 \                    --               \CCIS
33891 \                       -             \SCS
33892 \                        --           \CLLD
33893 \                          -          \CAP
33894 \                            ---      \OUTMOD \ 011 = set/reset
33895 \                               -     \CCIE
33896 \                                 -   \CCI
33897 \                                  -  \OUT
33898 \                                   - \COV
33899 \                                    -\CCIFG
33900 \ -------------------------------\
33901 \ LCD_TIM_CCRx                   \
33902 \ -------------------------------\
33903 \ LCD_TIM_EX0                    \ 
33904 \ ------------------------------\
33905 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
33906 \ ------------------------------\
33907 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
33908 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
33909 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
33910     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
33911 [THEN]
33912 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
33913     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
33914 [THEN]
33915     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
33916 \ ------------------------------\
33917 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
33918 \ ------------------------------\
33919 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
33920     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
33921 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
33922 \ ------------------------------\
33923     BIS.B #LCDVo,&LCDVo_DIR     \
33924     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
33925 \ ------------------------------\
33926     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
33927     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
33928 \ ------------------------------\
33929     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
33930     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
33931 \ ******************************\
33932 \ init RC5_Int                  \
33933 \ ******************************\
33934     BIS.B #RC5,&IR_IE           \ enable RC5_Int
33935     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
33936     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
33937 \ ******************************\
33938 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
33939 \ ******************************\
33940 \              %01 0001 0100    \ TAxCTL
33941 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
33942 \                  --           \ ID        divided by 1
33943 \                    --         \ MC        MODE = up to TAxCCRn
33944 \                        -      \ TACLR     clear timer count
33945 \                         -     \ TAIE
33946 \                          -    \ TAIFG
33947 \ ------------------------------\
33948 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
33949 \ ------------------------------\
33950 \                        000    \ TAxEX0
33951 \                        ---    \ TAIDEX    pre divisor
33952 \ ------------------------------\
33953 \          %0000 0000 0000 0101 \ TAxCCR0
33954     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
33955 \ ------------------------------\
33956 \          %0000 0000 0001 0000 \ TAxCCTL0
33957 \                   -           \ CAP capture/compare mode = compare
33958 \                        -      \ CCIEn
33959 \                             - \ CCIFGn
33960     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
33961 \ ------------------------------\
33962     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
33963 \ ------------------------------\
33964 \ define LPM mode for ACCEPT    \
33965 \ ------------------------------\
33966 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
33967 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
33968 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
33969 \ ------------------------------\
33970 \ activate I/O                  \
33971 \ ------------------------------\
33972 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
33973 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
33974 \ ------------------------------\
33975 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
33976 \ ------------------------------\
33977 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
33978 \ CMP #2,Y                        \ Power_ON event
33979 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
33980 CMP #4,Y                        \
33981 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
33982 \ CMP #6,Y                        \
33983 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
33984 \ CMP #$0A,Y                      \
33985 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
33986 \ CMP #$16,Y                      \
33987 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
33988 \ ------------------------------\
33989 COLON                           \
33990 \ ------------------------------\
33991 \ Init LCD 2x20                 \
33992 \ ------------------------------\
33993     #1000 20_US                 \ 1- wait 20 ms
33994     %011 TOP_LCD                \ 2- send DB5=DB4=1
33995     #205 20_US                  \ 3- wait 4,1 ms
33996     %011 TOP_LCD                \ 4- send again DB5=DB4=1
33997     #5 20_US                    \ 5- wait 0,1 ms
33998     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
33999     #2 20_US                    \    wait 40 us = LCD cycle
34000     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
34001     #2 20_US                    \    wait 40 us = LCD cycle
34002     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
34003     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
34004     LCD_CLEAR                   \ 10- "LCD_Clear"
34005     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
34006     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
34007     LCD_CLEAR                   \ 10- "LCD_Clear"
34008     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
34009     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
34010     CR ." I love you"           \ display message on LCD
34011     ['] CR >BODY IS CR          \ CR executes its default value
34012     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
34013     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
34014     PWR_STATE ABORT             \ init DP and continues with ABORT
34015 ;                               \
34016 \ ------------------------------\
34017
34018 \ ------------------------------\
34019 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
34020 \ ------------------------------\
34021 MOV #SLEEP,X                    \ replace default background process SLEEP
34022 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
34023 MOV #WARM,X                     \ replace default WARM
34024 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
34025 MOV X,PC                        \ then execute new WARM
34026 ENDCODE 
34027 \ ------------------------------\
34028
34029 ECHO
34030             ; downloading RC5toLCD.4th is done
34031 RST_HERE    ; this app is protected against <reset>
34032
34033
34034 RST_STATE
34035
34036 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
34037
34038 [UNDEFINED] MARKER [IF]
34039 \  https://forth-standard.org/standard/core/MARKER
34040 \  MARKER
34041 \ ( "<spaces>name" -- )
34042 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
34043 \ with the execution semantics defined below.
34044
34045 \ name Execution: ( -- )
34046 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
34047 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
34048 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
34049 \ not necessarily provided. No other contextual information such as numeric base is affected
34050 \
34051 : MARKER
34052 CREATE
34053 HI2LO
34054 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
34055 SUB #2,Y            \ 1 Y = LFA
34056 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
34057 ADD #4,&DP          \ 3 add 2 cells
34058 LO2HI
34059 DOES>
34060 HI2LO
34061 MOV @RSP+,IP        \ -- PFA
34062 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
34063 MOV @TOS,&INIDP     \       set DP value for RST_STATE
34064 MOV @PSP+,TOS       \ --
34065 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
34066 ENDCODE
34067 [THEN]
34068
34069 MARKER {RC5TOLCD}
34070
34071 [UNDEFINED] @ [IF]
34072 \ https://forth-standard.org/standard/core/Fetch
34073 \ @     c-addr -- char   fetch char from memory
34074 CODE @
34075 MOV @TOS,TOS
34076 MOV @IP+,PC
34077 ENDCODE
34078 [THEN]
34079
34080 [UNDEFINED] CONSTANT [IF]
34081 \ https://forth-standard.org/standard/core/CONSTANT
34082 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
34083 : CONSTANT 
34084 CREATE
34085 HI2LO
34086 MOV TOS,-2(W)           \   PFA = n
34087 MOV @PSP+,TOS
34088 MOV @RSP+,IP
34089 MOV @IP+,PC
34090 ENDCODE
34091 [THEN]
34092
34093 [UNDEFINED] STATE [IF]
34094 \ https://forth-standard.org/standard/core/STATE
34095 \ STATE   -- a-addr       holds compiler state
34096 STATEADR CONSTANT STATE
34097 [THEN]
34098
34099 [UNDEFINED] = [IF]
34100 \ https://forth-standard.org/standard/core/Equal
34101 \ =      x1 x2 -- flag         test x1=x2
34102 CODE =
34103 SUB @PSP+,TOS   \ 2
34104 0<> IF          \ 2
34105     AND #0,TOS  \ 1
34106     MOV @IP+,PC \ 4
34107 THEN
34108 XOR #-1,TOS     \ 1 flag Z = 1
34109 MOV @IP+,PC     \ 4
34110 ENDCODE
34111 [THEN]
34112
34113 [UNDEFINED] IF [IF]
34114 \ https://forth-standard.org/standard/core/IF
34115 \ IF       -- IFadr    initialize conditional forward branch
34116 CODE IF       \ immediate
34117 SUB #2,PSP              \
34118 MOV TOS,0(PSP)          \
34119 MOV &DP,TOS             \ -- HERE
34120 ADD #4,&DP            \           compile one word, reserve one word
34121 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
34122 ADD #2,TOS              \ -- HERE+2=IFadr
34123 MOV @IP+,PC
34124 ENDCODE IMMEDIATE
34125 [THEN]
34126
34127 [UNDEFINED] THEN [IF]
34128 \ https://forth-standard.org/standard/core/THEN
34129 \ THEN     IFadr --                resolve forward branch
34130 CODE THEN               \ immediate
34131 MOV &DP,0(TOS)          \ -- IFadr
34132 MOV @PSP+,TOS           \ --
34133 MOV @IP+,PC
34134 ENDCODE IMMEDIATE
34135 [THEN]
34136
34137 [UNDEFINED] ELSE [IF]
34138 \ https://forth-standard.org/standard/core/ELSE
34139 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
34140 CODE ELSE     \ immediate
34141 ADD #4,&DP              \ make room to compile two words
34142 MOV &DP,W               \ W=HERE+4
34143 MOV #BRAN,-4(W)
34144 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
34145 SUB #2,W                \ HERE+2
34146 MOV W,TOS               \ -- ELSEadr
34147 MOV @IP+,PC
34148 ENDCODE IMMEDIATE
34149 [THEN]
34150
34151 [UNDEFINED] DEFER [IF]
34152 \ https://forth-standard.org/standard/core/DEFER
34153 \ DEFER "<spaces>name"   --
34154 \ Skip leading space delimiters. Parse name delimited by a space.
34155 \ Create a definition for name with the execution semantics defined below.
34156
34157 \ name Execution:   --
34158 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
34159 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
34160 : DEFER
34161 CREATE
34162 HI2LO
34163 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
34164 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
34165 MOV @RSP+,IP
34166 MOV @IP+,PC
34167 ENDCODE
34168 [THEN]
34169
34170 [UNDEFINED] DEFER! [IF]
34171 \ https://forth-standard.org/standard/core/DEFERStore
34172 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
34173 CODE DEFER!             \ xt2 xt1 --
34174 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
34175 MOV @PSP+,TOS           \ --
34176 MOV @IP+,PC
34177 ENDCODE
34178 [THEN]
34179
34180 [UNDEFINED] IS [IF]
34181 \ https://forth-standard.org/standard/core/IS
34182 \ IS <name>        xt --
34183 \ used as is :
34184 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
34185 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
34186 \ or in a definition : ... ['] U. IS DISPLAY ...
34187 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
34188 \
34189 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
34190 : IS
34191 STATE @
34192 IF  POSTPONE ['] POSTPONE DEFER! 
34193 ELSE ' DEFER! 
34194 THEN
34195 ; IMMEDIATE
34196 [THEN]
34197
34198 [UNDEFINED] >BODY [IF]
34199 \ https://forth-standard.org/standard/core/toBODY
34200 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
34201 CODE >BODY
34202 ADD #4,TOS
34203 MOV @IP+,PC
34204 ENDCODE
34205 [THEN]
34206
34207 \ CODE 20uS           \ n --      8MHz version
34208 \ BEGIN               \ 4 + 16 ~ loop
34209 \     MOV #39,rDOCON   \ 39
34210 \     BEGIN           \ 4 ~ loop
34211 \         NOP
34212 \         SUB #1,rDOCON
34213 \     0=  UNTIL
34214 \     SUB #1,TOS      \ 1
34215 \ 0= UNTIL
34216 \ MOV #XDOCON,rDOCON  \ 2
34217 \ MOV @PSP+,TOS
34218 \ MOV @RSP+,IP        \
34219 \ ENDCODE
34220
34221 CODE 20_US                      \ n --      n * 20 us
34222 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
34223     BEGIN
34224         BIT #1,&LCD_TIM_CTL     \ 3
34225     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
34226     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
34227     SUB #1,TOS                  \ 1
34228 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
34229 MOV @PSP+,TOS                   \ 2
34230 MOV @IP+,PC                     \ 4
34231 ENDCODE
34232
34233 CODE TOP_LCD                    \ LCD Sample
34234 \                               \ if write : %xxxx_WWWW --
34235 \                               \ if read  : -- %0000_RRRR
34236     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
34237     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
34238 0= IF                           \ write LCD bits pattern
34239     AND.B #LCD_DB,TOS           \ 
34240     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
34241     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
34242     MOV @PSP+,TOS               \
34243     MOV @IP+,PC
34244 THEN                            \ read LCD bits pattern
34245     SUB #2,PSP
34246     MOV TOS,0(PSP)
34247     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
34248     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
34249     AND.B #LCD_DB,TOS           \
34250     MOV @IP+,PC
34251 ENDCODE
34252
34253 CODE LCD_WRC                    \ char --         Write Char
34254     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
34255 BW1 SUB #2,PSP                  \
34256     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
34257     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
34258     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
34259     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
34260 COLON                           \ high level word starts here 
34261     TOP_LCD 2 20_US             \ write high nibble first
34262     TOP_LCD 2 20_US 
34263 ;
34264
34265 CODE LCD_WRF                    \ func --         Write Fonction
34266     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
34267     GOTO BW1
34268 ENDCODE
34269
34270 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
34271 : LCD_HOME $02 LCD_WRF 100 20_us ;
34272
34273 \ [UNDEFINED] OR [IF]
34274
34275 \ \ https://forth-standard.org/standard/core/OR
34276 \ \ C OR     x1 x2 -- x3           logical OR
34277 \ CODE OR
34278 \ BIS @PSP+,TOS
34279 \ MOV @IP+,PC
34280 \ ENDCODE
34281
34282 \ [THEN]
34283
34284 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
34285 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
34286 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
34287 \ : LCD_FN_SET        $20 OR LCD_WrF ;
34288 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
34289 \ : LCD_GOTO          $80 OR LCD_WrF ;
34290
34291
34292 \ CODE LCD_RDS                    \ -- status       Read Status
34293 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
34294 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
34295 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
34296 \ COLON                           \ starts a FORTH word
34297 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
34298 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
34299 \ HI2LO                           \ switch from FORTH to assembler
34300 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
34301 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
34302 \     MOV @RSP+,IP                \ restore IP saved by COLON
34303 \     MOV @IP+,PC                 \
34304 \ ENDCODE
34305
34306 \ CODE LCD_RDC                    \ -- char         Read Char
34307 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
34308 \     GOTO BW1
34309 \ ENDCODE
34310
34311
34312 \ ******************************\
34313 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
34314 \ ******************************\
34315 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
34316 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
34317 BIT.B #SW2,&SW2_IN              \ test switch S2
34318 0= IF                           \ case of switch S2 pressed
34319     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
34320     U< IF
34321         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
34322     THEN
34323 ELSE
34324     BIT.B #SW1,&SW1_IN          \ test switch S1 input
34325     0= IF                       \ case of Switch S1 pressed
34326         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
34327         U>= IF                  \
34328            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
34329         THEN                    \
34330     THEN                        \
34331 THEN                            \
34332 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
34333 RET                             \ 5
34334 ENDASM
34335
34336 \ ******************************\
34337 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
34338 \ ******************************\
34339 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
34340 \ ******************************\
34341 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
34342 \                               \       SMclock = 8|16|24 MHz
34343 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
34344 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
34345 \                               \       SR(9)=new Toggle bit memory (ADD on)
34346 \ ******************************\
34347 \ RC5_FirstStartBitHalfCycle:   \
34348 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
34349 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
34350 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
34351 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
34352 \ [THEN]
34353 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
34354     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
34355 [THEN]
34356 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
34357     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
34358 [THEN]
34359 MOV #1778,X                     \ RC5_Period * 1us
34360 MOV #14,W                       \ count of loop
34361 BEGIN                           \
34362 \ ******************************\
34363 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
34364 \ ******************************\                   |
34365 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
34366 \ RC5_Compute_3/4_Period:       \                   |
34367     RRUM    #1,X                \ X=1/2 cycle       |
34368     MOV     X,Y                 \                   ^
34369     RRUM    #1,Y                \ Y=1/4
34370     ADD     X,Y                 \ Y=3/4 cycle
34371     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
34372     U>= UNTIL                   \ 2
34373 \ ******************************\
34374 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
34375 \ ******************************\
34376     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
34377     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
34378     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
34379     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
34380     SUB     #1,W                \ decrement count loop
34381 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
34382 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
34383 0<> WHILE                       \ ----> out of loop ----+
34384     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
34385     BEGIN                       \                       |
34386         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
34387         CMP Y,X                 \ 1                     |   cycle time out of bound ?
34388         U>= IF                  \ 2                 ^   |   yes:
34389         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
34390         GOTO BW1                \                   |   |      quit on truncated RC5 message
34391         THEN                    \                   |   |
34392         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
34393     0<> UNTIL                   \ 2                 |   |
34394 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
34395 \ ******************************\                       |
34396 \ RC5_SampleEndOf:              \ <---------------------+
34397 \ ******************************\
34398 BIC #$30,&RC5_TIM_CTL           \   stop timer
34399 \ ******************************\
34400 \ RC5_ComputeNewRC5word         \
34401 \ ******************************\
34402 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
34403 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
34404 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
34405 \ ******************************\
34406 \ RC5_ComputeC6bit              \
34407 \ ******************************\
34408 BIT     #BIT14,T                \ test /C6 bit in T
34409 0= IF   BIS #BIT6,X             \ set C6 bit in X
34410 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
34411 \ ******************************\
34412 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
34413 \ ******************************\
34414 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
34415 \ ******************************\
34416 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
34417 XOR     @RSP,T                  \ (new XOR old) Toggle bits
34418 BIT     #UF10,T                 \ repeated RC5_command ?
34419 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
34420 XOR #UF10,0(RSP)                \ 5 toggle bit memory
34421 \ ******************************\
34422 \ Display IR_RC5 code           \
34423 \ ******************************\
34424 SUB #8,PSP                      \ TOS -- x x x x TOS
34425 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
34426 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
34427 MOV #$10,&BASEADR               \                                               set hexadecimal base
34428 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
34429 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
34430 LO2HI                           \                                               switch from assembler to FORTH
34431     LCD_CLEAR                   \                                               set LCD cursor at home
34432     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
34433     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
34434     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
34435     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
34436 HI2LO                           \     --                                        switch from FORTH to assembler
34437 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
34438 MOV @PSP+,TOS                   \     -- TOS
34439 RET
34440 ENDASM
34441
34442 \ ******************************\
34443 ASM BACKGROUND                  \
34444 \ ******************************\
34445 BEGIN
34446 \     ...                         \ insert here your background task
34447 \     ...                         \
34448 \     ...                         \
34449     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
34450     BIS &LPM_MODE,SR            \
34451 \ ******************************\
34452 \ here start all interrupts     \
34453 \ ******************************\
34454 \ here return all interrupts    \
34455 \ ******************************\
34456 AGAIN                           \
34457 ENDASM                          \
34458 \ ******************************\
34459
34460 \ ------------------------------\
34461 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
34462 \ ------------------------------\
34463 \     ...                         \ init specific I/O sys as you want
34464 \     ...                         \ before executing default WARM
34465     MOV #WARM,X                 \ ['] WARM 
34466     ADD #4,X                    \ >BODY
34467     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
34468 ENDASM
34469 \ ------------------------------\
34470
34471 \ ------------------------------\
34472 CODE STOP                       \ stops multitasking, must to be used before downloading app
34473 \ ------------------------------\
34474 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
34475     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
34476     MOV X,-2(X)                 \ restore the default background: SLEEP
34477     MOV #WARM,X
34478     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
34479     BIC.B #RC5,&IR_IE           \ clear RC5_Int
34480     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
34481     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
34482     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
34483     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
34484     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
34485 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
34486 ECHO                            \
34487 ." RC5toLCD is removed,"
34488 ."  type START to restart"
34489  WARM                           \ performs reset to reset all interrupt vectors.    
34490 ;
34491 \ ------------------------------\
34492
34493 \ ------------------------------\
34494 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
34495 \ ------------------------------\
34496 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
34497 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
34498 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
34499 \                           --       \ID input divider \ 10 = /4
34500 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
34501 \                                 -  \TBCLR TimerB Clear
34502 \                                  - \TBIE
34503 \                                   -\TBIFG
34504 \ -------------------------------\
34505 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
34506 \                  --                 \CM Capture Mode
34507 \                    --               \CCIS
34508 \                       -             \SCS
34509 \                        --           \CLLD
34510 \                          -          \CAP
34511 \                            ---      \OUTMOD \ 011 = set/reset
34512 \                               -     \CCIE
34513 \                                 -   \CCI
34514 \                                  -  \OUT
34515 \                                   - \COV
34516 \                                    -\CCIFG
34517 \ -------------------------------\
34518 \ LCD_TIM_CCRx                   \
34519 \ -------------------------------\
34520 \ LCD_TIM_EX0                    \ 
34521 \ ------------------------------\
34522 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
34523 \ ------------------------------\
34524 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
34525 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
34526 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
34527     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
34528 [THEN]
34529 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
34530     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
34531 [THEN]
34532     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
34533 \ ------------------------------\
34534 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
34535 \ ------------------------------\
34536 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
34537     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
34538 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
34539 \ ------------------------------\
34540     BIS.B #LCDVo,&LCDVo_DIR     \
34541     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
34542 \ ------------------------------\
34543     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
34544     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
34545 \ ------------------------------\
34546     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
34547     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
34548 \ ******************************\
34549 \ init RC5_Int                  \
34550 \ ******************************\
34551     BIS.B #RC5,&IR_IE           \ enable RC5_Int
34552     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
34553     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
34554 \ ******************************\
34555 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
34556 \ ******************************\
34557 \              %01 0001 0100    \ TAxCTL
34558 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
34559 \                  --           \ ID        divided by 1
34560 \                    --         \ MC        MODE = up to TAxCCRn
34561 \                        -      \ TACLR     clear timer count
34562 \                         -     \ TAIE
34563 \                          -    \ TAIFG
34564 \ ------------------------------\
34565 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
34566 \ ------------------------------\
34567 \                        000    \ TAxEX0
34568 \                        ---    \ TAIDEX    pre divisor
34569 \ ------------------------------\
34570 \          %0000 0000 0000 0101 \ TAxCCR0
34571     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
34572 \ ------------------------------\
34573 \          %0000 0000 0001 0000 \ TAxCCTL0
34574 \                   -           \ CAP capture/compare mode = compare
34575 \                        -      \ CCIEn
34576 \                             - \ CCIFGn
34577     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
34578 \ ------------------------------\
34579     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
34580 \ ------------------------------\
34581 \ define LPM mode for ACCEPT    \
34582 \ ------------------------------\
34583 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
34584 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
34585 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
34586 \ ------------------------------\
34587 \ activate I/O                  \
34588 \ ------------------------------\
34589 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
34590 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
34591 \ ------------------------------\
34592 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
34593 \ ------------------------------\
34594 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
34595 \ CMP #2,Y                        \ Power_ON event
34596 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
34597 CMP #4,Y                        \
34598 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
34599 \ CMP #6,Y                        \
34600 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
34601 \ CMP #$0A,Y                      \
34602 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
34603 \ CMP #$16,Y                      \
34604 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
34605 \ ------------------------------\
34606 COLON                           \
34607 \ ------------------------------\
34608 \ Init LCD 2x20                 \
34609 \ ------------------------------\
34610     #1000 20_US                 \ 1- wait 20 ms
34611     %011 TOP_LCD                \ 2- send DB5=DB4=1
34612     #205 20_US                  \ 3- wait 4,1 ms
34613     %011 TOP_LCD                \ 4- send again DB5=DB4=1
34614     #5 20_US                    \ 5- wait 0,1 ms
34615     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
34616     #2 20_US                    \    wait 40 us = LCD cycle
34617     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
34618     #2 20_US                    \    wait 40 us = LCD cycle
34619     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
34620     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
34621     LCD_CLEAR                   \ 10- "LCD_Clear"
34622     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
34623     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
34624     LCD_CLEAR                   \ 10- "LCD_Clear"
34625     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
34626     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
34627     CR ." I love you"           \ display message on LCD
34628     ['] CR >BODY IS CR          \ CR executes its default value
34629     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
34630     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
34631     PWR_STATE ABORT             \ init DP and continues with ABORT
34632 ;                               \
34633 \ ------------------------------\
34634
34635 \ ------------------------------\
34636 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
34637 \ ------------------------------\
34638 MOV #SLEEP,X                    \ replace default background process SLEEP
34639 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
34640 MOV #WARM,X                     \ replace default WARM
34641 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
34642 MOV X,PC                        \ then execute new WARM
34643 ENDCODE 
34644 \ ------------------------------\
34645
34646 ECHO
34647             ; downloading RC5toLCD.4th is done
34648 RST_HERE    ; this app is protected against <reset>
34649
34650
34651 RST_STATE
34652
34653 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
34654
34655 [UNDEFINED] MARKER [IF]
34656 \  https://forth-standard.org/standard/core/MARKER
34657 \  MARKER
34658 \ ( "<spaces>name" -- )
34659 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
34660 \ with the execution semantics defined below.
34661
34662 \ name Execution: ( -- )
34663 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
34664 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
34665 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
34666 \ not necessarily provided. No other contextual information such as numeric base is affected
34667 \
34668 : MARKER
34669 CREATE
34670 HI2LO
34671 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
34672 SUB #2,Y            \ 1 Y = LFA
34673 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
34674 ADD #4,&DP          \ 3 add 2 cells
34675 LO2HI
34676 DOES>
34677 HI2LO
34678 MOV @RSP+,IP        \ -- PFA
34679 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
34680 MOV @TOS,&INIDP     \       set DP value for RST_STATE
34681 MOV @PSP+,TOS       \ --
34682 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
34683 ENDCODE
34684 [THEN]
34685
34686 MARKER {RC5TOLCD}
34687
34688 [UNDEFINED] @ [IF]
34689 \ https://forth-standard.org/standard/core/Fetch
34690 \ @     c-addr -- char   fetch char from memory
34691 CODE @
34692 MOV @TOS,TOS
34693 MOV @IP+,PC
34694 ENDCODE
34695 [THEN]
34696
34697 [UNDEFINED] CONSTANT [IF]
34698 \ https://forth-standard.org/standard/core/CONSTANT
34699 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
34700 : CONSTANT 
34701 CREATE
34702 HI2LO
34703 MOV TOS,-2(W)           \   PFA = n
34704 MOV @PSP+,TOS
34705 MOV @RSP+,IP
34706 MOV @IP+,PC
34707 ENDCODE
34708 [THEN]
34709
34710 [UNDEFINED] STATE [IF]
34711 \ https://forth-standard.org/standard/core/STATE
34712 \ STATE   -- a-addr       holds compiler state
34713 STATEADR CONSTANT STATE
34714 [THEN]
34715
34716 [UNDEFINED] = [IF]
34717 \ https://forth-standard.org/standard/core/Equal
34718 \ =      x1 x2 -- flag         test x1=x2
34719 CODE =
34720 SUB @PSP+,TOS   \ 2
34721 0<> IF          \ 2
34722     AND #0,TOS  \ 1
34723     MOV @IP+,PC \ 4
34724 THEN
34725 XOR #-1,TOS     \ 1 flag Z = 1
34726 MOV @IP+,PC     \ 4
34727 ENDCODE
34728 [THEN]
34729
34730 [UNDEFINED] IF [IF]
34731 \ https://forth-standard.org/standard/core/IF
34732 \ IF       -- IFadr    initialize conditional forward branch
34733 CODE IF       \ immediate
34734 SUB #2,PSP              \
34735 MOV TOS,0(PSP)          \
34736 MOV &DP,TOS             \ -- HERE
34737 ADD #4,&DP            \           compile one word, reserve one word
34738 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
34739 ADD #2,TOS              \ -- HERE+2=IFadr
34740 MOV @IP+,PC
34741 ENDCODE IMMEDIATE
34742 [THEN]
34743
34744 [UNDEFINED] THEN [IF]
34745 \ https://forth-standard.org/standard/core/THEN
34746 \ THEN     IFadr --                resolve forward branch
34747 CODE THEN               \ immediate
34748 MOV &DP,0(TOS)          \ -- IFadr
34749 MOV @PSP+,TOS           \ --
34750 MOV @IP+,PC
34751 ENDCODE IMMEDIATE
34752 [THEN]
34753
34754 [UNDEFINED] ELSE [IF]
34755 \ https://forth-standard.org/standard/core/ELSE
34756 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
34757 CODE ELSE     \ immediate
34758 ADD #4,&DP              \ make room to compile two words
34759 MOV &DP,W               \ W=HERE+4
34760 MOV #BRAN,-4(W)
34761 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
34762 SUB #2,W                \ HERE+2
34763 MOV W,TOS               \ -- ELSEadr
34764 MOV @IP+,PC
34765 ENDCODE IMMEDIATE
34766 [THEN]
34767
34768 [UNDEFINED] DEFER [IF]
34769 \ https://forth-standard.org/standard/core/DEFER
34770 \ DEFER "<spaces>name"   --
34771 \ Skip leading space delimiters. Parse name delimited by a space.
34772 \ Create a definition for name with the execution semantics defined below.
34773
34774 \ name Execution:   --
34775 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
34776 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
34777 : DEFER
34778 CREATE
34779 HI2LO
34780 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
34781 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
34782 MOV @RSP+,IP
34783 MOV @IP+,PC
34784 ENDCODE
34785 [THEN]
34786
34787 [UNDEFINED] DEFER! [IF]
34788 \ https://forth-standard.org/standard/core/DEFERStore
34789 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
34790 CODE DEFER!             \ xt2 xt1 --
34791 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
34792 MOV @PSP+,TOS           \ --
34793 MOV @IP+,PC
34794 ENDCODE
34795 [THEN]
34796
34797 [UNDEFINED] IS [IF]
34798 \ https://forth-standard.org/standard/core/IS
34799 \ IS <name>        xt --
34800 \ used as is :
34801 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
34802 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
34803 \ or in a definition : ... ['] U. IS DISPLAY ...
34804 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
34805 \
34806 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
34807 : IS
34808 STATE @
34809 IF  POSTPONE ['] POSTPONE DEFER! 
34810 ELSE ' DEFER! 
34811 THEN
34812 ; IMMEDIATE
34813 [THEN]
34814
34815 [UNDEFINED] >BODY [IF]
34816 \ https://forth-standard.org/standard/core/toBODY
34817 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
34818 CODE >BODY
34819 ADD #4,TOS
34820 MOV @IP+,PC
34821 ENDCODE
34822 [THEN]
34823
34824 \ CODE 20uS           \ n --      8MHz version
34825 \ BEGIN               \ 4 + 16 ~ loop
34826 \     MOV #39,rDOCON   \ 39
34827 \     BEGIN           \ 4 ~ loop
34828 \         NOP
34829 \         SUB #1,rDOCON
34830 \     0=  UNTIL
34831 \     SUB #1,TOS      \ 1
34832 \ 0= UNTIL
34833 \ MOV #XDOCON,rDOCON  \ 2
34834 \ MOV @PSP+,TOS
34835 \ MOV @RSP+,IP        \
34836 \ ENDCODE
34837
34838 CODE 20_US                      \ n --      n * 20 us
34839 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
34840     BEGIN
34841         BIT #1,&LCD_TIM_CTL     \ 3
34842     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
34843     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
34844     SUB #1,TOS                  \ 1
34845 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
34846 MOV @PSP+,TOS                   \ 2
34847 MOV @IP+,PC                     \ 4
34848 ENDCODE
34849
34850 CODE TOP_LCD                    \ LCD Sample
34851 \                               \ if write : %xxxx_WWWW --
34852 \                               \ if read  : -- %0000_RRRR
34853     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
34854     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
34855 0= IF                           \ write LCD bits pattern
34856     AND.B #LCD_DB,TOS           \ 
34857     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
34858     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
34859     MOV @PSP+,TOS               \
34860     MOV @IP+,PC
34861 THEN                            \ read LCD bits pattern
34862     SUB #2,PSP
34863     MOV TOS,0(PSP)
34864     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
34865     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
34866     AND.B #LCD_DB,TOS           \
34867     MOV @IP+,PC
34868 ENDCODE
34869
34870 CODE LCD_WRC                    \ char --         Write Char
34871     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
34872 BW1 SUB #2,PSP                  \
34873     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
34874     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
34875     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
34876     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
34877 COLON                           \ high level word starts here 
34878     TOP_LCD 2 20_US             \ write high nibble first
34879     TOP_LCD 2 20_US 
34880 ;
34881
34882 CODE LCD_WRF                    \ func --         Write Fonction
34883     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
34884     GOTO BW1
34885 ENDCODE
34886
34887 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
34888 : LCD_HOME $02 LCD_WRF 100 20_us ;
34889
34890 \ [UNDEFINED] OR [IF]
34891
34892 \ \ https://forth-standard.org/standard/core/OR
34893 \ \ C OR     x1 x2 -- x3           logical OR
34894 \ CODE OR
34895 \ BIS @PSP+,TOS
34896 \ MOV @IP+,PC
34897 \ ENDCODE
34898
34899 \ [THEN]
34900
34901 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
34902 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
34903 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
34904 \ : LCD_FN_SET        $20 OR LCD_WrF ;
34905 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
34906 \ : LCD_GOTO          $80 OR LCD_WrF ;
34907
34908
34909 \ CODE LCD_RDS                    \ -- status       Read Status
34910 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
34911 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
34912 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
34913 \ COLON                           \ starts a FORTH word
34914 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
34915 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
34916 \ HI2LO                           \ switch from FORTH to assembler
34917 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
34918 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
34919 \     MOV @RSP+,IP                \ restore IP saved by COLON
34920 \     MOV @IP+,PC                 \
34921 \ ENDCODE
34922
34923 \ CODE LCD_RDC                    \ -- char         Read Char
34924 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
34925 \     GOTO BW1
34926 \ ENDCODE
34927
34928
34929 \ ******************************\
34930 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
34931 \ ******************************\
34932 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
34933 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
34934 BIT.B #SW2,&SW2_IN              \ test switch S2
34935 0= IF                           \ case of switch S2 pressed
34936     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
34937     U< IF
34938         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
34939     THEN
34940 ELSE
34941     BIT.B #SW1,&SW1_IN          \ test switch S1 input
34942     0= IF                       \ case of Switch S1 pressed
34943         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
34944         U>= IF                  \
34945            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
34946         THEN                    \
34947     THEN                        \
34948 THEN                            \
34949 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
34950 RET                             \ 5
34951 ENDASM
34952
34953 \ ******************************\
34954 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
34955 \ ******************************\
34956 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
34957 \ ******************************\
34958 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
34959 \                               \       SMclock = 8|16|24 MHz
34960 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
34961 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
34962 \                               \       SR(9)=new Toggle bit memory (ADD on)
34963 \ ******************************\
34964 \ RC5_FirstStartBitHalfCycle:   \
34965 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
34966 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
34967 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
34968 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
34969 \ [THEN]
34970 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
34971     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
34972 [THEN]
34973 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
34974     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
34975 [THEN]
34976 MOV #1778,X                     \ RC5_Period * 1us
34977 MOV #14,W                       \ count of loop
34978 BEGIN                           \
34979 \ ******************************\
34980 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
34981 \ ******************************\                   |
34982 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
34983 \ RC5_Compute_3/4_Period:       \                   |
34984     RRUM    #1,X                \ X=1/2 cycle       |
34985     MOV     X,Y                 \                   ^
34986     RRUM    #1,Y                \ Y=1/4
34987     ADD     X,Y                 \ Y=3/4 cycle
34988     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
34989     U>= UNTIL                   \ 2
34990 \ ******************************\
34991 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
34992 \ ******************************\
34993     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
34994     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
34995     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
34996     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
34997     SUB     #1,W                \ decrement count loop
34998 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
34999 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
35000 0<> WHILE                       \ ----> out of loop ----+
35001     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
35002     BEGIN                       \                       |
35003         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
35004         CMP Y,X                 \ 1                     |   cycle time out of bound ?
35005         U>= IF                  \ 2                 ^   |   yes:
35006         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
35007         GOTO BW1                \                   |   |      quit on truncated RC5 message
35008         THEN                    \                   |   |
35009         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
35010     0<> UNTIL                   \ 2                 |   |
35011 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
35012 \ ******************************\                       |
35013 \ RC5_SampleEndOf:              \ <---------------------+
35014 \ ******************************\
35015 BIC #$30,&RC5_TIM_CTL           \   stop timer
35016 \ ******************************\
35017 \ RC5_ComputeNewRC5word         \
35018 \ ******************************\
35019 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
35020 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
35021 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
35022 \ ******************************\
35023 \ RC5_ComputeC6bit              \
35024 \ ******************************\
35025 BIT     #BIT14,T                \ test /C6 bit in T
35026 0= IF   BIS #BIT6,X             \ set C6 bit in X
35027 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
35028 \ ******************************\
35029 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
35030 \ ******************************\
35031 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
35032 \ ******************************\
35033 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
35034 XOR     @RSP,T                  \ (new XOR old) Toggle bits
35035 BIT     #UF10,T                 \ repeated RC5_command ?
35036 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
35037 XOR #UF10,0(RSP)                \ 5 toggle bit memory
35038 \ ******************************\
35039 \ Display IR_RC5 code           \
35040 \ ******************************\
35041 SUB #8,PSP                      \ TOS -- x x x x TOS
35042 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
35043 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
35044 MOV #$10,&BASEADR               \                                               set hexadecimal base
35045 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
35046 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
35047 LO2HI                           \                                               switch from assembler to FORTH
35048     LCD_CLEAR                   \                                               set LCD cursor at home
35049     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
35050     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
35051     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
35052     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
35053 HI2LO                           \     --                                        switch from FORTH to assembler
35054 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
35055 MOV @PSP+,TOS                   \     -- TOS
35056 RET
35057 ENDASM
35058
35059 \ ******************************\
35060 ASM BACKGROUND                  \
35061 \ ******************************\
35062 BEGIN
35063 \     ...                         \ insert here your background task
35064 \     ...                         \
35065 \     ...                         \
35066     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
35067     BIS &LPM_MODE,SR            \
35068 \ ******************************\
35069 \ here start all interrupts     \
35070 \ ******************************\
35071 \ here return all interrupts    \
35072 \ ******************************\
35073 AGAIN                           \
35074 ENDASM                          \
35075 \ ******************************\
35076
35077 \ ------------------------------\
35078 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
35079 \ ------------------------------\
35080 \     ...                         \ init specific I/O sys as you want
35081 \     ...                         \ before executing default WARM
35082     MOV #WARM,X                 \ ['] WARM 
35083     ADD #4,X                    \ >BODY
35084     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
35085 ENDASM
35086 \ ------------------------------\
35087
35088 \ ------------------------------\
35089 CODE STOP                       \ stops multitasking, must to be used before downloading app
35090 \ ------------------------------\
35091 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
35092     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
35093     MOV X,-2(X)                 \ restore the default background: SLEEP
35094     MOV #WARM,X
35095     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
35096     BIC.B #RC5,&IR_IE           \ clear RC5_Int
35097     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
35098     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
35099     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
35100     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
35101     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
35102 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
35103 ECHO                            \
35104 ." RC5toLCD is removed,"
35105 ."  type START to restart"
35106  WARM                           \ performs reset to reset all interrupt vectors.    
35107 ;
35108 \ ------------------------------\
35109
35110 \ ------------------------------\
35111 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
35112 \ ------------------------------\
35113 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
35114 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
35115 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
35116 \                           --       \ID input divider \ 10 = /4
35117 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
35118 \                                 -  \TBCLR TimerB Clear
35119 \                                  - \TBIE
35120 \                                   -\TBIFG
35121 \ -------------------------------\
35122 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
35123 \                  --                 \CM Capture Mode
35124 \                    --               \CCIS
35125 \                       -             \SCS
35126 \                        --           \CLLD
35127 \                          -          \CAP
35128 \                            ---      \OUTMOD \ 011 = set/reset
35129 \                               -     \CCIE
35130 \                                 -   \CCI
35131 \                                  -  \OUT
35132 \                                   - \COV
35133 \                                    -\CCIFG
35134 \ -------------------------------\
35135 \ LCD_TIM_CCRx                   \
35136 \ -------------------------------\
35137 \ LCD_TIM_EX0                    \ 
35138 \ ------------------------------\
35139 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
35140 \ ------------------------------\
35141 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
35142 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
35143 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
35144     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
35145 [THEN]
35146 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
35147     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
35148 [THEN]
35149     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
35150 \ ------------------------------\
35151 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
35152 \ ------------------------------\
35153 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
35154     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
35155 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
35156 \ ------------------------------\
35157     BIS.B #LCDVo,&LCDVo_DIR     \
35158     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
35159 \ ------------------------------\
35160     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
35161     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
35162 \ ------------------------------\
35163     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
35164     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
35165 \ ******************************\
35166 \ init RC5_Int                  \
35167 \ ******************************\
35168     BIS.B #RC5,&IR_IE           \ enable RC5_Int
35169     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
35170     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
35171 \ ******************************\
35172 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
35173 \ ******************************\
35174 \              %01 0001 0100    \ TAxCTL
35175 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
35176 \                  --           \ ID        divided by 1
35177 \                    --         \ MC        MODE = up to TAxCCRn
35178 \                        -      \ TACLR     clear timer count
35179 \                         -     \ TAIE
35180 \                          -    \ TAIFG
35181 \ ------------------------------\
35182 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
35183 \ ------------------------------\
35184 \                        000    \ TAxEX0
35185 \                        ---    \ TAIDEX    pre divisor
35186 \ ------------------------------\
35187 \          %0000 0000 0000 0101 \ TAxCCR0
35188     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
35189 \ ------------------------------\
35190 \          %0000 0000 0001 0000 \ TAxCCTL0
35191 \                   -           \ CAP capture/compare mode = compare
35192 \                        -      \ CCIEn
35193 \                             - \ CCIFGn
35194     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
35195 \ ------------------------------\
35196     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
35197 \ ------------------------------\
35198 \ define LPM mode for ACCEPT    \
35199 \ ------------------------------\
35200 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
35201 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
35202 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
35203 \ ------------------------------\
35204 \ activate I/O                  \
35205 \ ------------------------------\
35206 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
35207 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
35208 \ ------------------------------\
35209 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
35210 \ ------------------------------\
35211 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
35212 \ CMP #2,Y                        \ Power_ON event
35213 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
35214 CMP #4,Y                        \
35215 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
35216 \ CMP #6,Y                        \
35217 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
35218 \ CMP #$0A,Y                      \
35219 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
35220 \ CMP #$16,Y                      \
35221 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
35222 \ ------------------------------\
35223 COLON                           \
35224 \ ------------------------------\
35225 \ Init LCD 2x20                 \
35226 \ ------------------------------\
35227     #1000 20_US                 \ 1- wait 20 ms
35228     %011 TOP_LCD                \ 2- send DB5=DB4=1
35229     #205 20_US                  \ 3- wait 4,1 ms
35230     %011 TOP_LCD                \ 4- send again DB5=DB4=1
35231     #5 20_US                    \ 5- wait 0,1 ms
35232     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
35233     #2 20_US                    \    wait 40 us = LCD cycle
35234     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
35235     #2 20_US                    \    wait 40 us = LCD cycle
35236     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
35237     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
35238     LCD_CLEAR                   \ 10- "LCD_Clear"
35239     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
35240     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
35241     LCD_CLEAR                   \ 10- "LCD_Clear"
35242     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
35243     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
35244     CR ." I love you"           \ display message on LCD
35245     ['] CR >BODY IS CR          \ CR executes its default value
35246     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
35247     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
35248     PWR_STATE ABORT             \ init DP and continues with ABORT
35249 ;                               \
35250 \ ------------------------------\
35251
35252 \ ------------------------------\
35253 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
35254 \ ------------------------------\
35255 MOV #SLEEP,X                    \ replace default background process SLEEP
35256 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
35257 MOV #WARM,X                     \ replace default WARM
35258 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
35259 MOV X,PC                        \ then execute new WARM
35260 ENDCODE 
35261 \ ------------------------------\
35262
35263 ECHO
35264             ; downloading RC5toLCD.4th is done
35265 RST_HERE    ; this app is protected against <reset>
35266
35267
35268 RST_STATE
35269
35270 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
35271
35272 [UNDEFINED] MARKER [IF]
35273 \  https://forth-standard.org/standard/core/MARKER
35274 \  MARKER
35275 \ ( "<spaces>name" -- )
35276 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
35277 \ with the execution semantics defined below.
35278
35279 \ name Execution: ( -- )
35280 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
35281 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
35282 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
35283 \ not necessarily provided. No other contextual information such as numeric base is affected
35284 \
35285 : MARKER
35286 CREATE
35287 HI2LO
35288 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
35289 SUB #2,Y            \ 1 Y = LFA
35290 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
35291 ADD #4,&DP          \ 3 add 2 cells
35292 LO2HI
35293 DOES>
35294 HI2LO
35295 MOV @RSP+,IP        \ -- PFA
35296 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
35297 MOV @TOS,&INIDP     \       set DP value for RST_STATE
35298 MOV @PSP+,TOS       \ --
35299 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
35300 ENDCODE
35301 [THEN]
35302
35303 MARKER {RC5TOLCD}
35304
35305 [UNDEFINED] @ [IF]
35306 \ https://forth-standard.org/standard/core/Fetch
35307 \ @     c-addr -- char   fetch char from memory
35308 CODE @
35309 MOV @TOS,TOS
35310 MOV @IP+,PC
35311 ENDCODE
35312 [THEN]
35313
35314 [UNDEFINED] CONSTANT [IF]
35315 \ https://forth-standard.org/standard/core/CONSTANT
35316 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
35317 : CONSTANT 
35318 CREATE
35319 HI2LO
35320 MOV TOS,-2(W)           \   PFA = n
35321 MOV @PSP+,TOS
35322 MOV @RSP+,IP
35323 MOV @IP+,PC
35324 ENDCODE
35325 [THEN]
35326
35327 [UNDEFINED] STATE [IF]
35328 \ https://forth-standard.org/standard/core/STATE
35329 \ STATE   -- a-addr       holds compiler state
35330 STATEADR CONSTANT STATE
35331 [THEN]
35332
35333 [UNDEFINED] = [IF]
35334 \ https://forth-standard.org/standard/core/Equal
35335 \ =      x1 x2 -- flag         test x1=x2
35336 CODE =
35337 SUB @PSP+,TOS   \ 2
35338 0<> IF          \ 2
35339     AND #0,TOS  \ 1
35340     MOV @IP+,PC \ 4
35341 THEN
35342 XOR #-1,TOS     \ 1 flag Z = 1
35343 MOV @IP+,PC     \ 4
35344 ENDCODE
35345 [THEN]
35346
35347 [UNDEFINED] IF [IF]
35348 \ https://forth-standard.org/standard/core/IF
35349 \ IF       -- IFadr    initialize conditional forward branch
35350 CODE IF       \ immediate
35351 SUB #2,PSP              \
35352 MOV TOS,0(PSP)          \
35353 MOV &DP,TOS             \ -- HERE
35354 ADD #4,&DP            \           compile one word, reserve one word
35355 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
35356 ADD #2,TOS              \ -- HERE+2=IFadr
35357 MOV @IP+,PC
35358 ENDCODE IMMEDIATE
35359 [THEN]
35360
35361 [UNDEFINED] THEN [IF]
35362 \ https://forth-standard.org/standard/core/THEN
35363 \ THEN     IFadr --                resolve forward branch
35364 CODE THEN               \ immediate
35365 MOV &DP,0(TOS)          \ -- IFadr
35366 MOV @PSP+,TOS           \ --
35367 MOV @IP+,PC
35368 ENDCODE IMMEDIATE
35369 [THEN]
35370
35371 [UNDEFINED] ELSE [IF]
35372 \ https://forth-standard.org/standard/core/ELSE
35373 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
35374 CODE ELSE     \ immediate
35375 ADD #4,&DP              \ make room to compile two words
35376 MOV &DP,W               \ W=HERE+4
35377 MOV #BRAN,-4(W)
35378 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
35379 SUB #2,W                \ HERE+2
35380 MOV W,TOS               \ -- ELSEadr
35381 MOV @IP+,PC
35382 ENDCODE IMMEDIATE
35383 [THEN]
35384
35385 [UNDEFINED] DEFER [IF]
35386 \ https://forth-standard.org/standard/core/DEFER
35387 \ DEFER "<spaces>name"   --
35388 \ Skip leading space delimiters. Parse name delimited by a space.
35389 \ Create a definition for name with the execution semantics defined below.
35390
35391 \ name Execution:   --
35392 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
35393 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
35394 : DEFER
35395 CREATE
35396 HI2LO
35397 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
35398 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
35399 MOV @RSP+,IP
35400 MOV @IP+,PC
35401 ENDCODE
35402 [THEN]
35403
35404 [UNDEFINED] DEFER! [IF]
35405 \ https://forth-standard.org/standard/core/DEFERStore
35406 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
35407 CODE DEFER!             \ xt2 xt1 --
35408 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
35409 MOV @PSP+,TOS           \ --
35410 MOV @IP+,PC
35411 ENDCODE
35412 [THEN]
35413
35414 [UNDEFINED] IS [IF]
35415 \ https://forth-standard.org/standard/core/IS
35416 \ IS <name>        xt --
35417 \ used as is :
35418 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
35419 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
35420 \ or in a definition : ... ['] U. IS DISPLAY ...
35421 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
35422 \
35423 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
35424 : IS
35425 STATE @
35426 IF  POSTPONE ['] POSTPONE DEFER! 
35427 ELSE ' DEFER! 
35428 THEN
35429 ; IMMEDIATE
35430 [THEN]
35431
35432 [UNDEFINED] >BODY [IF]
35433 \ https://forth-standard.org/standard/core/toBODY
35434 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
35435 CODE >BODY
35436 ADD #4,TOS
35437 MOV @IP+,PC
35438 ENDCODE
35439 [THEN]
35440
35441 \ CODE 20uS           \ n --      8MHz version
35442 \ BEGIN               \ 4 + 16 ~ loop
35443 \     MOV #39,rDOCON   \ 39
35444 \     BEGIN           \ 4 ~ loop
35445 \         NOP
35446 \         SUB #1,rDOCON
35447 \     0=  UNTIL
35448 \     SUB #1,TOS      \ 1
35449 \ 0= UNTIL
35450 \ MOV #XDOCON,rDOCON  \ 2
35451 \ MOV @PSP+,TOS
35452 \ MOV @RSP+,IP        \
35453 \ ENDCODE
35454
35455 CODE 20_US                      \ n --      n * 20 us
35456 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
35457     BEGIN
35458         BIT #1,&LCD_TIM_CTL     \ 3
35459     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
35460     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
35461     SUB #1,TOS                  \ 1
35462 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
35463 MOV @PSP+,TOS                   \ 2
35464 MOV @IP+,PC                     \ 4
35465 ENDCODE
35466
35467 CODE TOP_LCD                    \ LCD Sample
35468 \                               \ if write : %xxxx_WWWW --
35469 \                               \ if read  : -- %0000_RRRR
35470     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
35471     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
35472 0= IF                           \ write LCD bits pattern
35473     AND.B #LCD_DB,TOS           \ 
35474     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
35475     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
35476     MOV @PSP+,TOS               \
35477     MOV @IP+,PC
35478 THEN                            \ read LCD bits pattern
35479     SUB #2,PSP
35480     MOV TOS,0(PSP)
35481     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
35482     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
35483     AND.B #LCD_DB,TOS           \
35484     MOV @IP+,PC
35485 ENDCODE
35486
35487 CODE LCD_WRC                    \ char --         Write Char
35488     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
35489 BW1 SUB #2,PSP                  \
35490     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
35491     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
35492     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
35493     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
35494 COLON                           \ high level word starts here 
35495     TOP_LCD 2 20_US             \ write high nibble first
35496     TOP_LCD 2 20_US 
35497 ;
35498
35499 CODE LCD_WRF                    \ func --         Write Fonction
35500     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
35501     GOTO BW1
35502 ENDCODE
35503
35504 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
35505 : LCD_HOME $02 LCD_WRF 100 20_us ;
35506
35507 \ [UNDEFINED] OR [IF]
35508
35509 \ \ https://forth-standard.org/standard/core/OR
35510 \ \ C OR     x1 x2 -- x3           logical OR
35511 \ CODE OR
35512 \ BIS @PSP+,TOS
35513 \ MOV @IP+,PC
35514 \ ENDCODE
35515
35516 \ [THEN]
35517
35518 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
35519 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
35520 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
35521 \ : LCD_FN_SET        $20 OR LCD_WrF ;
35522 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
35523 \ : LCD_GOTO          $80 OR LCD_WrF ;
35524
35525
35526 \ CODE LCD_RDS                    \ -- status       Read Status
35527 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
35528 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
35529 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
35530 \ COLON                           \ starts a FORTH word
35531 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
35532 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
35533 \ HI2LO                           \ switch from FORTH to assembler
35534 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
35535 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
35536 \     MOV @RSP+,IP                \ restore IP saved by COLON
35537 \     MOV @IP+,PC                 \
35538 \ ENDCODE
35539
35540 \ CODE LCD_RDC                    \ -- char         Read Char
35541 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
35542 \     GOTO BW1
35543 \ ENDCODE
35544
35545
35546 \ ******************************\
35547 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
35548 \ ******************************\
35549 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
35550 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
35551 BIT.B #SW2,&SW2_IN              \ test switch S2
35552 0= IF                           \ case of switch S2 pressed
35553     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
35554     U< IF
35555         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
35556     THEN
35557 ELSE
35558     BIT.B #SW1,&SW1_IN          \ test switch S1 input
35559     0= IF                       \ case of Switch S1 pressed
35560         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
35561         U>= IF                  \
35562            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
35563         THEN                    \
35564     THEN                        \
35565 THEN                            \
35566 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
35567 RET                             \ 5
35568 ENDASM
35569
35570 \ ******************************\
35571 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
35572 \ ******************************\
35573 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
35574 \ ******************************\
35575 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
35576 \                               \       SMclock = 8|16|24 MHz
35577 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
35578 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
35579 \                               \       SR(9)=new Toggle bit memory (ADD on)
35580 \ ******************************\
35581 \ RC5_FirstStartBitHalfCycle:   \
35582 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
35583 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
35584 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
35585 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
35586 \ [THEN]
35587 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
35588     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
35589 [THEN]
35590 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
35591     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
35592 [THEN]
35593 MOV #1778,X                     \ RC5_Period * 1us
35594 MOV #14,W                       \ count of loop
35595 BEGIN                           \
35596 \ ******************************\
35597 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
35598 \ ******************************\                   |
35599 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
35600 \ RC5_Compute_3/4_Period:       \                   |
35601     RRUM    #1,X                \ X=1/2 cycle       |
35602     MOV     X,Y                 \                   ^
35603     RRUM    #1,Y                \ Y=1/4
35604     ADD     X,Y                 \ Y=3/4 cycle
35605     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
35606     U>= UNTIL                   \ 2
35607 \ ******************************\
35608 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
35609 \ ******************************\
35610     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
35611     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
35612     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
35613     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
35614     SUB     #1,W                \ decrement count loop
35615 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
35616 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
35617 0<> WHILE                       \ ----> out of loop ----+
35618     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
35619     BEGIN                       \                       |
35620         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
35621         CMP Y,X                 \ 1                     |   cycle time out of bound ?
35622         U>= IF                  \ 2                 ^   |   yes:
35623         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
35624         GOTO BW1                \                   |   |      quit on truncated RC5 message
35625         THEN                    \                   |   |
35626         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
35627     0<> UNTIL                   \ 2                 |   |
35628 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
35629 \ ******************************\                       |
35630 \ RC5_SampleEndOf:              \ <---------------------+
35631 \ ******************************\
35632 BIC #$30,&RC5_TIM_CTL           \   stop timer
35633 \ ******************************\
35634 \ RC5_ComputeNewRC5word         \
35635 \ ******************************\
35636 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
35637 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
35638 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
35639 \ ******************************\
35640 \ RC5_ComputeC6bit              \
35641 \ ******************************\
35642 BIT     #BIT14,T                \ test /C6 bit in T
35643 0= IF   BIS #BIT6,X             \ set C6 bit in X
35644 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
35645 \ ******************************\
35646 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
35647 \ ******************************\
35648 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
35649 \ ******************************\
35650 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
35651 XOR     @RSP,T                  \ (new XOR old) Toggle bits
35652 BIT     #UF10,T                 \ repeated RC5_command ?
35653 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
35654 XOR #UF10,0(RSP)                \ 5 toggle bit memory
35655 \ ******************************\
35656 \ Display IR_RC5 code           \
35657 \ ******************************\
35658 SUB #8,PSP                      \ TOS -- x x x x TOS
35659 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
35660 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
35661 MOV #$10,&BASEADR               \                                               set hexadecimal base
35662 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
35663 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
35664 LO2HI                           \                                               switch from assembler to FORTH
35665     LCD_CLEAR                   \                                               set LCD cursor at home
35666     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
35667     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
35668     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
35669     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
35670 HI2LO                           \     --                                        switch from FORTH to assembler
35671 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
35672 MOV @PSP+,TOS                   \     -- TOS
35673 RET
35674 ENDASM
35675
35676 \ ******************************\
35677 ASM BACKGROUND                  \
35678 \ ******************************\
35679 BEGIN
35680 \     ...                         \ insert here your background task
35681 \     ...                         \
35682 \     ...                         \
35683     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
35684     BIS &LPM_MODE,SR            \
35685 \ ******************************\
35686 \ here start all interrupts     \
35687 \ ******************************\
35688 \ here return all interrupts    \
35689 \ ******************************\
35690 AGAIN                           \
35691 ENDASM                          \
35692 \ ******************************\
35693
35694 \ ------------------------------\
35695 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
35696 \ ------------------------------\
35697 \     ...                         \ init specific I/O sys as you want
35698 \     ...                         \ before executing default WARM
35699     MOV #WARM,X                 \ ['] WARM 
35700     ADD #4,X                    \ >BODY
35701     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
35702 ENDASM
35703 \ ------------------------------\
35704
35705 \ ------------------------------\
35706 CODE STOP                       \ stops multitasking, must to be used before downloading app
35707 \ ------------------------------\
35708 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
35709     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
35710     MOV X,-2(X)                 \ restore the default background: SLEEP
35711     MOV #WARM,X
35712     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
35713     BIC.B #RC5,&IR_IE           \ clear RC5_Int
35714     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
35715     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
35716     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
35717     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
35718     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
35719 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
35720 ECHO                            \
35721 ." RC5toLCD is removed,"
35722 ."  type START to restart"
35723  WARM                           \ performs reset to reset all interrupt vectors.    
35724 ;
35725 \ ------------------------------\
35726
35727 \ ------------------------------\
35728 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
35729 \ ------------------------------\
35730 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
35731 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
35732 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
35733 \                           --       \ID input divider \ 10 = /4
35734 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
35735 \                                 -  \TBCLR TimerB Clear
35736 \                                  - \TBIE
35737 \                                   -\TBIFG
35738 \ -------------------------------\
35739 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
35740 \                  --                 \CM Capture Mode
35741 \                    --               \CCIS
35742 \                       -             \SCS
35743 \                        --           \CLLD
35744 \                          -          \CAP
35745 \                            ---      \OUTMOD \ 011 = set/reset
35746 \                               -     \CCIE
35747 \                                 -   \CCI
35748 \                                  -  \OUT
35749 \                                   - \COV
35750 \                                    -\CCIFG
35751 \ -------------------------------\
35752 \ LCD_TIM_CCRx                   \
35753 \ -------------------------------\
35754 \ LCD_TIM_EX0                    \ 
35755 \ ------------------------------\
35756 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
35757 \ ------------------------------\
35758 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
35759 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
35760 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
35761     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
35762 [THEN]
35763 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
35764     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
35765 [THEN]
35766     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
35767 \ ------------------------------\
35768 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
35769 \ ------------------------------\
35770 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
35771     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
35772 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
35773 \ ------------------------------\
35774     BIS.B #LCDVo,&LCDVo_DIR     \
35775     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
35776 \ ------------------------------\
35777     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
35778     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
35779 \ ------------------------------\
35780     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
35781     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
35782 \ ******************************\
35783 \ init RC5_Int                  \
35784 \ ******************************\
35785     BIS.B #RC5,&IR_IE           \ enable RC5_Int
35786     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
35787     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
35788 \ ******************************\
35789 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
35790 \ ******************************\
35791 \              %01 0001 0100    \ TAxCTL
35792 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
35793 \                  --           \ ID        divided by 1
35794 \                    --         \ MC        MODE = up to TAxCCRn
35795 \                        -      \ TACLR     clear timer count
35796 \                         -     \ TAIE
35797 \                          -    \ TAIFG
35798 \ ------------------------------\
35799 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
35800 \ ------------------------------\
35801 \                        000    \ TAxEX0
35802 \                        ---    \ TAIDEX    pre divisor
35803 \ ------------------------------\
35804 \          %0000 0000 0000 0101 \ TAxCCR0
35805     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
35806 \ ------------------------------\
35807 \          %0000 0000 0001 0000 \ TAxCCTL0
35808 \                   -           \ CAP capture/compare mode = compare
35809 \                        -      \ CCIEn
35810 \                             - \ CCIFGn
35811     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
35812 \ ------------------------------\
35813     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
35814 \ ------------------------------\
35815 \ define LPM mode for ACCEPT    \
35816 \ ------------------------------\
35817 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
35818 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
35819 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
35820 \ ------------------------------\
35821 \ activate I/O                  \
35822 \ ------------------------------\
35823 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
35824 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
35825 \ ------------------------------\
35826 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
35827 \ ------------------------------\
35828 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
35829 \ CMP #2,Y                        \ Power_ON event
35830 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
35831 CMP #4,Y                        \
35832 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
35833 \ CMP #6,Y                        \
35834 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
35835 \ CMP #$0A,Y                      \
35836 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
35837 \ CMP #$16,Y                      \
35838 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
35839 \ ------------------------------\
35840 COLON                           \
35841 \ ------------------------------\
35842 \ Init LCD 2x20                 \
35843 \ ------------------------------\
35844     #1000 20_US                 \ 1- wait 20 ms
35845     %011 TOP_LCD                \ 2- send DB5=DB4=1
35846     #205 20_US                  \ 3- wait 4,1 ms
35847     %011 TOP_LCD                \ 4- send again DB5=DB4=1
35848     #5 20_US                    \ 5- wait 0,1 ms
35849     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
35850     #2 20_US                    \    wait 40 us = LCD cycle
35851     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
35852     #2 20_US                    \    wait 40 us = LCD cycle
35853     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
35854     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
35855     LCD_CLEAR                   \ 10- "LCD_Clear"
35856     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
35857     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
35858     LCD_CLEAR                   \ 10- "LCD_Clear"
35859     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
35860     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
35861     CR ." I love you"           \ display message on LCD
35862     ['] CR >BODY IS CR          \ CR executes its default value
35863     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
35864     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
35865     PWR_STATE ABORT             \ init DP and continues with ABORT
35866 ;                               \
35867 \ ------------------------------\
35868
35869 \ ------------------------------\
35870 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
35871 \ ------------------------------\
35872 MOV #SLEEP,X                    \ replace default background process SLEEP
35873 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
35874 MOV #WARM,X                     \ replace default WARM
35875 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
35876 MOV X,PC                        \ then execute new WARM
35877 ENDCODE 
35878 \ ------------------------------\
35879
35880 ECHO
35881             ; downloading RC5toLCD.4th is done
35882 RST_HERE    ; this app is protected against <reset>
35883
35884
35885 RST_STATE
35886
35887 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
35888
35889 [UNDEFINED] MARKER [IF]
35890 \  https://forth-standard.org/standard/core/MARKER
35891 \  MARKER
35892 \ ( "<spaces>name" -- )
35893 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
35894 \ with the execution semantics defined below.
35895
35896 \ name Execution: ( -- )
35897 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
35898 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
35899 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
35900 \ not necessarily provided. No other contextual information such as numeric base is affected
35901 \
35902 : MARKER
35903 CREATE
35904 HI2LO
35905 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
35906 SUB #2,Y            \ 1 Y = LFA
35907 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
35908 ADD #4,&DP          \ 3 add 2 cells
35909 LO2HI
35910 DOES>
35911 HI2LO
35912 MOV @RSP+,IP        \ -- PFA
35913 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
35914 MOV @TOS,&INIDP     \       set DP value for RST_STATE
35915 MOV @PSP+,TOS       \ --
35916 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
35917 ENDCODE
35918 [THEN]
35919
35920 MARKER {RC5TOLCD}
35921
35922 [UNDEFINED] @ [IF]
35923 \ https://forth-standard.org/standard/core/Fetch
35924 \ @     c-addr -- char   fetch char from memory
35925 CODE @
35926 MOV @TOS,TOS
35927 MOV @IP+,PC
35928 ENDCODE
35929 [THEN]
35930
35931 [UNDEFINED] CONSTANT [IF]
35932 \ https://forth-standard.org/standard/core/CONSTANT
35933 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
35934 : CONSTANT 
35935 CREATE
35936 HI2LO
35937 MOV TOS,-2(W)           \   PFA = n
35938 MOV @PSP+,TOS
35939 MOV @RSP+,IP
35940 MOV @IP+,PC
35941 ENDCODE
35942 [THEN]
35943
35944 [UNDEFINED] STATE [IF]
35945 \ https://forth-standard.org/standard/core/STATE
35946 \ STATE   -- a-addr       holds compiler state
35947 STATEADR CONSTANT STATE
35948 [THEN]
35949
35950 [UNDEFINED] = [IF]
35951 \ https://forth-standard.org/standard/core/Equal
35952 \ =      x1 x2 -- flag         test x1=x2
35953 CODE =
35954 SUB @PSP+,TOS   \ 2
35955 0<> IF          \ 2
35956     AND #0,TOS  \ 1
35957     MOV @IP+,PC \ 4
35958 THEN
35959 XOR #-1,TOS     \ 1 flag Z = 1
35960 MOV @IP+,PC     \ 4
35961 ENDCODE
35962 [THEN]
35963
35964 [UNDEFINED] IF [IF]
35965 \ https://forth-standard.org/standard/core/IF
35966 \ IF       -- IFadr    initialize conditional forward branch
35967 CODE IF       \ immediate
35968 SUB #2,PSP              \
35969 MOV TOS,0(PSP)          \
35970 MOV &DP,TOS             \ -- HERE
35971 ADD #4,&DP            \           compile one word, reserve one word
35972 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
35973 ADD #2,TOS              \ -- HERE+2=IFadr
35974 MOV @IP+,PC
35975 ENDCODE IMMEDIATE
35976 [THEN]
35977
35978 [UNDEFINED] THEN [IF]
35979 \ https://forth-standard.org/standard/core/THEN
35980 \ THEN     IFadr --                resolve forward branch
35981 CODE THEN               \ immediate
35982 MOV &DP,0(TOS)          \ -- IFadr
35983 MOV @PSP+,TOS           \ --
35984 MOV @IP+,PC
35985 ENDCODE IMMEDIATE
35986 [THEN]
35987
35988 [UNDEFINED] ELSE [IF]
35989 \ https://forth-standard.org/standard/core/ELSE
35990 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
35991 CODE ELSE     \ immediate
35992 ADD #4,&DP              \ make room to compile two words
35993 MOV &DP,W               \ W=HERE+4
35994 MOV #BRAN,-4(W)
35995 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
35996 SUB #2,W                \ HERE+2
35997 MOV W,TOS               \ -- ELSEadr
35998 MOV @IP+,PC
35999 ENDCODE IMMEDIATE
36000 [THEN]
36001
36002 [UNDEFINED] DEFER [IF]
36003 \ https://forth-standard.org/standard/core/DEFER
36004 \ DEFER "<spaces>name"   --
36005 \ Skip leading space delimiters. Parse name delimited by a space.
36006 \ Create a definition for name with the execution semantics defined below.
36007
36008 \ name Execution:   --
36009 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
36010 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
36011 : DEFER
36012 CREATE
36013 HI2LO
36014 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
36015 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
36016 MOV @RSP+,IP
36017 MOV @IP+,PC
36018 ENDCODE
36019 [THEN]
36020
36021 [UNDEFINED] DEFER! [IF]
36022 \ https://forth-standard.org/standard/core/DEFERStore
36023 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
36024 CODE DEFER!             \ xt2 xt1 --
36025 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
36026 MOV @PSP+,TOS           \ --
36027 MOV @IP+,PC
36028 ENDCODE
36029 [THEN]
36030
36031 [UNDEFINED] IS [IF]
36032 \ https://forth-standard.org/standard/core/IS
36033 \ IS <name>        xt --
36034 \ used as is :
36035 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
36036 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
36037 \ or in a definition : ... ['] U. IS DISPLAY ...
36038 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
36039 \
36040 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
36041 : IS
36042 STATE @
36043 IF  POSTPONE ['] POSTPONE DEFER! 
36044 ELSE ' DEFER! 
36045 THEN
36046 ; IMMEDIATE
36047 [THEN]
36048
36049 [UNDEFINED] >BODY [IF]
36050 \ https://forth-standard.org/standard/core/toBODY
36051 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
36052 CODE >BODY
36053 ADD #4,TOS
36054 MOV @IP+,PC
36055 ENDCODE
36056 [THEN]
36057
36058 \ CODE 20uS           \ n --      8MHz version
36059 \ BEGIN               \ 4 + 16 ~ loop
36060 \     MOV #39,rDOCON   \ 39
36061 \     BEGIN           \ 4 ~ loop
36062 \         NOP
36063 \         SUB #1,rDOCON
36064 \     0=  UNTIL
36065 \     SUB #1,TOS      \ 1
36066 \ 0= UNTIL
36067 \ MOV #XDOCON,rDOCON  \ 2
36068 \ MOV @PSP+,TOS
36069 \ MOV @RSP+,IP        \
36070 \ ENDCODE
36071
36072 CODE 20_US                      \ n --      n * 20 us
36073 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
36074     BEGIN
36075         BIT #1,&LCD_TIM_CTL     \ 3
36076     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
36077     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
36078     SUB #1,TOS                  \ 1
36079 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
36080 MOV @PSP+,TOS                   \ 2
36081 MOV @IP+,PC                     \ 4
36082 ENDCODE
36083
36084 CODE TOP_LCD                    \ LCD Sample
36085 \                               \ if write : %xxxx_WWWW --
36086 \                               \ if read  : -- %0000_RRRR
36087     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
36088     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
36089 0= IF                           \ write LCD bits pattern
36090     AND.B #LCD_DB,TOS           \ 
36091     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
36092     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
36093     MOV @PSP+,TOS               \
36094     MOV @IP+,PC
36095 THEN                            \ read LCD bits pattern
36096     SUB #2,PSP
36097     MOV TOS,0(PSP)
36098     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
36099     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
36100     AND.B #LCD_DB,TOS           \
36101     MOV @IP+,PC
36102 ENDCODE
36103
36104 CODE LCD_WRC                    \ char --         Write Char
36105     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
36106 BW1 SUB #2,PSP                  \
36107     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
36108     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
36109     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
36110     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
36111 COLON                           \ high level word starts here 
36112     TOP_LCD 2 20_US             \ write high nibble first
36113     TOP_LCD 2 20_US 
36114 ;
36115
36116 CODE LCD_WRF                    \ func --         Write Fonction
36117     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
36118     GOTO BW1
36119 ENDCODE
36120
36121 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
36122 : LCD_HOME $02 LCD_WRF 100 20_us ;
36123
36124 \ [UNDEFINED] OR [IF]
36125
36126 \ \ https://forth-standard.org/standard/core/OR
36127 \ \ C OR     x1 x2 -- x3           logical OR
36128 \ CODE OR
36129 \ BIS @PSP+,TOS
36130 \ MOV @IP+,PC
36131 \ ENDCODE
36132
36133 \ [THEN]
36134
36135 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
36136 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
36137 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
36138 \ : LCD_FN_SET        $20 OR LCD_WrF ;
36139 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
36140 \ : LCD_GOTO          $80 OR LCD_WrF ;
36141
36142
36143 \ CODE LCD_RDS                    \ -- status       Read Status
36144 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
36145 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
36146 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
36147 \ COLON                           \ starts a FORTH word
36148 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
36149 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
36150 \ HI2LO                           \ switch from FORTH to assembler
36151 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
36152 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
36153 \     MOV @RSP+,IP                \ restore IP saved by COLON
36154 \     MOV @IP+,PC                 \
36155 \ ENDCODE
36156
36157 \ CODE LCD_RDC                    \ -- char         Read Char
36158 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
36159 \     GOTO BW1
36160 \ ENDCODE
36161
36162
36163 \ ******************************\
36164 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
36165 \ ******************************\
36166 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
36167 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
36168 BIT.B #SW2,&SW2_IN              \ test switch S2
36169 0= IF                           \ case of switch S2 pressed
36170     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
36171     U< IF
36172         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
36173     THEN
36174 ELSE
36175     BIT.B #SW1,&SW1_IN          \ test switch S1 input
36176     0= IF                       \ case of Switch S1 pressed
36177         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
36178         U>= IF                  \
36179            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
36180         THEN                    \
36181     THEN                        \
36182 THEN                            \
36183 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
36184 RET                             \ 5
36185 ENDASM
36186
36187 \ ******************************\
36188 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
36189 \ ******************************\
36190 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
36191 \ ******************************\
36192 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
36193 \                               \       SMclock = 8|16|24 MHz
36194 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
36195 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
36196 \                               \       SR(9)=new Toggle bit memory (ADD on)
36197 \ ******************************\
36198 \ RC5_FirstStartBitHalfCycle:   \
36199 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
36200 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
36201 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
36202 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
36203 \ [THEN]
36204 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
36205     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
36206 [THEN]
36207 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
36208     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
36209 [THEN]
36210 MOV #1778,X                     \ RC5_Period * 1us
36211 MOV #14,W                       \ count of loop
36212 BEGIN                           \
36213 \ ******************************\
36214 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
36215 \ ******************************\                   |
36216 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
36217 \ RC5_Compute_3/4_Period:       \                   |
36218     RRUM    #1,X                \ X=1/2 cycle       |
36219     MOV     X,Y                 \                   ^
36220     RRUM    #1,Y                \ Y=1/4
36221     ADD     X,Y                 \ Y=3/4 cycle
36222     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
36223     U>= UNTIL                   \ 2
36224 \ ******************************\
36225 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
36226 \ ******************************\
36227     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
36228     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
36229     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
36230     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
36231     SUB     #1,W                \ decrement count loop
36232 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
36233 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
36234 0<> WHILE                       \ ----> out of loop ----+
36235     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
36236     BEGIN                       \                       |
36237         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
36238         CMP Y,X                 \ 1                     |   cycle time out of bound ?
36239         U>= IF                  \ 2                 ^   |   yes:
36240         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
36241         GOTO BW1                \                   |   |      quit on truncated RC5 message
36242         THEN                    \                   |   |
36243         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
36244     0<> UNTIL                   \ 2                 |   |
36245 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
36246 \ ******************************\                       |
36247 \ RC5_SampleEndOf:              \ <---------------------+
36248 \ ******************************\
36249 BIC #$30,&RC5_TIM_CTL           \   stop timer
36250 \ ******************************\
36251 \ RC5_ComputeNewRC5word         \
36252 \ ******************************\
36253 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
36254 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
36255 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
36256 \ ******************************\
36257 \ RC5_ComputeC6bit              \
36258 \ ******************************\
36259 BIT     #BIT14,T                \ test /C6 bit in T
36260 0= IF   BIS #BIT6,X             \ set C6 bit in X
36261 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
36262 \ ******************************\
36263 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
36264 \ ******************************\
36265 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
36266 \ ******************************\
36267 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
36268 XOR     @RSP,T                  \ (new XOR old) Toggle bits
36269 BIT     #UF10,T                 \ repeated RC5_command ?
36270 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
36271 XOR #UF10,0(RSP)                \ 5 toggle bit memory
36272 \ ******************************\
36273 \ Display IR_RC5 code           \
36274 \ ******************************\
36275 SUB #8,PSP                      \ TOS -- x x x x TOS
36276 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
36277 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
36278 MOV #$10,&BASEADR               \                                               set hexadecimal base
36279 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
36280 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
36281 LO2HI                           \                                               switch from assembler to FORTH
36282     LCD_CLEAR                   \                                               set LCD cursor at home
36283     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
36284     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
36285     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
36286     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
36287 HI2LO                           \     --                                        switch from FORTH to assembler
36288 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
36289 MOV @PSP+,TOS                   \     -- TOS
36290 RET
36291 ENDASM
36292
36293 \ ******************************\
36294 ASM BACKGROUND                  \
36295 \ ******************************\
36296 BEGIN
36297 \     ...                         \ insert here your background task
36298 \     ...                         \
36299 \     ...                         \
36300     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
36301     BIS &LPM_MODE,SR            \
36302 \ ******************************\
36303 \ here start all interrupts     \
36304 \ ******************************\
36305 \ here return all interrupts    \
36306 \ ******************************\
36307 AGAIN                           \
36308 ENDASM                          \
36309 \ ******************************\
36310
36311 \ ------------------------------\
36312 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
36313 \ ------------------------------\
36314 \     ...                         \ init specific I/O sys as you want
36315 \     ...                         \ before executing default WARM
36316     MOV #WARM,X                 \ ['] WARM 
36317     ADD #4,X                    \ >BODY
36318     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
36319 ENDASM
36320 \ ------------------------------\
36321
36322 \ ------------------------------\
36323 CODE STOP                       \ stops multitasking, must to be used before downloading app
36324 \ ------------------------------\
36325 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
36326     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
36327     MOV X,-2(X)                 \ restore the default background: SLEEP
36328     MOV #WARM,X
36329     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
36330     BIC.B #RC5,&IR_IE           \ clear RC5_Int
36331     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
36332     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
36333     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
36334     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
36335     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
36336 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
36337 ECHO                            \
36338 ." RC5toLCD is removed,"
36339 ."  type START to restart"
36340  WARM                           \ performs reset to reset all interrupt vectors.    
36341 ;
36342 \ ------------------------------\
36343
36344 \ ------------------------------\
36345 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
36346 \ ------------------------------\
36347 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
36348 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
36349 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
36350 \                           --       \ID input divider \ 10 = /4
36351 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
36352 \                                 -  \TBCLR TimerB Clear
36353 \                                  - \TBIE
36354 \                                   -\TBIFG
36355 \ -------------------------------\
36356 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
36357 \                  --                 \CM Capture Mode
36358 \                    --               \CCIS
36359 \                       -             \SCS
36360 \                        --           \CLLD
36361 \                          -          \CAP
36362 \                            ---      \OUTMOD \ 011 = set/reset
36363 \                               -     \CCIE
36364 \                                 -   \CCI
36365 \                                  -  \OUT
36366 \                                   - \COV
36367 \                                    -\CCIFG
36368 \ -------------------------------\
36369 \ LCD_TIM_CCRx                   \
36370 \ -------------------------------\
36371 \ LCD_TIM_EX0                    \ 
36372 \ ------------------------------\
36373 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
36374 \ ------------------------------\
36375 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
36376 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
36377 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
36378     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
36379 [THEN]
36380 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
36381     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
36382 [THEN]
36383     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
36384 \ ------------------------------\
36385 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
36386 \ ------------------------------\
36387 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
36388     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
36389 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
36390 \ ------------------------------\
36391     BIS.B #LCDVo,&LCDVo_DIR     \
36392     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
36393 \ ------------------------------\
36394     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
36395     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
36396 \ ------------------------------\
36397     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
36398     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
36399 \ ******************************\
36400 \ init RC5_Int                  \
36401 \ ******************************\
36402     BIS.B #RC5,&IR_IE           \ enable RC5_Int
36403     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
36404     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
36405 \ ******************************\
36406 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
36407 \ ******************************\
36408 \              %01 0001 0100    \ TAxCTL
36409 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
36410 \                  --           \ ID        divided by 1
36411 \                    --         \ MC        MODE = up to TAxCCRn
36412 \                        -      \ TACLR     clear timer count
36413 \                         -     \ TAIE
36414 \                          -    \ TAIFG
36415 \ ------------------------------\
36416 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
36417 \ ------------------------------\
36418 \                        000    \ TAxEX0
36419 \                        ---    \ TAIDEX    pre divisor
36420 \ ------------------------------\
36421 \          %0000 0000 0000 0101 \ TAxCCR0
36422     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
36423 \ ------------------------------\
36424 \          %0000 0000 0001 0000 \ TAxCCTL0
36425 \                   -           \ CAP capture/compare mode = compare
36426 \                        -      \ CCIEn
36427 \                             - \ CCIFGn
36428     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
36429 \ ------------------------------\
36430     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
36431 \ ------------------------------\
36432 \ define LPM mode for ACCEPT    \
36433 \ ------------------------------\
36434 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
36435 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
36436 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
36437 \ ------------------------------\
36438 \ activate I/O                  \
36439 \ ------------------------------\
36440 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
36441 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
36442 \ ------------------------------\
36443 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
36444 \ ------------------------------\
36445 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
36446 \ CMP #2,Y                        \ Power_ON event
36447 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
36448 CMP #4,Y                        \
36449 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
36450 \ CMP #6,Y                        \
36451 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
36452 \ CMP #$0A,Y                      \
36453 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
36454 \ CMP #$16,Y                      \
36455 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
36456 \ ------------------------------\
36457 COLON                           \
36458 \ ------------------------------\
36459 \ Init LCD 2x20                 \
36460 \ ------------------------------\
36461     #1000 20_US                 \ 1- wait 20 ms
36462     %011 TOP_LCD                \ 2- send DB5=DB4=1
36463     #205 20_US                  \ 3- wait 4,1 ms
36464     %011 TOP_LCD                \ 4- send again DB5=DB4=1
36465     #5 20_US                    \ 5- wait 0,1 ms
36466     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
36467     #2 20_US                    \    wait 40 us = LCD cycle
36468     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
36469     #2 20_US                    \    wait 40 us = LCD cycle
36470     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
36471     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
36472     LCD_CLEAR                   \ 10- "LCD_Clear"
36473     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
36474     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
36475     LCD_CLEAR                   \ 10- "LCD_Clear"
36476     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
36477     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
36478     CR ." I love you"           \ display message on LCD
36479     ['] CR >BODY IS CR          \ CR executes its default value
36480     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
36481     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
36482     PWR_STATE ABORT             \ init DP and continues with ABORT
36483 ;                               \
36484 \ ------------------------------\
36485
36486 \ ------------------------------\
36487 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
36488 \ ------------------------------\
36489 MOV #SLEEP,X                    \ replace default background process SLEEP
36490 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
36491 MOV #WARM,X                     \ replace default WARM
36492 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
36493 MOV X,PC                        \ then execute new WARM
36494 ENDCODE 
36495 \ ------------------------------\
36496
36497 ECHO
36498             ; downloading RC5toLCD.4th is done
36499 RST_HERE    ; this app is protected against <reset>
36500
36501
36502 RST_STATE
36503
36504 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
36505
36506 [UNDEFINED] MARKER [IF]
36507 \  https://forth-standard.org/standard/core/MARKER
36508 \  MARKER
36509 \ ( "<spaces>name" -- )
36510 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
36511 \ with the execution semantics defined below.
36512
36513 \ name Execution: ( -- )
36514 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
36515 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
36516 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
36517 \ not necessarily provided. No other contextual information such as numeric base is affected
36518 \
36519 : MARKER
36520 CREATE
36521 HI2LO
36522 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
36523 SUB #2,Y            \ 1 Y = LFA
36524 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
36525 ADD #4,&DP          \ 3 add 2 cells
36526 LO2HI
36527 DOES>
36528 HI2LO
36529 MOV @RSP+,IP        \ -- PFA
36530 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
36531 MOV @TOS,&INIDP     \       set DP value for RST_STATE
36532 MOV @PSP+,TOS       \ --
36533 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
36534 ENDCODE
36535 [THEN]
36536
36537 MARKER {RC5TOLCD}
36538
36539 [UNDEFINED] @ [IF]
36540 \ https://forth-standard.org/standard/core/Fetch
36541 \ @     c-addr -- char   fetch char from memory
36542 CODE @
36543 MOV @TOS,TOS
36544 MOV @IP+,PC
36545 ENDCODE
36546 [THEN]
36547
36548 [UNDEFINED] CONSTANT [IF]
36549 \ https://forth-standard.org/standard/core/CONSTANT
36550 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
36551 : CONSTANT 
36552 CREATE
36553 HI2LO
36554 MOV TOS,-2(W)           \   PFA = n
36555 MOV @PSP+,TOS
36556 MOV @RSP+,IP
36557 MOV @IP+,PC
36558 ENDCODE
36559 [THEN]
36560
36561 [UNDEFINED] STATE [IF]
36562 \ https://forth-standard.org/standard/core/STATE
36563 \ STATE   -- a-addr       holds compiler state
36564 STATEADR CONSTANT STATE
36565 [THEN]
36566
36567 [UNDEFINED] = [IF]
36568 \ https://forth-standard.org/standard/core/Equal
36569 \ =      x1 x2 -- flag         test x1=x2
36570 CODE =
36571 SUB @PSP+,TOS   \ 2
36572 0<> IF          \ 2
36573     AND #0,TOS  \ 1
36574     MOV @IP+,PC \ 4
36575 THEN
36576 XOR #-1,TOS     \ 1 flag Z = 1
36577 MOV @IP+,PC     \ 4
36578 ENDCODE
36579 [THEN]
36580
36581 [UNDEFINED] IF [IF]
36582 \ https://forth-standard.org/standard/core/IF
36583 \ IF       -- IFadr    initialize conditional forward branch
36584 CODE IF       \ immediate
36585 SUB #2,PSP              \
36586 MOV TOS,0(PSP)          \
36587 MOV &DP,TOS             \ -- HERE
36588 ADD #4,&DP            \           compile one word, reserve one word
36589 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
36590 ADD #2,TOS              \ -- HERE+2=IFadr
36591 MOV @IP+,PC
36592 ENDCODE IMMEDIATE
36593 [THEN]
36594
36595 [UNDEFINED] THEN [IF]
36596 \ https://forth-standard.org/standard/core/THEN
36597 \ THEN     IFadr --                resolve forward branch
36598 CODE THEN               \ immediate
36599 MOV &DP,0(TOS)          \ -- IFadr
36600 MOV @PSP+,TOS           \ --
36601 MOV @IP+,PC
36602 ENDCODE IMMEDIATE
36603 [THEN]
36604
36605 [UNDEFINED] ELSE [IF]
36606 \ https://forth-standard.org/standard/core/ELSE
36607 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
36608 CODE ELSE     \ immediate
36609 ADD #4,&DP              \ make room to compile two words
36610 MOV &DP,W               \ W=HERE+4
36611 MOV #BRAN,-4(W)
36612 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
36613 SUB #2,W                \ HERE+2
36614 MOV W,TOS               \ -- ELSEadr
36615 MOV @IP+,PC
36616 ENDCODE IMMEDIATE
36617 [THEN]
36618
36619 [UNDEFINED] DEFER [IF]
36620 \ https://forth-standard.org/standard/core/DEFER
36621 \ DEFER "<spaces>name"   --
36622 \ Skip leading space delimiters. Parse name delimited by a space.
36623 \ Create a definition for name with the execution semantics defined below.
36624
36625 \ name Execution:   --
36626 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
36627 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
36628 : DEFER
36629 CREATE
36630 HI2LO
36631 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
36632 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
36633 MOV @RSP+,IP
36634 MOV @IP+,PC
36635 ENDCODE
36636 [THEN]
36637
36638 [UNDEFINED] DEFER! [IF]
36639 \ https://forth-standard.org/standard/core/DEFERStore
36640 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
36641 CODE DEFER!             \ xt2 xt1 --
36642 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
36643 MOV @PSP+,TOS           \ --
36644 MOV @IP+,PC
36645 ENDCODE
36646 [THEN]
36647
36648 [UNDEFINED] IS [IF]
36649 \ https://forth-standard.org/standard/core/IS
36650 \ IS <name>        xt --
36651 \ used as is :
36652 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
36653 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
36654 \ or in a definition : ... ['] U. IS DISPLAY ...
36655 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
36656 \
36657 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
36658 : IS
36659 STATE @
36660 IF  POSTPONE ['] POSTPONE DEFER! 
36661 ELSE ' DEFER! 
36662 THEN
36663 ; IMMEDIATE
36664 [THEN]
36665
36666 [UNDEFINED] >BODY [IF]
36667 \ https://forth-standard.org/standard/core/toBODY
36668 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
36669 CODE >BODY
36670 ADD #4,TOS
36671 MOV @IP+,PC
36672 ENDCODE
36673 [THEN]
36674
36675 \ CODE 20uS           \ n --      8MHz version
36676 \ BEGIN               \ 4 + 16 ~ loop
36677 \     MOV #39,rDOCON   \ 39
36678 \     BEGIN           \ 4 ~ loop
36679 \         NOP
36680 \         SUB #1,rDOCON
36681 \     0=  UNTIL
36682 \     SUB #1,TOS      \ 1
36683 \ 0= UNTIL
36684 \ MOV #XDOCON,rDOCON  \ 2
36685 \ MOV @PSP+,TOS
36686 \ MOV @RSP+,IP        \
36687 \ ENDCODE
36688
36689 CODE 20_US                      \ n --      n * 20 us
36690 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
36691     BEGIN
36692         BIT #1,&LCD_TIM_CTL     \ 3
36693     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
36694     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
36695     SUB #1,TOS                  \ 1
36696 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
36697 MOV @PSP+,TOS                   \ 2
36698 MOV @IP+,PC                     \ 4
36699 ENDCODE
36700
36701 CODE TOP_LCD                    \ LCD Sample
36702 \                               \ if write : %xxxx_WWWW --
36703 \                               \ if read  : -- %0000_RRRR
36704     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
36705     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
36706 0= IF                           \ write LCD bits pattern
36707     AND.B #LCD_DB,TOS           \ 
36708     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
36709     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
36710     MOV @PSP+,TOS               \
36711     MOV @IP+,PC
36712 THEN                            \ read LCD bits pattern
36713     SUB #2,PSP
36714     MOV TOS,0(PSP)
36715     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
36716     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
36717     AND.B #LCD_DB,TOS           \
36718     MOV @IP+,PC
36719 ENDCODE
36720
36721 CODE LCD_WRC                    \ char --         Write Char
36722     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
36723 BW1 SUB #2,PSP                  \
36724     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
36725     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
36726     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
36727     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
36728 COLON                           \ high level word starts here 
36729     TOP_LCD 2 20_US             \ write high nibble first
36730     TOP_LCD 2 20_US 
36731 ;
36732
36733 CODE LCD_WRF                    \ func --         Write Fonction
36734     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
36735     GOTO BW1
36736 ENDCODE
36737
36738 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
36739 : LCD_HOME $02 LCD_WRF 100 20_us ;
36740
36741 \ [UNDEFINED] OR [IF]
36742
36743 \ \ https://forth-standard.org/standard/core/OR
36744 \ \ C OR     x1 x2 -- x3           logical OR
36745 \ CODE OR
36746 \ BIS @PSP+,TOS
36747 \ MOV @IP+,PC
36748 \ ENDCODE
36749
36750 \ [THEN]
36751
36752 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
36753 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
36754 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
36755 \ : LCD_FN_SET        $20 OR LCD_WrF ;
36756 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
36757 \ : LCD_GOTO          $80 OR LCD_WrF ;
36758
36759
36760 \ CODE LCD_RDS                    \ -- status       Read Status
36761 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
36762 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
36763 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
36764 \ COLON                           \ starts a FORTH word
36765 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
36766 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
36767 \ HI2LO                           \ switch from FORTH to assembler
36768 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
36769 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
36770 \     MOV @RSP+,IP                \ restore IP saved by COLON
36771 \     MOV @IP+,PC                 \
36772 \ ENDCODE
36773
36774 \ CODE LCD_RDC                    \ -- char         Read Char
36775 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
36776 \     GOTO BW1
36777 \ ENDCODE
36778
36779
36780 \ ******************************\
36781 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
36782 \ ******************************\
36783 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
36784 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
36785 BIT.B #SW2,&SW2_IN              \ test switch S2
36786 0= IF                           \ case of switch S2 pressed
36787     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
36788     U< IF
36789         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
36790     THEN
36791 ELSE
36792     BIT.B #SW1,&SW1_IN          \ test switch S1 input
36793     0= IF                       \ case of Switch S1 pressed
36794         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
36795         U>= IF                  \
36796            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
36797         THEN                    \
36798     THEN                        \
36799 THEN                            \
36800 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
36801 RET                             \ 5
36802 ENDASM
36803
36804 \ ******************************\
36805 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
36806 \ ******************************\
36807 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
36808 \ ******************************\
36809 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
36810 \                               \       SMclock = 8|16|24 MHz
36811 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
36812 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
36813 \                               \       SR(9)=new Toggle bit memory (ADD on)
36814 \ ******************************\
36815 \ RC5_FirstStartBitHalfCycle:   \
36816 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
36817 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
36818 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
36819 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
36820 \ [THEN]
36821 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
36822     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
36823 [THEN]
36824 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
36825     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
36826 [THEN]
36827 MOV #1778,X                     \ RC5_Period * 1us
36828 MOV #14,W                       \ count of loop
36829 BEGIN                           \
36830 \ ******************************\
36831 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
36832 \ ******************************\                   |
36833 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
36834 \ RC5_Compute_3/4_Period:       \                   |
36835     RRUM    #1,X                \ X=1/2 cycle       |
36836     MOV     X,Y                 \                   ^
36837     RRUM    #1,Y                \ Y=1/4
36838     ADD     X,Y                 \ Y=3/4 cycle
36839     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
36840     U>= UNTIL                   \ 2
36841 \ ******************************\
36842 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
36843 \ ******************************\
36844     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
36845     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
36846     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
36847     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
36848     SUB     #1,W                \ decrement count loop
36849 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
36850 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
36851 0<> WHILE                       \ ----> out of loop ----+
36852     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
36853     BEGIN                       \                       |
36854         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
36855         CMP Y,X                 \ 1                     |   cycle time out of bound ?
36856         U>= IF                  \ 2                 ^   |   yes:
36857         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
36858         GOTO BW1                \                   |   |      quit on truncated RC5 message
36859         THEN                    \                   |   |
36860         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
36861     0<> UNTIL                   \ 2                 |   |
36862 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
36863 \ ******************************\                       |
36864 \ RC5_SampleEndOf:              \ <---------------------+
36865 \ ******************************\
36866 BIC #$30,&RC5_TIM_CTL           \   stop timer
36867 \ ******************************\
36868 \ RC5_ComputeNewRC5word         \
36869 \ ******************************\
36870 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
36871 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
36872 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
36873 \ ******************************\
36874 \ RC5_ComputeC6bit              \
36875 \ ******************************\
36876 BIT     #BIT14,T                \ test /C6 bit in T
36877 0= IF   BIS #BIT6,X             \ set C6 bit in X
36878 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
36879 \ ******************************\
36880 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
36881 \ ******************************\
36882 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
36883 \ ******************************\
36884 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
36885 XOR     @RSP,T                  \ (new XOR old) Toggle bits
36886 BIT     #UF10,T                 \ repeated RC5_command ?
36887 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
36888 XOR #UF10,0(RSP)                \ 5 toggle bit memory
36889 \ ******************************\
36890 \ Display IR_RC5 code           \
36891 \ ******************************\
36892 SUB #8,PSP                      \ TOS -- x x x x TOS
36893 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
36894 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
36895 MOV #$10,&BASEADR               \                                               set hexadecimal base
36896 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
36897 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
36898 LO2HI                           \                                               switch from assembler to FORTH
36899     LCD_CLEAR                   \                                               set LCD cursor at home
36900     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
36901     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
36902     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
36903     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
36904 HI2LO                           \     --                                        switch from FORTH to assembler
36905 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
36906 MOV @PSP+,TOS                   \     -- TOS
36907 RET
36908 ENDASM
36909
36910 \ ******************************\
36911 ASM BACKGROUND                  \
36912 \ ******************************\
36913 BEGIN
36914 \     ...                         \ insert here your background task
36915 \     ...                         \
36916 \     ...                         \
36917     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
36918     BIS &LPM_MODE,SR            \
36919 \ ******************************\
36920 \ here start all interrupts     \
36921 \ ******************************\
36922 \ here return all interrupts    \
36923 \ ******************************\
36924 AGAIN                           \
36925 ENDASM                          \
36926 \ ******************************\
36927
36928 \ ------------------------------\
36929 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
36930 \ ------------------------------\
36931 \     ...                         \ init specific I/O sys as you want
36932 \     ...                         \ before executing default WARM
36933     MOV #WARM,X                 \ ['] WARM 
36934     ADD #4,X                    \ >BODY
36935     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
36936 ENDASM
36937 \ ------------------------------\
36938
36939 \ ------------------------------\
36940 CODE STOP                       \ stops multitasking, must to be used before downloading app
36941 \ ------------------------------\
36942 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
36943     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
36944     MOV X,-2(X)                 \ restore the default background: SLEEP
36945     MOV #WARM,X
36946     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
36947     BIC.B #RC5,&IR_IE           \ clear RC5_Int
36948     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
36949     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
36950     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
36951     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
36952     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
36953 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
36954 ECHO                            \
36955 ." RC5toLCD is removed,"
36956 ."  type START to restart"
36957  WARM                           \ performs reset to reset all interrupt vectors.    
36958 ;
36959 \ ------------------------------\
36960
36961 \ ------------------------------\
36962 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
36963 \ ------------------------------\
36964 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
36965 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
36966 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
36967 \                           --       \ID input divider \ 10 = /4
36968 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
36969 \                                 -  \TBCLR TimerB Clear
36970 \                                  - \TBIE
36971 \                                   -\TBIFG
36972 \ -------------------------------\
36973 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
36974 \                  --                 \CM Capture Mode
36975 \                    --               \CCIS
36976 \                       -             \SCS
36977 \                        --           \CLLD
36978 \                          -          \CAP
36979 \                            ---      \OUTMOD \ 011 = set/reset
36980 \                               -     \CCIE
36981 \                                 -   \CCI
36982 \                                  -  \OUT
36983 \                                   - \COV
36984 \                                    -\CCIFG
36985 \ -------------------------------\
36986 \ LCD_TIM_CCRx                   \
36987 \ -------------------------------\
36988 \ LCD_TIM_EX0                    \ 
36989 \ ------------------------------\
36990 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
36991 \ ------------------------------\
36992 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
36993 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
36994 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
36995     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
36996 [THEN]
36997 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
36998     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
36999 [THEN]
37000     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
37001 \ ------------------------------\
37002 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
37003 \ ------------------------------\
37004 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
37005     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
37006 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
37007 \ ------------------------------\
37008     BIS.B #LCDVo,&LCDVo_DIR     \
37009     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
37010 \ ------------------------------\
37011     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
37012     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
37013 \ ------------------------------\
37014     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
37015     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
37016 \ ******************************\
37017 \ init RC5_Int                  \
37018 \ ******************************\
37019     BIS.B #RC5,&IR_IE           \ enable RC5_Int
37020     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
37021     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
37022 \ ******************************\
37023 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
37024 \ ******************************\
37025 \              %01 0001 0100    \ TAxCTL
37026 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
37027 \                  --           \ ID        divided by 1
37028 \                    --         \ MC        MODE = up to TAxCCRn
37029 \                        -      \ TACLR     clear timer count
37030 \                         -     \ TAIE
37031 \                          -    \ TAIFG
37032 \ ------------------------------\
37033 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
37034 \ ------------------------------\
37035 \                        000    \ TAxEX0
37036 \                        ---    \ TAIDEX    pre divisor
37037 \ ------------------------------\
37038 \          %0000 0000 0000 0101 \ TAxCCR0
37039     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
37040 \ ------------------------------\
37041 \          %0000 0000 0001 0000 \ TAxCCTL0
37042 \                   -           \ CAP capture/compare mode = compare
37043 \                        -      \ CCIEn
37044 \                             - \ CCIFGn
37045     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
37046 \ ------------------------------\
37047     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
37048 \ ------------------------------\
37049 \ define LPM mode for ACCEPT    \
37050 \ ------------------------------\
37051 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
37052 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
37053 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
37054 \ ------------------------------\
37055 \ activate I/O                  \
37056 \ ------------------------------\
37057 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
37058 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
37059 \ ------------------------------\
37060 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
37061 \ ------------------------------\
37062 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
37063 \ CMP #2,Y                        \ Power_ON event
37064 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
37065 CMP #4,Y                        \
37066 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
37067 \ CMP #6,Y                        \
37068 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
37069 \ CMP #$0A,Y                      \
37070 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
37071 \ CMP #$16,Y                      \
37072 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
37073 \ ------------------------------\
37074 COLON                           \
37075 \ ------------------------------\
37076 \ Init LCD 2x20                 \
37077 \ ------------------------------\
37078     #1000 20_US                 \ 1- wait 20 ms
37079     %011 TOP_LCD                \ 2- send DB5=DB4=1
37080     #205 20_US                  \ 3- wait 4,1 ms
37081     %011 TOP_LCD                \ 4- send again DB5=DB4=1
37082     #5 20_US                    \ 5- wait 0,1 ms
37083     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
37084     #2 20_US                    \    wait 40 us = LCD cycle
37085     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
37086     #2 20_US                    \    wait 40 us = LCD cycle
37087     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
37088     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
37089     LCD_CLEAR                   \ 10- "LCD_Clear"
37090     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
37091     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
37092     LCD_CLEAR                   \ 10- "LCD_Clear"
37093     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
37094     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
37095     CR ." I love you"           \ display message on LCD
37096     ['] CR >BODY IS CR          \ CR executes its default value
37097     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
37098     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
37099     PWR_STATE ABORT             \ init DP and continues with ABORT
37100 ;                               \
37101 \ ------------------------------\
37102
37103 \ ------------------------------\
37104 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
37105 \ ------------------------------\
37106 MOV #SLEEP,X                    \ replace default background process SLEEP
37107 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
37108 MOV #WARM,X                     \ replace default WARM
37109 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
37110 MOV X,PC                        \ then execute new WARM
37111 ENDCODE 
37112 \ ------------------------------\
37113
37114 ECHO
37115             ; downloading RC5toLCD.4th is done
37116 RST_HERE    ; this app is protected against <reset>
37117
37118
37119 RST_STATE
37120
37121 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
37122
37123 [UNDEFINED] MARKER [IF]
37124 \  https://forth-standard.org/standard/core/MARKER
37125 \  MARKER
37126 \ ( "<spaces>name" -- )
37127 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
37128 \ with the execution semantics defined below.
37129
37130 \ name Execution: ( -- )
37131 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
37132 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
37133 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
37134 \ not necessarily provided. No other contextual information such as numeric base is affected
37135 \
37136 : MARKER
37137 CREATE
37138 HI2LO
37139 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
37140 SUB #2,Y            \ 1 Y = LFA
37141 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
37142 ADD #4,&DP          \ 3 add 2 cells
37143 LO2HI
37144 DOES>
37145 HI2LO
37146 MOV @RSP+,IP        \ -- PFA
37147 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
37148 MOV @TOS,&INIDP     \       set DP value for RST_STATE
37149 MOV @PSP+,TOS       \ --
37150 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
37151 ENDCODE
37152 [THEN]
37153
37154 MARKER {RC5TOLCD}
37155
37156 [UNDEFINED] @ [IF]
37157 \ https://forth-standard.org/standard/core/Fetch
37158 \ @     c-addr -- char   fetch char from memory
37159 CODE @
37160 MOV @TOS,TOS
37161 MOV @IP+,PC
37162 ENDCODE
37163 [THEN]
37164
37165 [UNDEFINED] CONSTANT [IF]
37166 \ https://forth-standard.org/standard/core/CONSTANT
37167 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
37168 : CONSTANT 
37169 CREATE
37170 HI2LO
37171 MOV TOS,-2(W)           \   PFA = n
37172 MOV @PSP+,TOS
37173 MOV @RSP+,IP
37174 MOV @IP+,PC
37175 ENDCODE
37176 [THEN]
37177
37178 [UNDEFINED] STATE [IF]
37179 \ https://forth-standard.org/standard/core/STATE
37180 \ STATE   -- a-addr       holds compiler state
37181 STATEADR CONSTANT STATE
37182 [THEN]
37183
37184 [UNDEFINED] = [IF]
37185 \ https://forth-standard.org/standard/core/Equal
37186 \ =      x1 x2 -- flag         test x1=x2
37187 CODE =
37188 SUB @PSP+,TOS   \ 2
37189 0<> IF          \ 2
37190     AND #0,TOS  \ 1
37191     MOV @IP+,PC \ 4
37192 THEN
37193 XOR #-1,TOS     \ 1 flag Z = 1
37194 MOV @IP+,PC     \ 4
37195 ENDCODE
37196 [THEN]
37197
37198 [UNDEFINED] IF [IF]
37199 \ https://forth-standard.org/standard/core/IF
37200 \ IF       -- IFadr    initialize conditional forward branch
37201 CODE IF       \ immediate
37202 SUB #2,PSP              \
37203 MOV TOS,0(PSP)          \
37204 MOV &DP,TOS             \ -- HERE
37205 ADD #4,&DP            \           compile one word, reserve one word
37206 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
37207 ADD #2,TOS              \ -- HERE+2=IFadr
37208 MOV @IP+,PC
37209 ENDCODE IMMEDIATE
37210 [THEN]
37211
37212 [UNDEFINED] THEN [IF]
37213 \ https://forth-standard.org/standard/core/THEN
37214 \ THEN     IFadr --                resolve forward branch
37215 CODE THEN               \ immediate
37216 MOV &DP,0(TOS)          \ -- IFadr
37217 MOV @PSP+,TOS           \ --
37218 MOV @IP+,PC
37219 ENDCODE IMMEDIATE
37220 [THEN]
37221
37222 [UNDEFINED] ELSE [IF]
37223 \ https://forth-standard.org/standard/core/ELSE
37224 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
37225 CODE ELSE     \ immediate
37226 ADD #4,&DP              \ make room to compile two words
37227 MOV &DP,W               \ W=HERE+4
37228 MOV #BRAN,-4(W)
37229 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
37230 SUB #2,W                \ HERE+2
37231 MOV W,TOS               \ -- ELSEadr
37232 MOV @IP+,PC
37233 ENDCODE IMMEDIATE
37234 [THEN]
37235
37236 [UNDEFINED] DEFER [IF]
37237 \ https://forth-standard.org/standard/core/DEFER
37238 \ DEFER "<spaces>name"   --
37239 \ Skip leading space delimiters. Parse name delimited by a space.
37240 \ Create a definition for name with the execution semantics defined below.
37241
37242 \ name Execution:   --
37243 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
37244 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
37245 : DEFER
37246 CREATE
37247 HI2LO
37248 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
37249 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
37250 MOV @RSP+,IP
37251 MOV @IP+,PC
37252 ENDCODE
37253 [THEN]
37254
37255 [UNDEFINED] DEFER! [IF]
37256 \ https://forth-standard.org/standard/core/DEFERStore
37257 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
37258 CODE DEFER!             \ xt2 xt1 --
37259 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
37260 MOV @PSP+,TOS           \ --
37261 MOV @IP+,PC
37262 ENDCODE
37263 [THEN]
37264
37265 [UNDEFINED] IS [IF]
37266 \ https://forth-standard.org/standard/core/IS
37267 \ IS <name>        xt --
37268 \ used as is :
37269 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
37270 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
37271 \ or in a definition : ... ['] U. IS DISPLAY ...
37272 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
37273 \
37274 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
37275 : IS
37276 STATE @
37277 IF  POSTPONE ['] POSTPONE DEFER! 
37278 ELSE ' DEFER! 
37279 THEN
37280 ; IMMEDIATE
37281 [THEN]
37282
37283 [UNDEFINED] >BODY [IF]
37284 \ https://forth-standard.org/standard/core/toBODY
37285 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
37286 CODE >BODY
37287 ADD #4,TOS
37288 MOV @IP+,PC
37289 ENDCODE
37290 [THEN]
37291
37292 \ CODE 20uS           \ n --      8MHz version
37293 \ BEGIN               \ 4 + 16 ~ loop
37294 \     MOV #39,rDOCON   \ 39
37295 \     BEGIN           \ 4 ~ loop
37296 \         NOP
37297 \         SUB #1,rDOCON
37298 \     0=  UNTIL
37299 \     SUB #1,TOS      \ 1
37300 \ 0= UNTIL
37301 \ MOV #XDOCON,rDOCON  \ 2
37302 \ MOV @PSP+,TOS
37303 \ MOV @RSP+,IP        \
37304 \ ENDCODE
37305
37306 CODE 20_US                      \ n --      n * 20 us
37307 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
37308     BEGIN
37309         BIT #1,&LCD_TIM_CTL     \ 3
37310     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
37311     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
37312     SUB #1,TOS                  \ 1
37313 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
37314 MOV @PSP+,TOS                   \ 2
37315 MOV @IP+,PC                     \ 4
37316 ENDCODE
37317
37318 CODE TOP_LCD                    \ LCD Sample
37319 \                               \ if write : %xxxx_WWWW --
37320 \                               \ if read  : -- %0000_RRRR
37321     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
37322     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
37323 0= IF                           \ write LCD bits pattern
37324     AND.B #LCD_DB,TOS           \ 
37325     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
37326     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
37327     MOV @PSP+,TOS               \
37328     MOV @IP+,PC
37329 THEN                            \ read LCD bits pattern
37330     SUB #2,PSP
37331     MOV TOS,0(PSP)
37332     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
37333     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
37334     AND.B #LCD_DB,TOS           \
37335     MOV @IP+,PC
37336 ENDCODE
37337
37338 CODE LCD_WRC                    \ char --         Write Char
37339     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
37340 BW1 SUB #2,PSP                  \
37341     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
37342     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
37343     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
37344     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
37345 COLON                           \ high level word starts here 
37346     TOP_LCD 2 20_US             \ write high nibble first
37347     TOP_LCD 2 20_US 
37348 ;
37349
37350 CODE LCD_WRF                    \ func --         Write Fonction
37351     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
37352     GOTO BW1
37353 ENDCODE
37354
37355 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
37356 : LCD_HOME $02 LCD_WRF 100 20_us ;
37357
37358 \ [UNDEFINED] OR [IF]
37359
37360 \ \ https://forth-standard.org/standard/core/OR
37361 \ \ C OR     x1 x2 -- x3           logical OR
37362 \ CODE OR
37363 \ BIS @PSP+,TOS
37364 \ MOV @IP+,PC
37365 \ ENDCODE
37366
37367 \ [THEN]
37368
37369 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
37370 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
37371 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
37372 \ : LCD_FN_SET        $20 OR LCD_WrF ;
37373 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
37374 \ : LCD_GOTO          $80 OR LCD_WrF ;
37375
37376
37377 \ CODE LCD_RDS                    \ -- status       Read Status
37378 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
37379 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
37380 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
37381 \ COLON                           \ starts a FORTH word
37382 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
37383 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
37384 \ HI2LO                           \ switch from FORTH to assembler
37385 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
37386 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
37387 \     MOV @RSP+,IP                \ restore IP saved by COLON
37388 \     MOV @IP+,PC                 \
37389 \ ENDCODE
37390
37391 \ CODE LCD_RDC                    \ -- char         Read Char
37392 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
37393 \     GOTO BW1
37394 \ ENDCODE
37395
37396
37397 \ ******************************\
37398 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
37399 \ ******************************\
37400 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
37401 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
37402 BIT.B #SW2,&SW2_IN              \ test switch S2
37403 0= IF                           \ case of switch S2 pressed
37404     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
37405     U< IF
37406         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
37407     THEN
37408 ELSE
37409     BIT.B #SW1,&SW1_IN          \ test switch S1 input
37410     0= IF                       \ case of Switch S1 pressed
37411         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
37412         U>= IF                  \
37413            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
37414         THEN                    \
37415     THEN                        \
37416 THEN                            \
37417 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
37418 RET                             \ 5
37419 ENDASM
37420
37421 \ ******************************\
37422 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
37423 \ ******************************\
37424 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
37425 \ ******************************\
37426 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
37427 \                               \       SMclock = 8|16|24 MHz
37428 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
37429 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
37430 \                               \       SR(9)=new Toggle bit memory (ADD on)
37431 \ ******************************\
37432 \ RC5_FirstStartBitHalfCycle:   \
37433 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
37434 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
37435 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
37436 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
37437 \ [THEN]
37438 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
37439     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
37440 [THEN]
37441 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
37442     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
37443 [THEN]
37444 MOV #1778,X                     \ RC5_Period * 1us
37445 MOV #14,W                       \ count of loop
37446 BEGIN                           \
37447 \ ******************************\
37448 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
37449 \ ******************************\                   |
37450 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
37451 \ RC5_Compute_3/4_Period:       \                   |
37452     RRUM    #1,X                \ X=1/2 cycle       |
37453     MOV     X,Y                 \                   ^
37454     RRUM    #1,Y                \ Y=1/4
37455     ADD     X,Y                 \ Y=3/4 cycle
37456     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
37457     U>= UNTIL                   \ 2
37458 \ ******************************\
37459 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
37460 \ ******************************\
37461     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
37462     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
37463     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
37464     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
37465     SUB     #1,W                \ decrement count loop
37466 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
37467 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
37468 0<> WHILE                       \ ----> out of loop ----+
37469     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
37470     BEGIN                       \                       |
37471         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
37472         CMP Y,X                 \ 1                     |   cycle time out of bound ?
37473         U>= IF                  \ 2                 ^   |   yes:
37474         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
37475         GOTO BW1                \                   |   |      quit on truncated RC5 message
37476         THEN                    \                   |   |
37477         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
37478     0<> UNTIL                   \ 2                 |   |
37479 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
37480 \ ******************************\                       |
37481 \ RC5_SampleEndOf:              \ <---------------------+
37482 \ ******************************\
37483 BIC #$30,&RC5_TIM_CTL           \   stop timer
37484 \ ******************************\
37485 \ RC5_ComputeNewRC5word         \
37486 \ ******************************\
37487 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
37488 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
37489 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
37490 \ ******************************\
37491 \ RC5_ComputeC6bit              \
37492 \ ******************************\
37493 BIT     #BIT14,T                \ test /C6 bit in T
37494 0= IF   BIS #BIT6,X             \ set C6 bit in X
37495 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
37496 \ ******************************\
37497 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
37498 \ ******************************\
37499 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
37500 \ ******************************\
37501 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
37502 XOR     @RSP,T                  \ (new XOR old) Toggle bits
37503 BIT     #UF10,T                 \ repeated RC5_command ?
37504 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
37505 XOR #UF10,0(RSP)                \ 5 toggle bit memory
37506 \ ******************************\
37507 \ Display IR_RC5 code           \
37508 \ ******************************\
37509 SUB #8,PSP                      \ TOS -- x x x x TOS
37510 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
37511 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
37512 MOV #$10,&BASEADR               \                                               set hexadecimal base
37513 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
37514 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
37515 LO2HI                           \                                               switch from assembler to FORTH
37516     LCD_CLEAR                   \                                               set LCD cursor at home
37517     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
37518     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
37519     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
37520     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
37521 HI2LO                           \     --                                        switch from FORTH to assembler
37522 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
37523 MOV @PSP+,TOS                   \     -- TOS
37524 RET
37525 ENDASM
37526
37527 \ ******************************\
37528 ASM BACKGROUND                  \
37529 \ ******************************\
37530 BEGIN
37531 \     ...                         \ insert here your background task
37532 \     ...                         \
37533 \     ...                         \
37534     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
37535     BIS &LPM_MODE,SR            \
37536 \ ******************************\
37537 \ here start all interrupts     \
37538 \ ******************************\
37539 \ here return all interrupts    \
37540 \ ******************************\
37541 AGAIN                           \
37542 ENDASM                          \
37543 \ ******************************\
37544
37545 \ ------------------------------\
37546 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
37547 \ ------------------------------\
37548 \     ...                         \ init specific I/O sys as you want
37549 \     ...                         \ before executing default WARM
37550     MOV #WARM,X                 \ ['] WARM 
37551     ADD #4,X                    \ >BODY
37552     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
37553 ENDASM
37554 \ ------------------------------\
37555
37556 \ ------------------------------\
37557 CODE STOP                       \ stops multitasking, must to be used before downloading app
37558 \ ------------------------------\
37559 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
37560     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
37561     MOV X,-2(X)                 \ restore the default background: SLEEP
37562     MOV #WARM,X
37563     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
37564     BIC.B #RC5,&IR_IE           \ clear RC5_Int
37565     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
37566     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
37567     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
37568     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
37569     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
37570 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
37571 ECHO                            \
37572 ." RC5toLCD is removed,"
37573 ."  type START to restart"
37574  WARM                           \ performs reset to reset all interrupt vectors.    
37575 ;
37576 \ ------------------------------\
37577
37578 \ ------------------------------\
37579 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
37580 \ ------------------------------\
37581 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
37582 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
37583 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
37584 \                           --       \ID input divider \ 10 = /4
37585 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
37586 \                                 -  \TBCLR TimerB Clear
37587 \                                  - \TBIE
37588 \                                   -\TBIFG
37589 \ -------------------------------\
37590 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
37591 \                  --                 \CM Capture Mode
37592 \                    --               \CCIS
37593 \                       -             \SCS
37594 \                        --           \CLLD
37595 \                          -          \CAP
37596 \                            ---      \OUTMOD \ 011 = set/reset
37597 \                               -     \CCIE
37598 \                                 -   \CCI
37599 \                                  -  \OUT
37600 \                                   - \COV
37601 \                                    -\CCIFG
37602 \ -------------------------------\
37603 \ LCD_TIM_CCRx                   \
37604 \ -------------------------------\
37605 \ LCD_TIM_EX0                    \ 
37606 \ ------------------------------\
37607 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
37608 \ ------------------------------\
37609 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
37610 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
37611 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
37612     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
37613 [THEN]
37614 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
37615     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
37616 [THEN]
37617     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
37618 \ ------------------------------\
37619 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
37620 \ ------------------------------\
37621 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
37622     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
37623 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
37624 \ ------------------------------\
37625     BIS.B #LCDVo,&LCDVo_DIR     \
37626     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
37627 \ ------------------------------\
37628     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
37629     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
37630 \ ------------------------------\
37631     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
37632     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
37633 \ ******************************\
37634 \ init RC5_Int                  \
37635 \ ******************************\
37636     BIS.B #RC5,&IR_IE           \ enable RC5_Int
37637     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
37638     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
37639 \ ******************************\
37640 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
37641 \ ******************************\
37642 \              %01 0001 0100    \ TAxCTL
37643 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
37644 \                  --           \ ID        divided by 1
37645 \                    --         \ MC        MODE = up to TAxCCRn
37646 \                        -      \ TACLR     clear timer count
37647 \                         -     \ TAIE
37648 \                          -    \ TAIFG
37649 \ ------------------------------\
37650 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
37651 \ ------------------------------\
37652 \                        000    \ TAxEX0
37653 \                        ---    \ TAIDEX    pre divisor
37654 \ ------------------------------\
37655 \          %0000 0000 0000 0101 \ TAxCCR0
37656     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
37657 \ ------------------------------\
37658 \          %0000 0000 0001 0000 \ TAxCCTL0
37659 \                   -           \ CAP capture/compare mode = compare
37660 \                        -      \ CCIEn
37661 \                             - \ CCIFGn
37662     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
37663 \ ------------------------------\
37664     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
37665 \ ------------------------------\
37666 \ define LPM mode for ACCEPT    \
37667 \ ------------------------------\
37668 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
37669 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
37670 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
37671 \ ------------------------------\
37672 \ activate I/O                  \
37673 \ ------------------------------\
37674 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
37675 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
37676 \ ------------------------------\
37677 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
37678 \ ------------------------------\
37679 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
37680 \ CMP #2,Y                        \ Power_ON event
37681 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
37682 CMP #4,Y                        \
37683 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
37684 \ CMP #6,Y                        \
37685 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
37686 \ CMP #$0A,Y                      \
37687 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
37688 \ CMP #$16,Y                      \
37689 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
37690 \ ------------------------------\
37691 COLON                           \
37692 \ ------------------------------\
37693 \ Init LCD 2x20                 \
37694 \ ------------------------------\
37695     #1000 20_US                 \ 1- wait 20 ms
37696     %011 TOP_LCD                \ 2- send DB5=DB4=1
37697     #205 20_US                  \ 3- wait 4,1 ms
37698     %011 TOP_LCD                \ 4- send again DB5=DB4=1
37699     #5 20_US                    \ 5- wait 0,1 ms
37700     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
37701     #2 20_US                    \    wait 40 us = LCD cycle
37702     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
37703     #2 20_US                    \    wait 40 us = LCD cycle
37704     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
37705     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
37706     LCD_CLEAR                   \ 10- "LCD_Clear"
37707     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
37708     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
37709     LCD_CLEAR                   \ 10- "LCD_Clear"
37710     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
37711     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
37712     CR ." I love you"           \ display message on LCD
37713     ['] CR >BODY IS CR          \ CR executes its default value
37714     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
37715     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
37716     PWR_STATE ABORT             \ init DP and continues with ABORT
37717 ;                               \
37718 \ ------------------------------\
37719
37720 \ ------------------------------\
37721 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
37722 \ ------------------------------\
37723 MOV #SLEEP,X                    \ replace default background process SLEEP
37724 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
37725 MOV #WARM,X                     \ replace default WARM
37726 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
37727 MOV X,PC                        \ then execute new WARM
37728 ENDCODE 
37729 \ ------------------------------\
37730
37731 ECHO
37732             ; downloading RC5toLCD.4th is done
37733 RST_HERE    ; this app is protected against <reset>
37734
37735
37736 RST_STATE
37737
37738 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
37739
37740 [UNDEFINED] MARKER [IF]
37741 \  https://forth-standard.org/standard/core/MARKER
37742 \  MARKER
37743 \ ( "<spaces>name" -- )
37744 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
37745 \ with the execution semantics defined below.
37746
37747 \ name Execution: ( -- )
37748 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
37749 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
37750 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
37751 \ not necessarily provided. No other contextual information such as numeric base is affected
37752 \
37753 : MARKER
37754 CREATE
37755 HI2LO
37756 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
37757 SUB #2,Y            \ 1 Y = LFA
37758 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
37759 ADD #4,&DP          \ 3 add 2 cells
37760 LO2HI
37761 DOES>
37762 HI2LO
37763 MOV @RSP+,IP        \ -- PFA
37764 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
37765 MOV @TOS,&INIDP     \       set DP value for RST_STATE
37766 MOV @PSP+,TOS       \ --
37767 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
37768 ENDCODE
37769 [THEN]
37770
37771 MARKER {RC5TOLCD}
37772
37773 [UNDEFINED] @ [IF]
37774 \ https://forth-standard.org/standard/core/Fetch
37775 \ @     c-addr -- char   fetch char from memory
37776 CODE @
37777 MOV @TOS,TOS
37778 MOV @IP+,PC
37779 ENDCODE
37780 [THEN]
37781
37782 [UNDEFINED] CONSTANT [IF]
37783 \ https://forth-standard.org/standard/core/CONSTANT
37784 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
37785 : CONSTANT 
37786 CREATE
37787 HI2LO
37788 MOV TOS,-2(W)           \   PFA = n
37789 MOV @PSP+,TOS
37790 MOV @RSP+,IP
37791 MOV @IP+,PC
37792 ENDCODE
37793 [THEN]
37794
37795 [UNDEFINED] STATE [IF]
37796 \ https://forth-standard.org/standard/core/STATE
37797 \ STATE   -- a-addr       holds compiler state
37798 STATEADR CONSTANT STATE
37799 [THEN]
37800
37801 [UNDEFINED] = [IF]
37802 \ https://forth-standard.org/standard/core/Equal
37803 \ =      x1 x2 -- flag         test x1=x2
37804 CODE =
37805 SUB @PSP+,TOS   \ 2
37806 0<> IF          \ 2
37807     AND #0,TOS  \ 1
37808     MOV @IP+,PC \ 4
37809 THEN
37810 XOR #-1,TOS     \ 1 flag Z = 1
37811 MOV @IP+,PC     \ 4
37812 ENDCODE
37813 [THEN]
37814
37815 [UNDEFINED] IF [IF]
37816 \ https://forth-standard.org/standard/core/IF
37817 \ IF       -- IFadr    initialize conditional forward branch
37818 CODE IF       \ immediate
37819 SUB #2,PSP              \
37820 MOV TOS,0(PSP)          \
37821 MOV &DP,TOS             \ -- HERE
37822 ADD #4,&DP            \           compile one word, reserve one word
37823 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
37824 ADD #2,TOS              \ -- HERE+2=IFadr
37825 MOV @IP+,PC
37826 ENDCODE IMMEDIATE
37827 [THEN]
37828
37829 [UNDEFINED] THEN [IF]
37830 \ https://forth-standard.org/standard/core/THEN
37831 \ THEN     IFadr --                resolve forward branch
37832 CODE THEN               \ immediate
37833 MOV &DP,0(TOS)          \ -- IFadr
37834 MOV @PSP+,TOS           \ --
37835 MOV @IP+,PC
37836 ENDCODE IMMEDIATE
37837 [THEN]
37838
37839 [UNDEFINED] ELSE [IF]
37840 \ https://forth-standard.org/standard/core/ELSE
37841 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
37842 CODE ELSE     \ immediate
37843 ADD #4,&DP              \ make room to compile two words
37844 MOV &DP,W               \ W=HERE+4
37845 MOV #BRAN,-4(W)
37846 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
37847 SUB #2,W                \ HERE+2
37848 MOV W,TOS               \ -- ELSEadr
37849 MOV @IP+,PC
37850 ENDCODE IMMEDIATE
37851 [THEN]
37852
37853 [UNDEFINED] DEFER [IF]
37854 \ https://forth-standard.org/standard/core/DEFER
37855 \ DEFER "<spaces>name"   --
37856 \ Skip leading space delimiters. Parse name delimited by a space.
37857 \ Create a definition for name with the execution semantics defined below.
37858
37859 \ name Execution:   --
37860 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
37861 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
37862 : DEFER
37863 CREATE
37864 HI2LO
37865 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
37866 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
37867 MOV @RSP+,IP
37868 MOV @IP+,PC
37869 ENDCODE
37870 [THEN]
37871
37872 [UNDEFINED] DEFER! [IF]
37873 \ https://forth-standard.org/standard/core/DEFERStore
37874 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
37875 CODE DEFER!             \ xt2 xt1 --
37876 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
37877 MOV @PSP+,TOS           \ --
37878 MOV @IP+,PC
37879 ENDCODE
37880 [THEN]
37881
37882 [UNDEFINED] IS [IF]
37883 \ https://forth-standard.org/standard/core/IS
37884 \ IS <name>        xt --
37885 \ used as is :
37886 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
37887 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
37888 \ or in a definition : ... ['] U. IS DISPLAY ...
37889 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
37890 \
37891 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
37892 : IS
37893 STATE @
37894 IF  POSTPONE ['] POSTPONE DEFER! 
37895 ELSE ' DEFER! 
37896 THEN
37897 ; IMMEDIATE
37898 [THEN]
37899
37900 [UNDEFINED] >BODY [IF]
37901 \ https://forth-standard.org/standard/core/toBODY
37902 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
37903 CODE >BODY
37904 ADD #4,TOS
37905 MOV @IP+,PC
37906 ENDCODE
37907 [THEN]
37908
37909 \ CODE 20uS           \ n --      8MHz version
37910 \ BEGIN               \ 4 + 16 ~ loop
37911 \     MOV #39,rDOCON   \ 39
37912 \     BEGIN           \ 4 ~ loop
37913 \         NOP
37914 \         SUB #1,rDOCON
37915 \     0=  UNTIL
37916 \     SUB #1,TOS      \ 1
37917 \ 0= UNTIL
37918 \ MOV #XDOCON,rDOCON  \ 2
37919 \ MOV @PSP+,TOS
37920 \ MOV @RSP+,IP        \
37921 \ ENDCODE
37922
37923 CODE 20_US                      \ n --      n * 20 us
37924 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
37925     BEGIN
37926         BIT #1,&LCD_TIM_CTL     \ 3
37927     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
37928     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
37929     SUB #1,TOS                  \ 1
37930 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
37931 MOV @PSP+,TOS                   \ 2
37932 MOV @IP+,PC                     \ 4
37933 ENDCODE
37934
37935 CODE TOP_LCD                    \ LCD Sample
37936 \                               \ if write : %xxxx_WWWW --
37937 \                               \ if read  : -- %0000_RRRR
37938     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
37939     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
37940 0= IF                           \ write LCD bits pattern
37941     AND.B #LCD_DB,TOS           \ 
37942     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
37943     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
37944     MOV @PSP+,TOS               \
37945     MOV @IP+,PC
37946 THEN                            \ read LCD bits pattern
37947     SUB #2,PSP
37948     MOV TOS,0(PSP)
37949     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
37950     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
37951     AND.B #LCD_DB,TOS           \
37952     MOV @IP+,PC
37953 ENDCODE
37954
37955 CODE LCD_WRC                    \ char --         Write Char
37956     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
37957 BW1 SUB #2,PSP                  \
37958     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
37959     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
37960     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
37961     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
37962 COLON                           \ high level word starts here 
37963     TOP_LCD 2 20_US             \ write high nibble first
37964     TOP_LCD 2 20_US 
37965 ;
37966
37967 CODE LCD_WRF                    \ func --         Write Fonction
37968     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
37969     GOTO BW1
37970 ENDCODE
37971
37972 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
37973 : LCD_HOME $02 LCD_WRF 100 20_us ;
37974
37975 \ [UNDEFINED] OR [IF]
37976
37977 \ \ https://forth-standard.org/standard/core/OR
37978 \ \ C OR     x1 x2 -- x3           logical OR
37979 \ CODE OR
37980 \ BIS @PSP+,TOS
37981 \ MOV @IP+,PC
37982 \ ENDCODE
37983
37984 \ [THEN]
37985
37986 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
37987 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
37988 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
37989 \ : LCD_FN_SET        $20 OR LCD_WrF ;
37990 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
37991 \ : LCD_GOTO          $80 OR LCD_WrF ;
37992
37993
37994 \ CODE LCD_RDS                    \ -- status       Read Status
37995 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
37996 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
37997 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
37998 \ COLON                           \ starts a FORTH word
37999 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
38000 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
38001 \ HI2LO                           \ switch from FORTH to assembler
38002 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
38003 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
38004 \     MOV @RSP+,IP                \ restore IP saved by COLON
38005 \     MOV @IP+,PC                 \
38006 \ ENDCODE
38007
38008 \ CODE LCD_RDC                    \ -- char         Read Char
38009 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
38010 \     GOTO BW1
38011 \ ENDCODE
38012
38013
38014 \ ******************************\
38015 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
38016 \ ******************************\
38017 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
38018 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
38019 BIT.B #SW2,&SW2_IN              \ test switch S2
38020 0= IF                           \ case of switch S2 pressed
38021     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
38022     U< IF
38023         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
38024     THEN
38025 ELSE
38026     BIT.B #SW1,&SW1_IN          \ test switch S1 input
38027     0= IF                       \ case of Switch S1 pressed
38028         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
38029         U>= IF                  \
38030            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
38031         THEN                    \
38032     THEN                        \
38033 THEN                            \
38034 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
38035 RET                             \ 5
38036 ENDASM
38037
38038 \ ******************************\
38039 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
38040 \ ******************************\
38041 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
38042 \ ******************************\
38043 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
38044 \                               \       SMclock = 8|16|24 MHz
38045 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
38046 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
38047 \                               \       SR(9)=new Toggle bit memory (ADD on)
38048 \ ******************************\
38049 \ RC5_FirstStartBitHalfCycle:   \
38050 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
38051 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
38052 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
38053 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
38054 \ [THEN]
38055 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
38056     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
38057 [THEN]
38058 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
38059     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
38060 [THEN]
38061 MOV #1778,X                     \ RC5_Period * 1us
38062 MOV #14,W                       \ count of loop
38063 BEGIN                           \
38064 \ ******************************\
38065 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
38066 \ ******************************\                   |
38067 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
38068 \ RC5_Compute_3/4_Period:       \                   |
38069     RRUM    #1,X                \ X=1/2 cycle       |
38070     MOV     X,Y                 \                   ^
38071     RRUM    #1,Y                \ Y=1/4
38072     ADD     X,Y                 \ Y=3/4 cycle
38073     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
38074     U>= UNTIL                   \ 2
38075 \ ******************************\
38076 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
38077 \ ******************************\
38078     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
38079     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
38080     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
38081     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
38082     SUB     #1,W                \ decrement count loop
38083 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
38084 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
38085 0<> WHILE                       \ ----> out of loop ----+
38086     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
38087     BEGIN                       \                       |
38088         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
38089         CMP Y,X                 \ 1                     |   cycle time out of bound ?
38090         U>= IF                  \ 2                 ^   |   yes:
38091         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
38092         GOTO BW1                \                   |   |      quit on truncated RC5 message
38093         THEN                    \                   |   |
38094         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
38095     0<> UNTIL                   \ 2                 |   |
38096 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
38097 \ ******************************\                       |
38098 \ RC5_SampleEndOf:              \ <---------------------+
38099 \ ******************************\
38100 BIC #$30,&RC5_TIM_CTL           \   stop timer
38101 \ ******************************\
38102 \ RC5_ComputeNewRC5word         \
38103 \ ******************************\
38104 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
38105 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
38106 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
38107 \ ******************************\
38108 \ RC5_ComputeC6bit              \
38109 \ ******************************\
38110 BIT     #BIT14,T                \ test /C6 bit in T
38111 0= IF   BIS #BIT6,X             \ set C6 bit in X
38112 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
38113 \ ******************************\
38114 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
38115 \ ******************************\
38116 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
38117 \ ******************************\
38118 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
38119 XOR     @RSP,T                  \ (new XOR old) Toggle bits
38120 BIT     #UF10,T                 \ repeated RC5_command ?
38121 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
38122 XOR #UF10,0(RSP)                \ 5 toggle bit memory
38123 \ ******************************\
38124 \ Display IR_RC5 code           \
38125 \ ******************************\
38126 SUB #8,PSP                      \ TOS -- x x x x TOS
38127 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
38128 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
38129 MOV #$10,&BASEADR               \                                               set hexadecimal base
38130 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
38131 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
38132 LO2HI                           \                                               switch from assembler to FORTH
38133     LCD_CLEAR                   \                                               set LCD cursor at home
38134     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
38135     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
38136     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
38137     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
38138 HI2LO                           \     --                                        switch from FORTH to assembler
38139 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
38140 MOV @PSP+,TOS                   \     -- TOS
38141 RET
38142 ENDASM
38143
38144 \ ******************************\
38145 ASM BACKGROUND                  \
38146 \ ******************************\
38147 BEGIN
38148 \     ...                         \ insert here your background task
38149 \     ...                         \
38150 \     ...                         \
38151     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
38152     BIS &LPM_MODE,SR            \
38153 \ ******************************\
38154 \ here start all interrupts     \
38155 \ ******************************\
38156 \ here return all interrupts    \
38157 \ ******************************\
38158 AGAIN                           \
38159 ENDASM                          \
38160 \ ******************************\
38161
38162 \ ------------------------------\
38163 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
38164 \ ------------------------------\
38165 \     ...                         \ init specific I/O sys as you want
38166 \     ...                         \ before executing default WARM
38167     MOV #WARM,X                 \ ['] WARM 
38168     ADD #4,X                    \ >BODY
38169     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
38170 ENDASM
38171 \ ------------------------------\
38172
38173 \ ------------------------------\
38174 CODE STOP                       \ stops multitasking, must to be used before downloading app
38175 \ ------------------------------\
38176 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
38177     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
38178     MOV X,-2(X)                 \ restore the default background: SLEEP
38179     MOV #WARM,X
38180     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
38181     BIC.B #RC5,&IR_IE           \ clear RC5_Int
38182     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
38183     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
38184     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
38185     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
38186     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
38187 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
38188 ECHO                            \
38189 ." RC5toLCD is removed,"
38190 ."  type START to restart"
38191  WARM                           \ performs reset to reset all interrupt vectors.    
38192 ;
38193 \ ------------------------------\
38194
38195 \ ------------------------------\
38196 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
38197 \ ------------------------------\
38198 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
38199 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
38200 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
38201 \                           --       \ID input divider \ 10 = /4
38202 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
38203 \                                 -  \TBCLR TimerB Clear
38204 \                                  - \TBIE
38205 \                                   -\TBIFG
38206 \ -------------------------------\
38207 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
38208 \                  --                 \CM Capture Mode
38209 \                    --               \CCIS
38210 \                       -             \SCS
38211 \                        --           \CLLD
38212 \                          -          \CAP
38213 \                            ---      \OUTMOD \ 011 = set/reset
38214 \                               -     \CCIE
38215 \                                 -   \CCI
38216 \                                  -  \OUT
38217 \                                   - \COV
38218 \                                    -\CCIFG
38219 \ -------------------------------\
38220 \ LCD_TIM_CCRx                   \
38221 \ -------------------------------\
38222 \ LCD_TIM_EX0                    \ 
38223 \ ------------------------------\
38224 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
38225 \ ------------------------------\
38226 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
38227 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
38228 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
38229     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
38230 [THEN]
38231 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
38232     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
38233 [THEN]
38234     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
38235 \ ------------------------------\
38236 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
38237 \ ------------------------------\
38238 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
38239     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
38240 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
38241 \ ------------------------------\
38242     BIS.B #LCDVo,&LCDVo_DIR     \
38243     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
38244 \ ------------------------------\
38245     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
38246     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
38247 \ ------------------------------\
38248     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
38249     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
38250 \ ******************************\
38251 \ init RC5_Int                  \
38252 \ ******************************\
38253     BIS.B #RC5,&IR_IE           \ enable RC5_Int
38254     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
38255     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
38256 \ ******************************\
38257 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
38258 \ ******************************\
38259 \              %01 0001 0100    \ TAxCTL
38260 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
38261 \                  --           \ ID        divided by 1
38262 \                    --         \ MC        MODE = up to TAxCCRn
38263 \                        -      \ TACLR     clear timer count
38264 \                         -     \ TAIE
38265 \                          -    \ TAIFG
38266 \ ------------------------------\
38267 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
38268 \ ------------------------------\
38269 \                        000    \ TAxEX0
38270 \                        ---    \ TAIDEX    pre divisor
38271 \ ------------------------------\
38272 \          %0000 0000 0000 0101 \ TAxCCR0
38273     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
38274 \ ------------------------------\
38275 \          %0000 0000 0001 0000 \ TAxCCTL0
38276 \                   -           \ CAP capture/compare mode = compare
38277 \                        -      \ CCIEn
38278 \                             - \ CCIFGn
38279     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
38280 \ ------------------------------\
38281     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
38282 \ ------------------------------\
38283 \ define LPM mode for ACCEPT    \
38284 \ ------------------------------\
38285 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
38286 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
38287 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
38288 \ ------------------------------\
38289 \ activate I/O                  \
38290 \ ------------------------------\
38291 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
38292 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
38293 \ ------------------------------\
38294 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
38295 \ ------------------------------\
38296 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
38297 \ CMP #2,Y                        \ Power_ON event
38298 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
38299 CMP #4,Y                        \
38300 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
38301 \ CMP #6,Y                        \
38302 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
38303 \ CMP #$0A,Y                      \
38304 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
38305 \ CMP #$16,Y                      \
38306 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
38307 \ ------------------------------\
38308 COLON                           \
38309 \ ------------------------------\
38310 \ Init LCD 2x20                 \
38311 \ ------------------------------\
38312     #1000 20_US                 \ 1- wait 20 ms
38313     %011 TOP_LCD                \ 2- send DB5=DB4=1
38314     #205 20_US                  \ 3- wait 4,1 ms
38315     %011 TOP_LCD                \ 4- send again DB5=DB4=1
38316     #5 20_US                    \ 5- wait 0,1 ms
38317     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
38318     #2 20_US                    \    wait 40 us = LCD cycle
38319     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
38320     #2 20_US                    \    wait 40 us = LCD cycle
38321     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
38322     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
38323     LCD_CLEAR                   \ 10- "LCD_Clear"
38324     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
38325     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
38326     LCD_CLEAR                   \ 10- "LCD_Clear"
38327     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
38328     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
38329     CR ." I love you"           \ display message on LCD
38330     ['] CR >BODY IS CR          \ CR executes its default value
38331     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
38332     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
38333     PWR_STATE ABORT             \ init DP and continues with ABORT
38334 ;                               \
38335 \ ------------------------------\
38336
38337 \ ------------------------------\
38338 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
38339 \ ------------------------------\
38340 MOV #SLEEP,X                    \ replace default background process SLEEP
38341 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
38342 MOV #WARM,X                     \ replace default WARM
38343 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
38344 MOV X,PC                        \ then execute new WARM
38345 ENDCODE 
38346 \ ------------------------------\
38347
38348 ECHO
38349             ; downloading RC5toLCD.4th is done
38350 RST_HERE    ; this app is protected against <reset>
38351
38352
38353 RST_STATE
38354
38355 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
38356
38357 [UNDEFINED] MARKER [IF]
38358 \  https://forth-standard.org/standard/core/MARKER
38359 \  MARKER
38360 \ ( "<spaces>name" -- )
38361 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
38362 \ with the execution semantics defined below.
38363
38364 \ name Execution: ( -- )
38365 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
38366 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
38367 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
38368 \ not necessarily provided. No other contextual information such as numeric base is affected
38369 \
38370 : MARKER
38371 CREATE
38372 HI2LO
38373 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
38374 SUB #2,Y            \ 1 Y = LFA
38375 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
38376 ADD #4,&DP          \ 3 add 2 cells
38377 LO2HI
38378 DOES>
38379 HI2LO
38380 MOV @RSP+,IP        \ -- PFA
38381 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
38382 MOV @TOS,&INIDP     \       set DP value for RST_STATE
38383 MOV @PSP+,TOS       \ --
38384 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
38385 ENDCODE
38386 [THEN]
38387
38388 MARKER {RC5TOLCD}
38389
38390 [UNDEFINED] @ [IF]
38391 \ https://forth-standard.org/standard/core/Fetch
38392 \ @     c-addr -- char   fetch char from memory
38393 CODE @
38394 MOV @TOS,TOS
38395 MOV @IP+,PC
38396 ENDCODE
38397 [THEN]
38398
38399 [UNDEFINED] CONSTANT [IF]
38400 \ https://forth-standard.org/standard/core/CONSTANT
38401 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
38402 : CONSTANT 
38403 CREATE
38404 HI2LO
38405 MOV TOS,-2(W)           \   PFA = n
38406 MOV @PSP+,TOS
38407 MOV @RSP+,IP
38408 MOV @IP+,PC
38409 ENDCODE
38410 [THEN]
38411
38412 [UNDEFINED] STATE [IF]
38413 \ https://forth-standard.org/standard/core/STATE
38414 \ STATE   -- a-addr       holds compiler state
38415 STATEADR CONSTANT STATE
38416 [THEN]
38417
38418 [UNDEFINED] = [IF]
38419 \ https://forth-standard.org/standard/core/Equal
38420 \ =      x1 x2 -- flag         test x1=x2
38421 CODE =
38422 SUB @PSP+,TOS   \ 2
38423 0<> IF          \ 2
38424     AND #0,TOS  \ 1
38425     MOV @IP+,PC \ 4
38426 THEN
38427 XOR #-1,TOS     \ 1 flag Z = 1
38428 MOV @IP+,PC     \ 4
38429 ENDCODE
38430 [THEN]
38431
38432 [UNDEFINED] IF [IF]
38433 \ https://forth-standard.org/standard/core/IF
38434 \ IF       -- IFadr    initialize conditional forward branch
38435 CODE IF       \ immediate
38436 SUB #2,PSP              \
38437 MOV TOS,0(PSP)          \
38438 MOV &DP,TOS             \ -- HERE
38439 ADD #4,&DP            \           compile one word, reserve one word
38440 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
38441 ADD #2,TOS              \ -- HERE+2=IFadr
38442 MOV @IP+,PC
38443 ENDCODE IMMEDIATE
38444 [THEN]
38445
38446 [UNDEFINED] THEN [IF]
38447 \ https://forth-standard.org/standard/core/THEN
38448 \ THEN     IFadr --                resolve forward branch
38449 CODE THEN               \ immediate
38450 MOV &DP,0(TOS)          \ -- IFadr
38451 MOV @PSP+,TOS           \ --
38452 MOV @IP+,PC
38453 ENDCODE IMMEDIATE
38454 [THEN]
38455
38456 [UNDEFINED] ELSE [IF]
38457 \ https://forth-standard.org/standard/core/ELSE
38458 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
38459 CODE ELSE     \ immediate
38460 ADD #4,&DP              \ make room to compile two words
38461 MOV &DP,W               \ W=HERE+4
38462 MOV #BRAN,-4(W)
38463 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
38464 SUB #2,W                \ HERE+2
38465 MOV W,TOS               \ -- ELSEadr
38466 MOV @IP+,PC
38467 ENDCODE IMMEDIATE
38468 [THEN]
38469
38470 [UNDEFINED] DEFER [IF]
38471 \ https://forth-standard.org/standard/core/DEFER
38472 \ DEFER "<spaces>name"   --
38473 \ Skip leading space delimiters. Parse name delimited by a space.
38474 \ Create a definition for name with the execution semantics defined below.
38475
38476 \ name Execution:   --
38477 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
38478 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
38479 : DEFER
38480 CREATE
38481 HI2LO
38482 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
38483 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
38484 MOV @RSP+,IP
38485 MOV @IP+,PC
38486 ENDCODE
38487 [THEN]
38488
38489 [UNDEFINED] DEFER! [IF]
38490 \ https://forth-standard.org/standard/core/DEFERStore
38491 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
38492 CODE DEFER!             \ xt2 xt1 --
38493 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
38494 MOV @PSP+,TOS           \ --
38495 MOV @IP+,PC
38496 ENDCODE
38497 [THEN]
38498
38499 [UNDEFINED] IS [IF]
38500 \ https://forth-standard.org/standard/core/IS
38501 \ IS <name>        xt --
38502 \ used as is :
38503 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
38504 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
38505 \ or in a definition : ... ['] U. IS DISPLAY ...
38506 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
38507 \
38508 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
38509 : IS
38510 STATE @
38511 IF  POSTPONE ['] POSTPONE DEFER! 
38512 ELSE ' DEFER! 
38513 THEN
38514 ; IMMEDIATE
38515 [THEN]
38516
38517 [UNDEFINED] >BODY [IF]
38518 \ https://forth-standard.org/standard/core/toBODY
38519 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
38520 CODE >BODY
38521 ADD #4,TOS
38522 MOV @IP+,PC
38523 ENDCODE
38524 [THEN]
38525
38526 \ CODE 20uS           \ n --      8MHz version
38527 \ BEGIN               \ 4 + 16 ~ loop
38528 \     MOV #39,rDOCON   \ 39
38529 \     BEGIN           \ 4 ~ loop
38530 \         NOP
38531 \         SUB #1,rDOCON
38532 \     0=  UNTIL
38533 \     SUB #1,TOS      \ 1
38534 \ 0= UNTIL
38535 \ MOV #XDOCON,rDOCON  \ 2
38536 \ MOV @PSP+,TOS
38537 \ MOV @RSP+,IP        \
38538 \ ENDCODE
38539
38540 CODE 20_US                      \ n --      n * 20 us
38541 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
38542     BEGIN
38543         BIT #1,&LCD_TIM_CTL     \ 3
38544     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
38545     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
38546     SUB #1,TOS                  \ 1
38547 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
38548 MOV @PSP+,TOS                   \ 2
38549 MOV @IP+,PC                     \ 4
38550 ENDCODE
38551
38552 CODE TOP_LCD                    \ LCD Sample
38553 \                               \ if write : %xxxx_WWWW --
38554 \                               \ if read  : -- %0000_RRRR
38555     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
38556     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
38557 0= IF                           \ write LCD bits pattern
38558     AND.B #LCD_DB,TOS           \ 
38559     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
38560     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
38561     MOV @PSP+,TOS               \
38562     MOV @IP+,PC
38563 THEN                            \ read LCD bits pattern
38564     SUB #2,PSP
38565     MOV TOS,0(PSP)
38566     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
38567     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
38568     AND.B #LCD_DB,TOS           \
38569     MOV @IP+,PC
38570 ENDCODE
38571
38572 CODE LCD_WRC                    \ char --         Write Char
38573     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
38574 BW1 SUB #2,PSP                  \
38575     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
38576     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
38577     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
38578     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
38579 COLON                           \ high level word starts here 
38580     TOP_LCD 2 20_US             \ write high nibble first
38581     TOP_LCD 2 20_US 
38582 ;
38583
38584 CODE LCD_WRF                    \ func --         Write Fonction
38585     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
38586     GOTO BW1
38587 ENDCODE
38588
38589 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
38590 : LCD_HOME $02 LCD_WRF 100 20_us ;
38591
38592 \ [UNDEFINED] OR [IF]
38593
38594 \ \ https://forth-standard.org/standard/core/OR
38595 \ \ C OR     x1 x2 -- x3           logical OR
38596 \ CODE OR
38597 \ BIS @PSP+,TOS
38598 \ MOV @IP+,PC
38599 \ ENDCODE
38600
38601 \ [THEN]
38602
38603 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
38604 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
38605 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
38606 \ : LCD_FN_SET        $20 OR LCD_WrF ;
38607 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
38608 \ : LCD_GOTO          $80 OR LCD_WrF ;
38609
38610
38611 \ CODE LCD_RDS                    \ -- status       Read Status
38612 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
38613 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
38614 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
38615 \ COLON                           \ starts a FORTH word
38616 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
38617 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
38618 \ HI2LO                           \ switch from FORTH to assembler
38619 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
38620 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
38621 \     MOV @RSP+,IP                \ restore IP saved by COLON
38622 \     MOV @IP+,PC                 \
38623 \ ENDCODE
38624
38625 \ CODE LCD_RDC                    \ -- char         Read Char
38626 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
38627 \     GOTO BW1
38628 \ ENDCODE
38629
38630
38631 \ ******************************\
38632 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
38633 \ ******************************\
38634 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
38635 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
38636 BIT.B #SW2,&SW2_IN              \ test switch S2
38637 0= IF                           \ case of switch S2 pressed
38638     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
38639     U< IF
38640         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
38641     THEN
38642 ELSE
38643     BIT.B #SW1,&SW1_IN          \ test switch S1 input
38644     0= IF                       \ case of Switch S1 pressed
38645         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
38646         U>= IF                  \
38647            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
38648         THEN                    \
38649     THEN                        \
38650 THEN                            \
38651 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
38652 RET                             \ 5
38653 ENDASM
38654
38655 \ ******************************\
38656 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
38657 \ ******************************\
38658 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
38659 \ ******************************\
38660 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
38661 \                               \       SMclock = 8|16|24 MHz
38662 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
38663 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
38664 \                               \       SR(9)=new Toggle bit memory (ADD on)
38665 \ ******************************\
38666 \ RC5_FirstStartBitHalfCycle:   \
38667 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
38668 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
38669 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
38670 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
38671 \ [THEN]
38672 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
38673     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
38674 [THEN]
38675 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
38676     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
38677 [THEN]
38678 MOV #1778,X                     \ RC5_Period * 1us
38679 MOV #14,W                       \ count of loop
38680 BEGIN                           \
38681 \ ******************************\
38682 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
38683 \ ******************************\                   |
38684 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
38685 \ RC5_Compute_3/4_Period:       \                   |
38686     RRUM    #1,X                \ X=1/2 cycle       |
38687     MOV     X,Y                 \                   ^
38688     RRUM    #1,Y                \ Y=1/4
38689     ADD     X,Y                 \ Y=3/4 cycle
38690     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
38691     U>= UNTIL                   \ 2
38692 \ ******************************\
38693 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
38694 \ ******************************\
38695     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
38696     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
38697     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
38698     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
38699     SUB     #1,W                \ decrement count loop
38700 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
38701 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
38702 0<> WHILE                       \ ----> out of loop ----+
38703     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
38704     BEGIN                       \                       |
38705         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
38706         CMP Y,X                 \ 1                     |   cycle time out of bound ?
38707         U>= IF                  \ 2                 ^   |   yes:
38708         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
38709         GOTO BW1                \                   |   |      quit on truncated RC5 message
38710         THEN                    \                   |   |
38711         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
38712     0<> UNTIL                   \ 2                 |   |
38713 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
38714 \ ******************************\                       |
38715 \ RC5_SampleEndOf:              \ <---------------------+
38716 \ ******************************\
38717 BIC #$30,&RC5_TIM_CTL           \   stop timer
38718 \ ******************************\
38719 \ RC5_ComputeNewRC5word         \
38720 \ ******************************\
38721 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
38722 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
38723 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
38724 \ ******************************\
38725 \ RC5_ComputeC6bit              \
38726 \ ******************************\
38727 BIT     #BIT14,T                \ test /C6 bit in T
38728 0= IF   BIS #BIT6,X             \ set C6 bit in X
38729 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
38730 \ ******************************\
38731 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
38732 \ ******************************\
38733 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
38734 \ ******************************\
38735 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
38736 XOR     @RSP,T                  \ (new XOR old) Toggle bits
38737 BIT     #UF10,T                 \ repeated RC5_command ?
38738 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
38739 XOR #UF10,0(RSP)                \ 5 toggle bit memory
38740 \ ******************************\
38741 \ Display IR_RC5 code           \
38742 \ ******************************\
38743 SUB #8,PSP                      \ TOS -- x x x x TOS
38744 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
38745 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
38746 MOV #$10,&BASEADR               \                                               set hexadecimal base
38747 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
38748 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
38749 LO2HI                           \                                               switch from assembler to FORTH
38750     LCD_CLEAR                   \                                               set LCD cursor at home
38751     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
38752     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
38753     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
38754     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
38755 HI2LO                           \     --                                        switch from FORTH to assembler
38756 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
38757 MOV @PSP+,TOS                   \     -- TOS
38758 RET
38759 ENDASM
38760
38761 \ ******************************\
38762 ASM BACKGROUND                  \
38763 \ ******************************\
38764 BEGIN
38765 \     ...                         \ insert here your background task
38766 \     ...                         \
38767 \     ...                         \
38768     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
38769     BIS &LPM_MODE,SR            \
38770 \ ******************************\
38771 \ here start all interrupts     \
38772 \ ******************************\
38773 \ here return all interrupts    \
38774 \ ******************************\
38775 AGAIN                           \
38776 ENDASM                          \
38777 \ ******************************\
38778
38779 \ ------------------------------\
38780 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
38781 \ ------------------------------\
38782 \     ...                         \ init specific I/O sys as you want
38783 \     ...                         \ before executing default WARM
38784     MOV #WARM,X                 \ ['] WARM 
38785     ADD #4,X                    \ >BODY
38786     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
38787 ENDASM
38788 \ ------------------------------\
38789
38790 \ ------------------------------\
38791 CODE STOP                       \ stops multitasking, must to be used before downloading app
38792 \ ------------------------------\
38793 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
38794     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
38795     MOV X,-2(X)                 \ restore the default background: SLEEP
38796     MOV #WARM,X
38797     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
38798     BIC.B #RC5,&IR_IE           \ clear RC5_Int
38799     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
38800     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
38801     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
38802     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
38803     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
38804 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
38805 ECHO                            \
38806 ." RC5toLCD is removed,"
38807 ."  type START to restart"
38808  WARM                           \ performs reset to reset all interrupt vectors.    
38809 ;
38810 \ ------------------------------\
38811
38812 \ ------------------------------\
38813 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
38814 \ ------------------------------\
38815 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
38816 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
38817 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
38818 \                           --       \ID input divider \ 10 = /4
38819 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
38820 \                                 -  \TBCLR TimerB Clear
38821 \                                  - \TBIE
38822 \                                   -\TBIFG
38823 \ -------------------------------\
38824 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
38825 \                  --                 \CM Capture Mode
38826 \                    --               \CCIS
38827 \                       -             \SCS
38828 \                        --           \CLLD
38829 \                          -          \CAP
38830 \                            ---      \OUTMOD \ 011 = set/reset
38831 \                               -     \CCIE
38832 \                                 -   \CCI
38833 \                                  -  \OUT
38834 \                                   - \COV
38835 \                                    -\CCIFG
38836 \ -------------------------------\
38837 \ LCD_TIM_CCRx                   \
38838 \ -------------------------------\
38839 \ LCD_TIM_EX0                    \ 
38840 \ ------------------------------\
38841 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
38842 \ ------------------------------\
38843 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
38844 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
38845 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
38846     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
38847 [THEN]
38848 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
38849     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
38850 [THEN]
38851     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
38852 \ ------------------------------\
38853 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
38854 \ ------------------------------\
38855 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
38856     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
38857 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
38858 \ ------------------------------\
38859     BIS.B #LCDVo,&LCDVo_DIR     \
38860     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
38861 \ ------------------------------\
38862     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
38863     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
38864 \ ------------------------------\
38865     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
38866     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
38867 \ ******************************\
38868 \ init RC5_Int                  \
38869 \ ******************************\
38870     BIS.B #RC5,&IR_IE           \ enable RC5_Int
38871     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
38872     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
38873 \ ******************************\
38874 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
38875 \ ******************************\
38876 \              %01 0001 0100    \ TAxCTL
38877 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
38878 \                  --           \ ID        divided by 1
38879 \                    --         \ MC        MODE = up to TAxCCRn
38880 \                        -      \ TACLR     clear timer count
38881 \                         -     \ TAIE
38882 \                          -    \ TAIFG
38883 \ ------------------------------\
38884 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
38885 \ ------------------------------\
38886 \                        000    \ TAxEX0
38887 \                        ---    \ TAIDEX    pre divisor
38888 \ ------------------------------\
38889 \          %0000 0000 0000 0101 \ TAxCCR0
38890     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
38891 \ ------------------------------\
38892 \          %0000 0000 0001 0000 \ TAxCCTL0
38893 \                   -           \ CAP capture/compare mode = compare
38894 \                        -      \ CCIEn
38895 \                             - \ CCIFGn
38896     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
38897 \ ------------------------------\
38898     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
38899 \ ------------------------------\
38900 \ define LPM mode for ACCEPT    \
38901 \ ------------------------------\
38902 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
38903 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
38904 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
38905 \ ------------------------------\
38906 \ activate I/O                  \
38907 \ ------------------------------\
38908 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
38909 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
38910 \ ------------------------------\
38911 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
38912 \ ------------------------------\
38913 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
38914 \ CMP #2,Y                        \ Power_ON event
38915 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
38916 CMP #4,Y                        \
38917 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
38918 \ CMP #6,Y                        \
38919 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
38920 \ CMP #$0A,Y                      \
38921 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
38922 \ CMP #$16,Y                      \
38923 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
38924 \ ------------------------------\
38925 COLON                           \
38926 \ ------------------------------\
38927 \ Init LCD 2x20                 \
38928 \ ------------------------------\
38929     #1000 20_US                 \ 1- wait 20 ms
38930     %011 TOP_LCD                \ 2- send DB5=DB4=1
38931     #205 20_US                  \ 3- wait 4,1 ms
38932     %011 TOP_LCD                \ 4- send again DB5=DB4=1
38933     #5 20_US                    \ 5- wait 0,1 ms
38934     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
38935     #2 20_US                    \    wait 40 us = LCD cycle
38936     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
38937     #2 20_US                    \    wait 40 us = LCD cycle
38938     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
38939     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
38940     LCD_CLEAR                   \ 10- "LCD_Clear"
38941     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
38942     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
38943     LCD_CLEAR                   \ 10- "LCD_Clear"
38944     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
38945     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
38946     CR ." I love you"           \ display message on LCD
38947     ['] CR >BODY IS CR          \ CR executes its default value
38948     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
38949     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
38950     PWR_STATE ABORT             \ init DP and continues with ABORT
38951 ;                               \
38952 \ ------------------------------\
38953
38954 \ ------------------------------\
38955 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
38956 \ ------------------------------\
38957 MOV #SLEEP,X                    \ replace default background process SLEEP
38958 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
38959 MOV #WARM,X                     \ replace default WARM
38960 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
38961 MOV X,PC                        \ then execute new WARM
38962 ENDCODE 
38963 \ ------------------------------\
38964
38965 ECHO
38966             ; downloading RC5toLCD.4th is done
38967 RST_HERE    ; this app is protected against <reset>
38968
38969
38970 RST_STATE
38971
38972 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
38973
38974 [UNDEFINED] MARKER [IF]
38975 \  https://forth-standard.org/standard/core/MARKER
38976 \  MARKER
38977 \ ( "<spaces>name" -- )
38978 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
38979 \ with the execution semantics defined below.
38980
38981 \ name Execution: ( -- )
38982 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
38983 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
38984 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
38985 \ not necessarily provided. No other contextual information such as numeric base is affected
38986 \
38987 : MARKER
38988 CREATE
38989 HI2LO
38990 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
38991 SUB #2,Y            \ 1 Y = LFA
38992 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
38993 ADD #4,&DP          \ 3 add 2 cells
38994 LO2HI
38995 DOES>
38996 HI2LO
38997 MOV @RSP+,IP        \ -- PFA
38998 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
38999 MOV @TOS,&INIDP     \       set DP value for RST_STATE
39000 MOV @PSP+,TOS       \ --
39001 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
39002 ENDCODE
39003 [THEN]
39004
39005 MARKER {RC5TOLCD}
39006
39007 [UNDEFINED] @ [IF]
39008 \ https://forth-standard.org/standard/core/Fetch
39009 \ @     c-addr -- char   fetch char from memory
39010 CODE @
39011 MOV @TOS,TOS
39012 MOV @IP+,PC
39013 ENDCODE
39014 [THEN]
39015
39016 [UNDEFINED] CONSTANT [IF]
39017 \ https://forth-standard.org/standard/core/CONSTANT
39018 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
39019 : CONSTANT 
39020 CREATE
39021 HI2LO
39022 MOV TOS,-2(W)           \   PFA = n
39023 MOV @PSP+,TOS
39024 MOV @RSP+,IP
39025 MOV @IP+,PC
39026 ENDCODE
39027 [THEN]
39028
39029 [UNDEFINED] STATE [IF]
39030 \ https://forth-standard.org/standard/core/STATE
39031 \ STATE   -- a-addr       holds compiler state
39032 STATEADR CONSTANT STATE
39033 [THEN]
39034
39035 [UNDEFINED] = [IF]
39036 \ https://forth-standard.org/standard/core/Equal
39037 \ =      x1 x2 -- flag         test x1=x2
39038 CODE =
39039 SUB @PSP+,TOS   \ 2
39040 0<> IF          \ 2
39041     AND #0,TOS  \ 1
39042     MOV @IP+,PC \ 4
39043 THEN
39044 XOR #-1,TOS     \ 1 flag Z = 1
39045 MOV @IP+,PC     \ 4
39046 ENDCODE
39047 [THEN]
39048
39049 [UNDEFINED] IF [IF]
39050 \ https://forth-standard.org/standard/core/IF
39051 \ IF       -- IFadr    initialize conditional forward branch
39052 CODE IF       \ immediate
39053 SUB #2,PSP              \
39054 MOV TOS,0(PSP)          \
39055 MOV &DP,TOS             \ -- HERE
39056 ADD #4,&DP            \           compile one word, reserve one word
39057 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
39058 ADD #2,TOS              \ -- HERE+2=IFadr
39059 MOV @IP+,PC
39060 ENDCODE IMMEDIATE
39061 [THEN]
39062
39063 [UNDEFINED] THEN [IF]
39064 \ https://forth-standard.org/standard/core/THEN
39065 \ THEN     IFadr --                resolve forward branch
39066 CODE THEN               \ immediate
39067 MOV &DP,0(TOS)          \ -- IFadr
39068 MOV @PSP+,TOS           \ --
39069 MOV @IP+,PC
39070 ENDCODE IMMEDIATE
39071 [THEN]
39072
39073 [UNDEFINED] ELSE [IF]
39074 \ https://forth-standard.org/standard/core/ELSE
39075 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
39076 CODE ELSE     \ immediate
39077 ADD #4,&DP              \ make room to compile two words
39078 MOV &DP,W               \ W=HERE+4
39079 MOV #BRAN,-4(W)
39080 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
39081 SUB #2,W                \ HERE+2
39082 MOV W,TOS               \ -- ELSEadr
39083 MOV @IP+,PC
39084 ENDCODE IMMEDIATE
39085 [THEN]
39086
39087 [UNDEFINED] DEFER [IF]
39088 \ https://forth-standard.org/standard/core/DEFER
39089 \ DEFER "<spaces>name"   --
39090 \ Skip leading space delimiters. Parse name delimited by a space.
39091 \ Create a definition for name with the execution semantics defined below.
39092
39093 \ name Execution:   --
39094 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
39095 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
39096 : DEFER
39097 CREATE
39098 HI2LO
39099 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
39100 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
39101 MOV @RSP+,IP
39102 MOV @IP+,PC
39103 ENDCODE
39104 [THEN]
39105
39106 [UNDEFINED] DEFER! [IF]
39107 \ https://forth-standard.org/standard/core/DEFERStore
39108 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
39109 CODE DEFER!             \ xt2 xt1 --
39110 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
39111 MOV @PSP+,TOS           \ --
39112 MOV @IP+,PC
39113 ENDCODE
39114 [THEN]
39115
39116 [UNDEFINED] IS [IF]
39117 \ https://forth-standard.org/standard/core/IS
39118 \ IS <name>        xt --
39119 \ used as is :
39120 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
39121 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
39122 \ or in a definition : ... ['] U. IS DISPLAY ...
39123 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
39124 \
39125 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
39126 : IS
39127 STATE @
39128 IF  POSTPONE ['] POSTPONE DEFER! 
39129 ELSE ' DEFER! 
39130 THEN
39131 ; IMMEDIATE
39132 [THEN]
39133
39134 [UNDEFINED] >BODY [IF]
39135 \ https://forth-standard.org/standard/core/toBODY
39136 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
39137 CODE >BODY
39138 ADD #4,TOS
39139 MOV @IP+,PC
39140 ENDCODE
39141 [THEN]
39142
39143 \ CODE 20uS           \ n --      8MHz version
39144 \ BEGIN               \ 4 + 16 ~ loop
39145 \     MOV #39,rDOCON   \ 39
39146 \     BEGIN           \ 4 ~ loop
39147 \         NOP
39148 \         SUB #1,rDOCON
39149 \     0=  UNTIL
39150 \     SUB #1,TOS      \ 1
39151 \ 0= UNTIL
39152 \ MOV #XDOCON,rDOCON  \ 2
39153 \ MOV @PSP+,TOS
39154 \ MOV @RSP+,IP        \
39155 \ ENDCODE
39156
39157 CODE 20_US                      \ n --      n * 20 us
39158 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
39159     BEGIN
39160         BIT #1,&LCD_TIM_CTL     \ 3
39161     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
39162     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
39163     SUB #1,TOS                  \ 1
39164 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
39165 MOV @PSP+,TOS                   \ 2
39166 MOV @IP+,PC                     \ 4
39167 ENDCODE
39168
39169 CODE TOP_LCD                    \ LCD Sample
39170 \                               \ if write : %xxxx_WWWW --
39171 \                               \ if read  : -- %0000_RRRR
39172     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
39173     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
39174 0= IF                           \ write LCD bits pattern
39175     AND.B #LCD_DB,TOS           \ 
39176     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
39177     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
39178     MOV @PSP+,TOS               \
39179     MOV @IP+,PC
39180 THEN                            \ read LCD bits pattern
39181     SUB #2,PSP
39182     MOV TOS,0(PSP)
39183     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
39184     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
39185     AND.B #LCD_DB,TOS           \
39186     MOV @IP+,PC
39187 ENDCODE
39188
39189 CODE LCD_WRC                    \ char --         Write Char
39190     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
39191 BW1 SUB #2,PSP                  \
39192     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
39193     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
39194     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
39195     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
39196 COLON                           \ high level word starts here 
39197     TOP_LCD 2 20_US             \ write high nibble first
39198     TOP_LCD 2 20_US 
39199 ;
39200
39201 CODE LCD_WRF                    \ func --         Write Fonction
39202     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
39203     GOTO BW1
39204 ENDCODE
39205
39206 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
39207 : LCD_HOME $02 LCD_WRF 100 20_us ;
39208
39209 \ [UNDEFINED] OR [IF]
39210
39211 \ \ https://forth-standard.org/standard/core/OR
39212 \ \ C OR     x1 x2 -- x3           logical OR
39213 \ CODE OR
39214 \ BIS @PSP+,TOS
39215 \ MOV @IP+,PC
39216 \ ENDCODE
39217
39218 \ [THEN]
39219
39220 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
39221 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
39222 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
39223 \ : LCD_FN_SET        $20 OR LCD_WrF ;
39224 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
39225 \ : LCD_GOTO          $80 OR LCD_WrF ;
39226
39227
39228 \ CODE LCD_RDS                    \ -- status       Read Status
39229 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
39230 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
39231 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
39232 \ COLON                           \ starts a FORTH word
39233 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
39234 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
39235 \ HI2LO                           \ switch from FORTH to assembler
39236 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
39237 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
39238 \     MOV @RSP+,IP                \ restore IP saved by COLON
39239 \     MOV @IP+,PC                 \
39240 \ ENDCODE
39241
39242 \ CODE LCD_RDC                    \ -- char         Read Char
39243 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
39244 \     GOTO BW1
39245 \ ENDCODE
39246
39247
39248 \ ******************************\
39249 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
39250 \ ******************************\
39251 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
39252 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
39253 BIT.B #SW2,&SW2_IN              \ test switch S2
39254 0= IF                           \ case of switch S2 pressed
39255     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
39256     U< IF
39257         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
39258     THEN
39259 ELSE
39260     BIT.B #SW1,&SW1_IN          \ test switch S1 input
39261     0= IF                       \ case of Switch S1 pressed
39262         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
39263         U>= IF                  \
39264            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
39265         THEN                    \
39266     THEN                        \
39267 THEN                            \
39268 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
39269 RET                             \ 5
39270 ENDASM
39271
39272 \ ******************************\
39273 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
39274 \ ******************************\
39275 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
39276 \ ******************************\
39277 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
39278 \                               \       SMclock = 8|16|24 MHz
39279 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
39280 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
39281 \                               \       SR(9)=new Toggle bit memory (ADD on)
39282 \ ******************************\
39283 \ RC5_FirstStartBitHalfCycle:   \
39284 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
39285 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
39286 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
39287 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
39288 \ [THEN]
39289 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
39290     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
39291 [THEN]
39292 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
39293     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
39294 [THEN]
39295 MOV #1778,X                     \ RC5_Period * 1us
39296 MOV #14,W                       \ count of loop
39297 BEGIN                           \
39298 \ ******************************\
39299 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
39300 \ ******************************\                   |
39301 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
39302 \ RC5_Compute_3/4_Period:       \                   |
39303     RRUM    #1,X                \ X=1/2 cycle       |
39304     MOV     X,Y                 \                   ^
39305     RRUM    #1,Y                \ Y=1/4
39306     ADD     X,Y                 \ Y=3/4 cycle
39307     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
39308     U>= UNTIL                   \ 2
39309 \ ******************************\
39310 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
39311 \ ******************************\
39312     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
39313     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
39314     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
39315     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
39316     SUB     #1,W                \ decrement count loop
39317 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
39318 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
39319 0<> WHILE                       \ ----> out of loop ----+
39320     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
39321     BEGIN                       \                       |
39322         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
39323         CMP Y,X                 \ 1                     |   cycle time out of bound ?
39324         U>= IF                  \ 2                 ^   |   yes:
39325         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
39326         GOTO BW1                \                   |   |      quit on truncated RC5 message
39327         THEN                    \                   |   |
39328         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
39329     0<> UNTIL                   \ 2                 |   |
39330 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
39331 \ ******************************\                       |
39332 \ RC5_SampleEndOf:              \ <---------------------+
39333 \ ******************************\
39334 BIC #$30,&RC5_TIM_CTL           \   stop timer
39335 \ ******************************\
39336 \ RC5_ComputeNewRC5word         \
39337 \ ******************************\
39338 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
39339 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
39340 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
39341 \ ******************************\
39342 \ RC5_ComputeC6bit              \
39343 \ ******************************\
39344 BIT     #BIT14,T                \ test /C6 bit in T
39345 0= IF   BIS #BIT6,X             \ set C6 bit in X
39346 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
39347 \ ******************************\
39348 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
39349 \ ******************************\
39350 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
39351 \ ******************************\
39352 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
39353 XOR     @RSP,T                  \ (new XOR old) Toggle bits
39354 BIT     #UF10,T                 \ repeated RC5_command ?
39355 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
39356 XOR #UF10,0(RSP)                \ 5 toggle bit memory
39357 \ ******************************\
39358 \ Display IR_RC5 code           \
39359 \ ******************************\
39360 SUB #8,PSP                      \ TOS -- x x x x TOS
39361 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
39362 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
39363 MOV #$10,&BASEADR               \                                               set hexadecimal base
39364 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
39365 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
39366 LO2HI                           \                                               switch from assembler to FORTH
39367     LCD_CLEAR                   \                                               set LCD cursor at home
39368     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
39369     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
39370     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
39371     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
39372 HI2LO                           \     --                                        switch from FORTH to assembler
39373 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
39374 MOV @PSP+,TOS                   \     -- TOS
39375 RET
39376 ENDASM
39377
39378 \ ******************************\
39379 ASM BACKGROUND                  \
39380 \ ******************************\
39381 BEGIN
39382 \     ...                         \ insert here your background task
39383 \     ...                         \
39384 \     ...                         \
39385     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
39386     BIS &LPM_MODE,SR            \
39387 \ ******************************\
39388 \ here start all interrupts     \
39389 \ ******************************\
39390 \ here return all interrupts    \
39391 \ ******************************\
39392 AGAIN                           \
39393 ENDASM                          \
39394 \ ******************************\
39395
39396 \ ------------------------------\
39397 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
39398 \ ------------------------------\
39399 \     ...                         \ init specific I/O sys as you want
39400 \     ...                         \ before executing default WARM
39401     MOV #WARM,X                 \ ['] WARM 
39402     ADD #4,X                    \ >BODY
39403     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
39404 ENDASM
39405 \ ------------------------------\
39406
39407 \ ------------------------------\
39408 CODE STOP                       \ stops multitasking, must to be used before downloading app
39409 \ ------------------------------\
39410 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
39411     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
39412     MOV X,-2(X)                 \ restore the default background: SLEEP
39413     MOV #WARM,X
39414     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
39415     BIC.B #RC5,&IR_IE           \ clear RC5_Int
39416     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
39417     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
39418     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
39419     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
39420     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
39421 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
39422 ECHO                            \
39423 ." RC5toLCD is removed,"
39424 ."  type START to restart"
39425  WARM                           \ performs reset to reset all interrupt vectors.    
39426 ;
39427 \ ------------------------------\
39428
39429 \ ------------------------------\
39430 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
39431 \ ------------------------------\
39432 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
39433 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
39434 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
39435 \                           --       \ID input divider \ 10 = /4
39436 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
39437 \                                 -  \TBCLR TimerB Clear
39438 \                                  - \TBIE
39439 \                                   -\TBIFG
39440 \ -------------------------------\
39441 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
39442 \                  --                 \CM Capture Mode
39443 \                    --               \CCIS
39444 \                       -             \SCS
39445 \                        --           \CLLD
39446 \                          -          \CAP
39447 \                            ---      \OUTMOD \ 011 = set/reset
39448 \                               -     \CCIE
39449 \                                 -   \CCI
39450 \                                  -  \OUT
39451 \                                   - \COV
39452 \                                    -\CCIFG
39453 \ -------------------------------\
39454 \ LCD_TIM_CCRx                   \
39455 \ -------------------------------\
39456 \ LCD_TIM_EX0                    \ 
39457 \ ------------------------------\
39458 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
39459 \ ------------------------------\
39460 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
39461 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
39462 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
39463     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
39464 [THEN]
39465 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
39466     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
39467 [THEN]
39468     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
39469 \ ------------------------------\
39470 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
39471 \ ------------------------------\
39472 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
39473     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
39474 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
39475 \ ------------------------------\
39476     BIS.B #LCDVo,&LCDVo_DIR     \
39477     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
39478 \ ------------------------------\
39479     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
39480     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
39481 \ ------------------------------\
39482     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
39483     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
39484 \ ******************************\
39485 \ init RC5_Int                  \
39486 \ ******************************\
39487     BIS.B #RC5,&IR_IE           \ enable RC5_Int
39488     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
39489     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
39490 \ ******************************\
39491 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
39492 \ ******************************\
39493 \              %01 0001 0100    \ TAxCTL
39494 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
39495 \                  --           \ ID        divided by 1
39496 \                    --         \ MC        MODE = up to TAxCCRn
39497 \                        -      \ TACLR     clear timer count
39498 \                         -     \ TAIE
39499 \                          -    \ TAIFG
39500 \ ------------------------------\
39501 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
39502 \ ------------------------------\
39503 \                        000    \ TAxEX0
39504 \                        ---    \ TAIDEX    pre divisor
39505 \ ------------------------------\
39506 \          %0000 0000 0000 0101 \ TAxCCR0
39507     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
39508 \ ------------------------------\
39509 \          %0000 0000 0001 0000 \ TAxCCTL0
39510 \                   -           \ CAP capture/compare mode = compare
39511 \                        -      \ CCIEn
39512 \                             - \ CCIFGn
39513     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
39514 \ ------------------------------\
39515     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
39516 \ ------------------------------\
39517 \ define LPM mode for ACCEPT    \
39518 \ ------------------------------\
39519 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
39520 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
39521 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
39522 \ ------------------------------\
39523 \ activate I/O                  \
39524 \ ------------------------------\
39525 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
39526 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
39527 \ ------------------------------\
39528 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
39529 \ ------------------------------\
39530 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
39531 \ CMP #2,Y                        \ Power_ON event
39532 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
39533 CMP #4,Y                        \
39534 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
39535 \ CMP #6,Y                        \
39536 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
39537 \ CMP #$0A,Y                      \
39538 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
39539 \ CMP #$16,Y                      \
39540 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
39541 \ ------------------------------\
39542 COLON                           \
39543 \ ------------------------------\
39544 \ Init LCD 2x20                 \
39545 \ ------------------------------\
39546     #1000 20_US                 \ 1- wait 20 ms
39547     %011 TOP_LCD                \ 2- send DB5=DB4=1
39548     #205 20_US                  \ 3- wait 4,1 ms
39549     %011 TOP_LCD                \ 4- send again DB5=DB4=1
39550     #5 20_US                    \ 5- wait 0,1 ms
39551     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
39552     #2 20_US                    \    wait 40 us = LCD cycle
39553     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
39554     #2 20_US                    \    wait 40 us = LCD cycle
39555     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
39556     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
39557     LCD_CLEAR                   \ 10- "LCD_Clear"
39558     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
39559     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
39560     LCD_CLEAR                   \ 10- "LCD_Clear"
39561     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
39562     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
39563     CR ." I love you"           \ display message on LCD
39564     ['] CR >BODY IS CR          \ CR executes its default value
39565     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
39566     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
39567     PWR_STATE ABORT             \ init DP and continues with ABORT
39568 ;                               \
39569 \ ------------------------------\
39570
39571 \ ------------------------------\
39572 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
39573 \ ------------------------------\
39574 MOV #SLEEP,X                    \ replace default background process SLEEP
39575 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
39576 MOV #WARM,X                     \ replace default WARM
39577 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
39578 MOV X,PC                        \ then execute new WARM
39579 ENDCODE 
39580 \ ------------------------------\
39581
39582 ECHO
39583             ; downloading RC5toLCD.4th is done
39584 RST_HERE    ; this app is protected against <reset>
39585
39586
39587 RST_STATE
39588
39589 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
39590
39591 [UNDEFINED] MARKER [IF]
39592 \  https://forth-standard.org/standard/core/MARKER
39593 \  MARKER
39594 \ ( "<spaces>name" -- )
39595 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
39596 \ with the execution semantics defined below.
39597
39598 \ name Execution: ( -- )
39599 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
39600 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
39601 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
39602 \ not necessarily provided. No other contextual information such as numeric base is affected
39603 \
39604 : MARKER
39605 CREATE
39606 HI2LO
39607 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
39608 SUB #2,Y            \ 1 Y = LFA
39609 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
39610 ADD #4,&DP          \ 3 add 2 cells
39611 LO2HI
39612 DOES>
39613 HI2LO
39614 MOV @RSP+,IP        \ -- PFA
39615 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
39616 MOV @TOS,&INIDP     \       set DP value for RST_STATE
39617 MOV @PSP+,TOS       \ --
39618 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
39619 ENDCODE
39620 [THEN]
39621
39622 MARKER {RC5TOLCD}
39623
39624 [UNDEFINED] @ [IF]
39625 \ https://forth-standard.org/standard/core/Fetch
39626 \ @     c-addr -- char   fetch char from memory
39627 CODE @
39628 MOV @TOS,TOS
39629 MOV @IP+,PC
39630 ENDCODE
39631 [THEN]
39632
39633 [UNDEFINED] CONSTANT [IF]
39634 \ https://forth-standard.org/standard/core/CONSTANT
39635 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
39636 : CONSTANT 
39637 CREATE
39638 HI2LO
39639 MOV TOS,-2(W)           \   PFA = n
39640 MOV @PSP+,TOS
39641 MOV @RSP+,IP
39642 MOV @IP+,PC
39643 ENDCODE
39644 [THEN]
39645
39646 [UNDEFINED] STATE [IF]
39647 \ https://forth-standard.org/standard/core/STATE
39648 \ STATE   -- a-addr       holds compiler state
39649 STATEADR CONSTANT STATE
39650 [THEN]
39651
39652 [UNDEFINED] = [IF]
39653 \ https://forth-standard.org/standard/core/Equal
39654 \ =      x1 x2 -- flag         test x1=x2
39655 CODE =
39656 SUB @PSP+,TOS   \ 2
39657 0<> IF          \ 2
39658     AND #0,TOS  \ 1
39659     MOV @IP+,PC \ 4
39660 THEN
39661 XOR #-1,TOS     \ 1 flag Z = 1
39662 MOV @IP+,PC     \ 4
39663 ENDCODE
39664 [THEN]
39665
39666 [UNDEFINED] IF [IF]
39667 \ https://forth-standard.org/standard/core/IF
39668 \ IF       -- IFadr    initialize conditional forward branch
39669 CODE IF       \ immediate
39670 SUB #2,PSP              \
39671 MOV TOS,0(PSP)          \
39672 MOV &DP,TOS             \ -- HERE
39673 ADD #4,&DP            \           compile one word, reserve one word
39674 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
39675 ADD #2,TOS              \ -- HERE+2=IFadr
39676 MOV @IP+,PC
39677 ENDCODE IMMEDIATE
39678 [THEN]
39679
39680 [UNDEFINED] THEN [IF]
39681 \ https://forth-standard.org/standard/core/THEN
39682 \ THEN     IFadr --                resolve forward branch
39683 CODE THEN               \ immediate
39684 MOV &DP,0(TOS)          \ -- IFadr
39685 MOV @PSP+,TOS           \ --
39686 MOV @IP+,PC
39687 ENDCODE IMMEDIATE
39688 [THEN]
39689
39690 [UNDEFINED] ELSE [IF]
39691 \ https://forth-standard.org/standard/core/ELSE
39692 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
39693 CODE ELSE     \ immediate
39694 ADD #4,&DP              \ make room to compile two words
39695 MOV &DP,W               \ W=HERE+4
39696 MOV #BRAN,-4(W)
39697 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
39698 SUB #2,W                \ HERE+2
39699 MOV W,TOS               \ -- ELSEadr
39700 MOV @IP+,PC
39701 ENDCODE IMMEDIATE
39702 [THEN]
39703
39704 [UNDEFINED] DEFER [IF]
39705 \ https://forth-standard.org/standard/core/DEFER
39706 \ DEFER "<spaces>name"   --
39707 \ Skip leading space delimiters. Parse name delimited by a space.
39708 \ Create a definition for name with the execution semantics defined below.
39709
39710 \ name Execution:   --
39711 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
39712 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
39713 : DEFER
39714 CREATE
39715 HI2LO
39716 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
39717 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
39718 MOV @RSP+,IP
39719 MOV @IP+,PC
39720 ENDCODE
39721 [THEN]
39722
39723 [UNDEFINED] DEFER! [IF]
39724 \ https://forth-standard.org/standard/core/DEFERStore
39725 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
39726 CODE DEFER!             \ xt2 xt1 --
39727 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
39728 MOV @PSP+,TOS           \ --
39729 MOV @IP+,PC
39730 ENDCODE
39731 [THEN]
39732
39733 [UNDEFINED] IS [IF]
39734 \ https://forth-standard.org/standard/core/IS
39735 \ IS <name>        xt --
39736 \ used as is :
39737 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
39738 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
39739 \ or in a definition : ... ['] U. IS DISPLAY ...
39740 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
39741 \
39742 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
39743 : IS
39744 STATE @
39745 IF  POSTPONE ['] POSTPONE DEFER! 
39746 ELSE ' DEFER! 
39747 THEN
39748 ; IMMEDIATE
39749 [THEN]
39750
39751 [UNDEFINED] >BODY [IF]
39752 \ https://forth-standard.org/standard/core/toBODY
39753 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
39754 CODE >BODY
39755 ADD #4,TOS
39756 MOV @IP+,PC
39757 ENDCODE
39758 [THEN]
39759
39760 \ CODE 20uS           \ n --      8MHz version
39761 \ BEGIN               \ 4 + 16 ~ loop
39762 \     MOV #39,rDOCON   \ 39
39763 \     BEGIN           \ 4 ~ loop
39764 \         NOP
39765 \         SUB #1,rDOCON
39766 \     0=  UNTIL
39767 \     SUB #1,TOS      \ 1
39768 \ 0= UNTIL
39769 \ MOV #XDOCON,rDOCON  \ 2
39770 \ MOV @PSP+,TOS
39771 \ MOV @RSP+,IP        \
39772 \ ENDCODE
39773
39774 CODE 20_US                      \ n --      n * 20 us
39775 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
39776     BEGIN
39777         BIT #1,&LCD_TIM_CTL     \ 3
39778     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
39779     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
39780     SUB #1,TOS                  \ 1
39781 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
39782 MOV @PSP+,TOS                   \ 2
39783 MOV @IP+,PC                     \ 4
39784 ENDCODE
39785
39786 CODE TOP_LCD                    \ LCD Sample
39787 \                               \ if write : %xxxx_WWWW --
39788 \                               \ if read  : -- %0000_RRRR
39789     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
39790     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
39791 0= IF                           \ write LCD bits pattern
39792     AND.B #LCD_DB,TOS           \ 
39793     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
39794     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
39795     MOV @PSP+,TOS               \
39796     MOV @IP+,PC
39797 THEN                            \ read LCD bits pattern
39798     SUB #2,PSP
39799     MOV TOS,0(PSP)
39800     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
39801     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
39802     AND.B #LCD_DB,TOS           \
39803     MOV @IP+,PC
39804 ENDCODE
39805
39806 CODE LCD_WRC                    \ char --         Write Char
39807     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
39808 BW1 SUB #2,PSP                  \
39809     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
39810     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
39811     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
39812     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
39813 COLON                           \ high level word starts here 
39814     TOP_LCD 2 20_US             \ write high nibble first
39815     TOP_LCD 2 20_US 
39816 ;
39817
39818 CODE LCD_WRF                    \ func --         Write Fonction
39819     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
39820     GOTO BW1
39821 ENDCODE
39822
39823 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
39824 : LCD_HOME $02 LCD_WRF 100 20_us ;
39825
39826 \ [UNDEFINED] OR [IF]
39827
39828 \ \ https://forth-standard.org/standard/core/OR
39829 \ \ C OR     x1 x2 -- x3           logical OR
39830 \ CODE OR
39831 \ BIS @PSP+,TOS
39832 \ MOV @IP+,PC
39833 \ ENDCODE
39834
39835 \ [THEN]
39836
39837 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
39838 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
39839 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
39840 \ : LCD_FN_SET        $20 OR LCD_WrF ;
39841 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
39842 \ : LCD_GOTO          $80 OR LCD_WrF ;
39843
39844
39845 \ CODE LCD_RDS                    \ -- status       Read Status
39846 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
39847 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
39848 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
39849 \ COLON                           \ starts a FORTH word
39850 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
39851 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
39852 \ HI2LO                           \ switch from FORTH to assembler
39853 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
39854 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
39855 \     MOV @RSP+,IP                \ restore IP saved by COLON
39856 \     MOV @IP+,PC                 \
39857 \ ENDCODE
39858
39859 \ CODE LCD_RDC                    \ -- char         Read Char
39860 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
39861 \     GOTO BW1
39862 \ ENDCODE
39863
39864
39865 \ ******************************\
39866 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
39867 \ ******************************\
39868 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
39869 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
39870 BIT.B #SW2,&SW2_IN              \ test switch S2
39871 0= IF                           \ case of switch S2 pressed
39872     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
39873     U< IF
39874         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
39875     THEN
39876 ELSE
39877     BIT.B #SW1,&SW1_IN          \ test switch S1 input
39878     0= IF                       \ case of Switch S1 pressed
39879         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
39880         U>= IF                  \
39881            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
39882         THEN                    \
39883     THEN                        \
39884 THEN                            \
39885 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
39886 RET                             \ 5
39887 ENDASM
39888
39889 \ ******************************\
39890 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
39891 \ ******************************\
39892 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
39893 \ ******************************\
39894 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
39895 \                               \       SMclock = 8|16|24 MHz
39896 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
39897 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
39898 \                               \       SR(9)=new Toggle bit memory (ADD on)
39899 \ ******************************\
39900 \ RC5_FirstStartBitHalfCycle:   \
39901 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
39902 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
39903 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
39904 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
39905 \ [THEN]
39906 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
39907     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
39908 [THEN]
39909 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
39910     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
39911 [THEN]
39912 MOV #1778,X                     \ RC5_Period * 1us
39913 MOV #14,W                       \ count of loop
39914 BEGIN                           \
39915 \ ******************************\
39916 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
39917 \ ******************************\                   |
39918 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
39919 \ RC5_Compute_3/4_Period:       \                   |
39920     RRUM    #1,X                \ X=1/2 cycle       |
39921     MOV     X,Y                 \                   ^
39922     RRUM    #1,Y                \ Y=1/4
39923     ADD     X,Y                 \ Y=3/4 cycle
39924     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
39925     U>= UNTIL                   \ 2
39926 \ ******************************\
39927 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
39928 \ ******************************\
39929     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
39930     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
39931     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
39932     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
39933     SUB     #1,W                \ decrement count loop
39934 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
39935 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
39936 0<> WHILE                       \ ----> out of loop ----+
39937     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
39938     BEGIN                       \                       |
39939         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
39940         CMP Y,X                 \ 1                     |   cycle time out of bound ?
39941         U>= IF                  \ 2                 ^   |   yes:
39942         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
39943         GOTO BW1                \                   |   |      quit on truncated RC5 message
39944         THEN                    \                   |   |
39945         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
39946     0<> UNTIL                   \ 2                 |   |
39947 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
39948 \ ******************************\                       |
39949 \ RC5_SampleEndOf:              \ <---------------------+
39950 \ ******************************\
39951 BIC #$30,&RC5_TIM_CTL           \   stop timer
39952 \ ******************************\
39953 \ RC5_ComputeNewRC5word         \
39954 \ ******************************\
39955 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
39956 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
39957 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
39958 \ ******************************\
39959 \ RC5_ComputeC6bit              \
39960 \ ******************************\
39961 BIT     #BIT14,T                \ test /C6 bit in T
39962 0= IF   BIS #BIT6,X             \ set C6 bit in X
39963 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
39964 \ ******************************\
39965 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
39966 \ ******************************\
39967 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
39968 \ ******************************\
39969 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
39970 XOR     @RSP,T                  \ (new XOR old) Toggle bits
39971 BIT     #UF10,T                 \ repeated RC5_command ?
39972 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
39973 XOR #UF10,0(RSP)                \ 5 toggle bit memory
39974 \ ******************************\
39975 \ Display IR_RC5 code           \
39976 \ ******************************\
39977 SUB #8,PSP                      \ TOS -- x x x x TOS
39978 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
39979 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
39980 MOV #$10,&BASEADR               \                                               set hexadecimal base
39981 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
39982 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
39983 LO2HI                           \                                               switch from assembler to FORTH
39984     LCD_CLEAR                   \                                               set LCD cursor at home
39985     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
39986     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
39987     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
39988     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
39989 HI2LO                           \     --                                        switch from FORTH to assembler
39990 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
39991 MOV @PSP+,TOS                   \     -- TOS
39992 RET
39993 ENDASM
39994
39995 \ ******************************\
39996 ASM BACKGROUND                  \
39997 \ ******************************\
39998 BEGIN
39999 \     ...                         \ insert here your background task
40000 \     ...                         \
40001 \     ...                         \
40002     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
40003     BIS &LPM_MODE,SR            \
40004 \ ******************************\
40005 \ here start all interrupts     \
40006 \ ******************************\
40007 \ here return all interrupts    \
40008 \ ******************************\
40009 AGAIN                           \
40010 ENDASM                          \
40011 \ ******************************\
40012
40013 \ ------------------------------\
40014 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
40015 \ ------------------------------\
40016 \     ...                         \ init specific I/O sys as you want
40017 \     ...                         \ before executing default WARM
40018     MOV #WARM,X                 \ ['] WARM 
40019     ADD #4,X                    \ >BODY
40020     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
40021 ENDASM
40022 \ ------------------------------\
40023
40024 \ ------------------------------\
40025 CODE STOP                       \ stops multitasking, must to be used before downloading app
40026 \ ------------------------------\
40027 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
40028     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
40029     MOV X,-2(X)                 \ restore the default background: SLEEP
40030     MOV #WARM,X
40031     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
40032     BIC.B #RC5,&IR_IE           \ clear RC5_Int
40033     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
40034     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
40035     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
40036     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
40037     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
40038 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
40039 ECHO                            \
40040 ." RC5toLCD is removed,"
40041 ."  type START to restart"
40042  WARM                           \ performs reset to reset all interrupt vectors.    
40043 ;
40044 \ ------------------------------\
40045
40046 \ ------------------------------\
40047 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
40048 \ ------------------------------\
40049 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
40050 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
40051 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
40052 \                           --       \ID input divider \ 10 = /4
40053 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
40054 \                                 -  \TBCLR TimerB Clear
40055 \                                  - \TBIE
40056 \                                   -\TBIFG
40057 \ -------------------------------\
40058 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
40059 \                  --                 \CM Capture Mode
40060 \                    --               \CCIS
40061 \                       -             \SCS
40062 \                        --           \CLLD
40063 \                          -          \CAP
40064 \                            ---      \OUTMOD \ 011 = set/reset
40065 \                               -     \CCIE
40066 \                                 -   \CCI
40067 \                                  -  \OUT
40068 \                                   - \COV
40069 \                                    -\CCIFG
40070 \ -------------------------------\
40071 \ LCD_TIM_CCRx                   \
40072 \ -------------------------------\
40073 \ LCD_TIM_EX0                    \ 
40074 \ ------------------------------\
40075 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
40076 \ ------------------------------\
40077 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
40078 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
40079 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
40080     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
40081 [THEN]
40082 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
40083     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
40084 [THEN]
40085     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
40086 \ ------------------------------\
40087 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
40088 \ ------------------------------\
40089 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
40090     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
40091 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
40092 \ ------------------------------\
40093     BIS.B #LCDVo,&LCDVo_DIR     \
40094     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
40095 \ ------------------------------\
40096     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
40097     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
40098 \ ------------------------------\
40099     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
40100     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
40101 \ ******************************\
40102 \ init RC5_Int                  \
40103 \ ******************************\
40104     BIS.B #RC5,&IR_IE           \ enable RC5_Int
40105     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
40106     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
40107 \ ******************************\
40108 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
40109 \ ******************************\
40110 \              %01 0001 0100    \ TAxCTL
40111 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
40112 \                  --           \ ID        divided by 1
40113 \                    --         \ MC        MODE = up to TAxCCRn
40114 \                        -      \ TACLR     clear timer count
40115 \                         -     \ TAIE
40116 \                          -    \ TAIFG
40117 \ ------------------------------\
40118 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
40119 \ ------------------------------\
40120 \                        000    \ TAxEX0
40121 \                        ---    \ TAIDEX    pre divisor
40122 \ ------------------------------\
40123 \          %0000 0000 0000 0101 \ TAxCCR0
40124     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
40125 \ ------------------------------\
40126 \          %0000 0000 0001 0000 \ TAxCCTL0
40127 \                   -           \ CAP capture/compare mode = compare
40128 \                        -      \ CCIEn
40129 \                             - \ CCIFGn
40130     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
40131 \ ------------------------------\
40132     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
40133 \ ------------------------------\
40134 \ define LPM mode for ACCEPT    \
40135 \ ------------------------------\
40136 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
40137 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
40138 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
40139 \ ------------------------------\
40140 \ activate I/O                  \
40141 \ ------------------------------\
40142 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
40143 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
40144 \ ------------------------------\
40145 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
40146 \ ------------------------------\
40147 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
40148 \ CMP #2,Y                        \ Power_ON event
40149 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
40150 CMP #4,Y                        \
40151 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
40152 \ CMP #6,Y                        \
40153 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
40154 \ CMP #$0A,Y                      \
40155 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
40156 \ CMP #$16,Y                      \
40157 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
40158 \ ------------------------------\
40159 COLON                           \
40160 \ ------------------------------\
40161 \ Init LCD 2x20                 \
40162 \ ------------------------------\
40163     #1000 20_US                 \ 1- wait 20 ms
40164     %011 TOP_LCD                \ 2- send DB5=DB4=1
40165     #205 20_US                  \ 3- wait 4,1 ms
40166     %011 TOP_LCD                \ 4- send again DB5=DB4=1
40167     #5 20_US                    \ 5- wait 0,1 ms
40168     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
40169     #2 20_US                    \    wait 40 us = LCD cycle
40170     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
40171     #2 20_US                    \    wait 40 us = LCD cycle
40172     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
40173     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
40174     LCD_CLEAR                   \ 10- "LCD_Clear"
40175     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
40176     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
40177     LCD_CLEAR                   \ 10- "LCD_Clear"
40178     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
40179     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
40180     CR ." I love you"           \ display message on LCD
40181     ['] CR >BODY IS CR          \ CR executes its default value
40182     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
40183     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
40184     PWR_STATE ABORT             \ init DP and continues with ABORT
40185 ;                               \
40186 \ ------------------------------\
40187
40188 \ ------------------------------\
40189 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
40190 \ ------------------------------\
40191 MOV #SLEEP,X                    \ replace default background process SLEEP
40192 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
40193 MOV #WARM,X                     \ replace default WARM
40194 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
40195 MOV X,PC                        \ then execute new WARM
40196 ENDCODE 
40197 \ ------------------------------\
40198
40199 ECHO
40200             ; downloading RC5toLCD.4th is done
40201 RST_HERE    ; this app is protected against <reset>
40202
40203
40204 RST_STATE
40205
40206 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
40207
40208 [UNDEFINED] MARKER [IF]
40209 \  https://forth-standard.org/standard/core/MARKER
40210 \  MARKER
40211 \ ( "<spaces>name" -- )
40212 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
40213 \ with the execution semantics defined below.
40214
40215 \ name Execution: ( -- )
40216 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
40217 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
40218 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
40219 \ not necessarily provided. No other contextual information such as numeric base is affected
40220 \
40221 : MARKER
40222 CREATE
40223 HI2LO
40224 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
40225 SUB #2,Y            \ 1 Y = LFA
40226 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
40227 ADD #4,&DP          \ 3 add 2 cells
40228 LO2HI
40229 DOES>
40230 HI2LO
40231 MOV @RSP+,IP        \ -- PFA
40232 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
40233 MOV @TOS,&INIDP     \       set DP value for RST_STATE
40234 MOV @PSP+,TOS       \ --
40235 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
40236 ENDCODE
40237 [THEN]
40238
40239 MARKER {RC5TOLCD}
40240
40241 [UNDEFINED] @ [IF]
40242 \ https://forth-standard.org/standard/core/Fetch
40243 \ @     c-addr -- char   fetch char from memory
40244 CODE @
40245 MOV @TOS,TOS
40246 MOV @IP+,PC
40247 ENDCODE
40248 [THEN]
40249
40250 [UNDEFINED] CONSTANT [IF]
40251 \ https://forth-standard.org/standard/core/CONSTANT
40252 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
40253 : CONSTANT 
40254 CREATE
40255 HI2LO
40256 MOV TOS,-2(W)           \   PFA = n
40257 MOV @PSP+,TOS
40258 MOV @RSP+,IP
40259 MOV @IP+,PC
40260 ENDCODE
40261 [THEN]
40262
40263 [UNDEFINED] STATE [IF]
40264 \ https://forth-standard.org/standard/core/STATE
40265 \ STATE   -- a-addr       holds compiler state
40266 STATEADR CONSTANT STATE
40267 [THEN]
40268
40269 [UNDEFINED] = [IF]
40270 \ https://forth-standard.org/standard/core/Equal
40271 \ =      x1 x2 -- flag         test x1=x2
40272 CODE =
40273 SUB @PSP+,TOS   \ 2
40274 0<> IF          \ 2
40275     AND #0,TOS  \ 1
40276     MOV @IP+,PC \ 4
40277 THEN
40278 XOR #-1,TOS     \ 1 flag Z = 1
40279 MOV @IP+,PC     \ 4
40280 ENDCODE
40281 [THEN]
40282
40283 [UNDEFINED] IF [IF]
40284 \ https://forth-standard.org/standard/core/IF
40285 \ IF       -- IFadr    initialize conditional forward branch
40286 CODE IF       \ immediate
40287 SUB #2,PSP              \
40288 MOV TOS,0(PSP)          \
40289 MOV &DP,TOS             \ -- HERE
40290 ADD #4,&DP            \           compile one word, reserve one word
40291 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
40292 ADD #2,TOS              \ -- HERE+2=IFadr
40293 MOV @IP+,PC
40294 ENDCODE IMMEDIATE
40295 [THEN]
40296
40297 [UNDEFINED] THEN [IF]
40298 \ https://forth-standard.org/standard/core/THEN
40299 \ THEN     IFadr --                resolve forward branch
40300 CODE THEN               \ immediate
40301 MOV &DP,0(TOS)          \ -- IFadr
40302 MOV @PSP+,TOS           \ --
40303 MOV @IP+,PC
40304 ENDCODE IMMEDIATE
40305 [THEN]
40306
40307 [UNDEFINED] ELSE [IF]
40308 \ https://forth-standard.org/standard/core/ELSE
40309 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
40310 CODE ELSE     \ immediate
40311 ADD #4,&DP              \ make room to compile two words
40312 MOV &DP,W               \ W=HERE+4
40313 MOV #BRAN,-4(W)
40314 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
40315 SUB #2,W                \ HERE+2
40316 MOV W,TOS               \ -- ELSEadr
40317 MOV @IP+,PC
40318 ENDCODE IMMEDIATE
40319 [THEN]
40320
40321 [UNDEFINED] DEFER [IF]
40322 \ https://forth-standard.org/standard/core/DEFER
40323 \ DEFER "<spaces>name"   --
40324 \ Skip leading space delimiters. Parse name delimited by a space.
40325 \ Create a definition for name with the execution semantics defined below.
40326
40327 \ name Execution:   --
40328 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
40329 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
40330 : DEFER
40331 CREATE
40332 HI2LO
40333 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
40334 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
40335 MOV @RSP+,IP
40336 MOV @IP+,PC
40337 ENDCODE
40338 [THEN]
40339
40340 [UNDEFINED] DEFER! [IF]
40341 \ https://forth-standard.org/standard/core/DEFERStore
40342 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
40343 CODE DEFER!             \ xt2 xt1 --
40344 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
40345 MOV @PSP+,TOS           \ --
40346 MOV @IP+,PC
40347 ENDCODE
40348 [THEN]
40349
40350 [UNDEFINED] IS [IF]
40351 \ https://forth-standard.org/standard/core/IS
40352 \ IS <name>        xt --
40353 \ used as is :
40354 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
40355 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
40356 \ or in a definition : ... ['] U. IS DISPLAY ...
40357 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
40358 \
40359 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
40360 : IS
40361 STATE @
40362 IF  POSTPONE ['] POSTPONE DEFER! 
40363 ELSE ' DEFER! 
40364 THEN
40365 ; IMMEDIATE
40366 [THEN]
40367
40368 [UNDEFINED] >BODY [IF]
40369 \ https://forth-standard.org/standard/core/toBODY
40370 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
40371 CODE >BODY
40372 ADD #4,TOS
40373 MOV @IP+,PC
40374 ENDCODE
40375 [THEN]
40376
40377 \ CODE 20uS           \ n --      8MHz version
40378 \ BEGIN               \ 4 + 16 ~ loop
40379 \     MOV #39,rDOCON   \ 39
40380 \     BEGIN           \ 4 ~ loop
40381 \         NOP
40382 \         SUB #1,rDOCON
40383 \     0=  UNTIL
40384 \     SUB #1,TOS      \ 1
40385 \ 0= UNTIL
40386 \ MOV #XDOCON,rDOCON  \ 2
40387 \ MOV @PSP+,TOS
40388 \ MOV @RSP+,IP        \
40389 \ ENDCODE
40390
40391 CODE 20_US                      \ n --      n * 20 us
40392 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
40393     BEGIN
40394         BIT #1,&LCD_TIM_CTL     \ 3
40395     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
40396     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
40397     SUB #1,TOS                  \ 1
40398 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
40399 MOV @PSP+,TOS                   \ 2
40400 MOV @IP+,PC                     \ 4
40401 ENDCODE
40402
40403 CODE TOP_LCD                    \ LCD Sample
40404 \                               \ if write : %xxxx_WWWW --
40405 \                               \ if read  : -- %0000_RRRR
40406     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
40407     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
40408 0= IF                           \ write LCD bits pattern
40409     AND.B #LCD_DB,TOS           \ 
40410     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
40411     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
40412     MOV @PSP+,TOS               \
40413     MOV @IP+,PC
40414 THEN                            \ read LCD bits pattern
40415     SUB #2,PSP
40416     MOV TOS,0(PSP)
40417     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
40418     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
40419     AND.B #LCD_DB,TOS           \
40420     MOV @IP+,PC
40421 ENDCODE
40422
40423 CODE LCD_WRC                    \ char --         Write Char
40424     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
40425 BW1 SUB #2,PSP                  \
40426     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
40427     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
40428     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
40429     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
40430 COLON                           \ high level word starts here 
40431     TOP_LCD 2 20_US             \ write high nibble first
40432     TOP_LCD 2 20_US 
40433 ;
40434
40435 CODE LCD_WRF                    \ func --         Write Fonction
40436     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
40437     GOTO BW1
40438 ENDCODE
40439
40440 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
40441 : LCD_HOME $02 LCD_WRF 100 20_us ;
40442
40443 \ [UNDEFINED] OR [IF]
40444
40445 \ \ https://forth-standard.org/standard/core/OR
40446 \ \ C OR     x1 x2 -- x3           logical OR
40447 \ CODE OR
40448 \ BIS @PSP+,TOS
40449 \ MOV @IP+,PC
40450 \ ENDCODE
40451
40452 \ [THEN]
40453
40454 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
40455 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
40456 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
40457 \ : LCD_FN_SET        $20 OR LCD_WrF ;
40458 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
40459 \ : LCD_GOTO          $80 OR LCD_WrF ;
40460
40461
40462 \ CODE LCD_RDS                    \ -- status       Read Status
40463 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
40464 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
40465 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
40466 \ COLON                           \ starts a FORTH word
40467 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
40468 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
40469 \ HI2LO                           \ switch from FORTH to assembler
40470 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
40471 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
40472 \     MOV @RSP+,IP                \ restore IP saved by COLON
40473 \     MOV @IP+,PC                 \
40474 \ ENDCODE
40475
40476 \ CODE LCD_RDC                    \ -- char         Read Char
40477 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
40478 \     GOTO BW1
40479 \ ENDCODE
40480
40481
40482 \ ******************************\
40483 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
40484 \ ******************************\
40485 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
40486 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
40487 BIT.B #SW2,&SW2_IN              \ test switch S2
40488 0= IF                           \ case of switch S2 pressed
40489     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
40490     U< IF
40491         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
40492     THEN
40493 ELSE
40494     BIT.B #SW1,&SW1_IN          \ test switch S1 input
40495     0= IF                       \ case of Switch S1 pressed
40496         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
40497         U>= IF                  \
40498            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
40499         THEN                    \
40500     THEN                        \
40501 THEN                            \
40502 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
40503 RET                             \ 5
40504 ENDASM
40505
40506 \ ******************************\
40507 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
40508 \ ******************************\
40509 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
40510 \ ******************************\
40511 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
40512 \                               \       SMclock = 8|16|24 MHz
40513 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
40514 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
40515 \                               \       SR(9)=new Toggle bit memory (ADD on)
40516 \ ******************************\
40517 \ RC5_FirstStartBitHalfCycle:   \
40518 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
40519 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
40520 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
40521 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
40522 \ [THEN]
40523 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
40524     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
40525 [THEN]
40526 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
40527     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
40528 [THEN]
40529 MOV #1778,X                     \ RC5_Period * 1us
40530 MOV #14,W                       \ count of loop
40531 BEGIN                           \
40532 \ ******************************\
40533 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
40534 \ ******************************\                   |
40535 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
40536 \ RC5_Compute_3/4_Period:       \                   |
40537     RRUM    #1,X                \ X=1/2 cycle       |
40538     MOV     X,Y                 \                   ^
40539     RRUM    #1,Y                \ Y=1/4
40540     ADD     X,Y                 \ Y=3/4 cycle
40541     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
40542     U>= UNTIL                   \ 2
40543 \ ******************************\
40544 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
40545 \ ******************************\
40546     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
40547     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
40548     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
40549     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
40550     SUB     #1,W                \ decrement count loop
40551 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
40552 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
40553 0<> WHILE                       \ ----> out of loop ----+
40554     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
40555     BEGIN                       \                       |
40556         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
40557         CMP Y,X                 \ 1                     |   cycle time out of bound ?
40558         U>= IF                  \ 2                 ^   |   yes:
40559         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
40560         GOTO BW1                \                   |   |      quit on truncated RC5 message
40561         THEN                    \                   |   |
40562         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
40563     0<> UNTIL                   \ 2                 |   |
40564 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
40565 \ ******************************\                       |
40566 \ RC5_SampleEndOf:              \ <---------------------+
40567 \ ******************************\
40568 BIC #$30,&RC5_TIM_CTL           \   stop timer
40569 \ ******************************\
40570 \ RC5_ComputeNewRC5word         \
40571 \ ******************************\
40572 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
40573 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
40574 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
40575 \ ******************************\
40576 \ RC5_ComputeC6bit              \
40577 \ ******************************\
40578 BIT     #BIT14,T                \ test /C6 bit in T
40579 0= IF   BIS #BIT6,X             \ set C6 bit in X
40580 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
40581 \ ******************************\
40582 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
40583 \ ******************************\
40584 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
40585 \ ******************************\
40586 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
40587 XOR     @RSP,T                  \ (new XOR old) Toggle bits
40588 BIT     #UF10,T                 \ repeated RC5_command ?
40589 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
40590 XOR #UF10,0(RSP)                \ 5 toggle bit memory
40591 \ ******************************\
40592 \ Display IR_RC5 code           \
40593 \ ******************************\
40594 SUB #8,PSP                      \ TOS -- x x x x TOS
40595 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
40596 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
40597 MOV #$10,&BASEADR               \                                               set hexadecimal base
40598 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
40599 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
40600 LO2HI                           \                                               switch from assembler to FORTH
40601     LCD_CLEAR                   \                                               set LCD cursor at home
40602     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
40603     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
40604     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
40605     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
40606 HI2LO                           \     --                                        switch from FORTH to assembler
40607 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
40608 MOV @PSP+,TOS                   \     -- TOS
40609 RET
40610 ENDASM
40611
40612 \ ******************************\
40613 ASM BACKGROUND                  \
40614 \ ******************************\
40615 BEGIN
40616 \     ...                         \ insert here your background task
40617 \     ...                         \
40618 \     ...                         \
40619     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
40620     BIS &LPM_MODE,SR            \
40621 \ ******************************\
40622 \ here start all interrupts     \
40623 \ ******************************\
40624 \ here return all interrupts    \
40625 \ ******************************\
40626 AGAIN                           \
40627 ENDASM                          \
40628 \ ******************************\
40629
40630 \ ------------------------------\
40631 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
40632 \ ------------------------------\
40633 \     ...                         \ init specific I/O sys as you want
40634 \     ...                         \ before executing default WARM
40635     MOV #WARM,X                 \ ['] WARM 
40636     ADD #4,X                    \ >BODY
40637     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
40638 ENDASM
40639 \ ------------------------------\
40640
40641 \ ------------------------------\
40642 CODE STOP                       \ stops multitasking, must to be used before downloading app
40643 \ ------------------------------\
40644 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
40645     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
40646     MOV X,-2(X)                 \ restore the default background: SLEEP
40647     MOV #WARM,X
40648     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
40649     BIC.B #RC5,&IR_IE           \ clear RC5_Int
40650     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
40651     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
40652     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
40653     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
40654     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
40655 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
40656 ECHO                            \
40657 ." RC5toLCD is removed,"
40658 ."  type START to restart"
40659  WARM                           \ performs reset to reset all interrupt vectors.    
40660 ;
40661 \ ------------------------------\
40662
40663 \ ------------------------------\
40664 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
40665 \ ------------------------------\
40666 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
40667 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
40668 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
40669 \                           --       \ID input divider \ 10 = /4
40670 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
40671 \                                 -  \TBCLR TimerB Clear
40672 \                                  - \TBIE
40673 \                                   -\TBIFG
40674 \ -------------------------------\
40675 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
40676 \                  --                 \CM Capture Mode
40677 \                    --               \CCIS
40678 \                       -             \SCS
40679 \                        --           \CLLD
40680 \                          -          \CAP
40681 \                            ---      \OUTMOD \ 011 = set/reset
40682 \                               -     \CCIE
40683 \                                 -   \CCI
40684 \                                  -  \OUT
40685 \                                   - \COV
40686 \                                    -\CCIFG
40687 \ -------------------------------\
40688 \ LCD_TIM_CCRx                   \
40689 \ -------------------------------\
40690 \ LCD_TIM_EX0                    \ 
40691 \ ------------------------------\
40692 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
40693 \ ------------------------------\
40694 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
40695 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
40696 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
40697     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
40698 [THEN]
40699 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
40700     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
40701 [THEN]
40702     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
40703 \ ------------------------------\
40704 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
40705 \ ------------------------------\
40706 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
40707     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
40708 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
40709 \ ------------------------------\
40710     BIS.B #LCDVo,&LCDVo_DIR     \
40711     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
40712 \ ------------------------------\
40713     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
40714     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
40715 \ ------------------------------\
40716     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
40717     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
40718 \ ******************************\
40719 \ init RC5_Int                  \
40720 \ ******************************\
40721     BIS.B #RC5,&IR_IE           \ enable RC5_Int
40722     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
40723     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
40724 \ ******************************\
40725 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
40726 \ ******************************\
40727 \              %01 0001 0100    \ TAxCTL
40728 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
40729 \                  --           \ ID        divided by 1
40730 \                    --         \ MC        MODE = up to TAxCCRn
40731 \                        -      \ TACLR     clear timer count
40732 \                         -     \ TAIE
40733 \                          -    \ TAIFG
40734 \ ------------------------------\
40735 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
40736 \ ------------------------------\
40737 \                        000    \ TAxEX0
40738 \                        ---    \ TAIDEX    pre divisor
40739 \ ------------------------------\
40740 \          %0000 0000 0000 0101 \ TAxCCR0
40741     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
40742 \ ------------------------------\
40743 \          %0000 0000 0001 0000 \ TAxCCTL0
40744 \                   -           \ CAP capture/compare mode = compare
40745 \                        -      \ CCIEn
40746 \                             - \ CCIFGn
40747     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
40748 \ ------------------------------\
40749     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
40750 \ ------------------------------\
40751 \ define LPM mode for ACCEPT    \
40752 \ ------------------------------\
40753 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
40754 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
40755 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
40756 \ ------------------------------\
40757 \ activate I/O                  \
40758 \ ------------------------------\
40759 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
40760 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
40761 \ ------------------------------\
40762 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
40763 \ ------------------------------\
40764 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
40765 \ CMP #2,Y                        \ Power_ON event
40766 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
40767 CMP #4,Y                        \
40768 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
40769 \ CMP #6,Y                        \
40770 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
40771 \ CMP #$0A,Y                      \
40772 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
40773 \ CMP #$16,Y                      \
40774 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
40775 \ ------------------------------\
40776 COLON                           \
40777 \ ------------------------------\
40778 \ Init LCD 2x20                 \
40779 \ ------------------------------\
40780     #1000 20_US                 \ 1- wait 20 ms
40781     %011 TOP_LCD                \ 2- send DB5=DB4=1
40782     #205 20_US                  \ 3- wait 4,1 ms
40783     %011 TOP_LCD                \ 4- send again DB5=DB4=1
40784     #5 20_US                    \ 5- wait 0,1 ms
40785     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
40786     #2 20_US                    \    wait 40 us = LCD cycle
40787     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
40788     #2 20_US                    \    wait 40 us = LCD cycle
40789     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
40790     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
40791     LCD_CLEAR                   \ 10- "LCD_Clear"
40792     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
40793     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
40794     LCD_CLEAR                   \ 10- "LCD_Clear"
40795     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
40796     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
40797     CR ." I love you"           \ display message on LCD
40798     ['] CR >BODY IS CR          \ CR executes its default value
40799     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
40800     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
40801     PWR_STATE ABORT             \ init DP and continues with ABORT
40802 ;                               \
40803 \ ------------------------------\
40804
40805 \ ------------------------------\
40806 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
40807 \ ------------------------------\
40808 MOV #SLEEP,X                    \ replace default background process SLEEP
40809 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
40810 MOV #WARM,X                     \ replace default WARM
40811 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
40812 MOV X,PC                        \ then execute new WARM
40813 ENDCODE 
40814 \ ------------------------------\
40815
40816 ECHO
40817             ; downloading RC5toLCD.4th is done
40818 RST_HERE    ; this app is protected against <reset>
40819
40820
40821 RST_STATE
40822
40823 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
40824
40825 [UNDEFINED] MARKER [IF]
40826 \  https://forth-standard.org/standard/core/MARKER
40827 \  MARKER
40828 \ ( "<spaces>name" -- )
40829 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
40830 \ with the execution semantics defined below.
40831
40832 \ name Execution: ( -- )
40833 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
40834 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
40835 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
40836 \ not necessarily provided. No other contextual information such as numeric base is affected
40837 \
40838 : MARKER
40839 CREATE
40840 HI2LO
40841 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
40842 SUB #2,Y            \ 1 Y = LFA
40843 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
40844 ADD #4,&DP          \ 3 add 2 cells
40845 LO2HI
40846 DOES>
40847 HI2LO
40848 MOV @RSP+,IP        \ -- PFA
40849 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
40850 MOV @TOS,&INIDP     \       set DP value for RST_STATE
40851 MOV @PSP+,TOS       \ --
40852 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
40853 ENDCODE
40854 [THEN]
40855
40856 MARKER {RC5TOLCD}
40857
40858 [UNDEFINED] @ [IF]
40859 \ https://forth-standard.org/standard/core/Fetch
40860 \ @     c-addr -- char   fetch char from memory
40861 CODE @
40862 MOV @TOS,TOS
40863 MOV @IP+,PC
40864 ENDCODE
40865 [THEN]
40866
40867 [UNDEFINED] CONSTANT [IF]
40868 \ https://forth-standard.org/standard/core/CONSTANT
40869 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
40870 : CONSTANT 
40871 CREATE
40872 HI2LO
40873 MOV TOS,-2(W)           \   PFA = n
40874 MOV @PSP+,TOS
40875 MOV @RSP+,IP
40876 MOV @IP+,PC
40877 ENDCODE
40878 [THEN]
40879
40880 [UNDEFINED] STATE [IF]
40881 \ https://forth-standard.org/standard/core/STATE
40882 \ STATE   -- a-addr       holds compiler state
40883 STATEADR CONSTANT STATE
40884 [THEN]
40885
40886 [UNDEFINED] = [IF]
40887 \ https://forth-standard.org/standard/core/Equal
40888 \ =      x1 x2 -- flag         test x1=x2
40889 CODE =
40890 SUB @PSP+,TOS   \ 2
40891 0<> IF          \ 2
40892     AND #0,TOS  \ 1
40893     MOV @IP+,PC \ 4
40894 THEN
40895 XOR #-1,TOS     \ 1 flag Z = 1
40896 MOV @IP+,PC     \ 4
40897 ENDCODE
40898 [THEN]
40899
40900 [UNDEFINED] IF [IF]
40901 \ https://forth-standard.org/standard/core/IF
40902 \ IF       -- IFadr    initialize conditional forward branch
40903 CODE IF       \ immediate
40904 SUB #2,PSP              \
40905 MOV TOS,0(PSP)          \
40906 MOV &DP,TOS             \ -- HERE
40907 ADD #4,&DP            \           compile one word, reserve one word
40908 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
40909 ADD #2,TOS              \ -- HERE+2=IFadr
40910 MOV @IP+,PC
40911 ENDCODE IMMEDIATE
40912 [THEN]
40913
40914 [UNDEFINED] THEN [IF]
40915 \ https://forth-standard.org/standard/core/THEN
40916 \ THEN     IFadr --                resolve forward branch
40917 CODE THEN               \ immediate
40918 MOV &DP,0(TOS)          \ -- IFadr
40919 MOV @PSP+,TOS           \ --
40920 MOV @IP+,PC
40921 ENDCODE IMMEDIATE
40922 [THEN]
40923
40924 [UNDEFINED] ELSE [IF]
40925 \ https://forth-standard.org/standard/core/ELSE
40926 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
40927 CODE ELSE     \ immediate
40928 ADD #4,&DP              \ make room to compile two words
40929 MOV &DP,W               \ W=HERE+4
40930 MOV #BRAN,-4(W)
40931 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
40932 SUB #2,W                \ HERE+2
40933 MOV W,TOS               \ -- ELSEadr
40934 MOV @IP+,PC
40935 ENDCODE IMMEDIATE
40936 [THEN]
40937
40938 [UNDEFINED] DEFER [IF]
40939 \ https://forth-standard.org/standard/core/DEFER
40940 \ DEFER "<spaces>name"   --
40941 \ Skip leading space delimiters. Parse name delimited by a space.
40942 \ Create a definition for name with the execution semantics defined below.
40943
40944 \ name Execution:   --
40945 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
40946 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
40947 : DEFER
40948 CREATE
40949 HI2LO
40950 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
40951 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
40952 MOV @RSP+,IP
40953 MOV @IP+,PC
40954 ENDCODE
40955 [THEN]
40956
40957 [UNDEFINED] DEFER! [IF]
40958 \ https://forth-standard.org/standard/core/DEFERStore
40959 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
40960 CODE DEFER!             \ xt2 xt1 --
40961 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
40962 MOV @PSP+,TOS           \ --
40963 MOV @IP+,PC
40964 ENDCODE
40965 [THEN]
40966
40967 [UNDEFINED] IS [IF]
40968 \ https://forth-standard.org/standard/core/IS
40969 \ IS <name>        xt --
40970 \ used as is :
40971 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
40972 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
40973 \ or in a definition : ... ['] U. IS DISPLAY ...
40974 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
40975 \
40976 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
40977 : IS
40978 STATE @
40979 IF  POSTPONE ['] POSTPONE DEFER! 
40980 ELSE ' DEFER! 
40981 THEN
40982 ; IMMEDIATE
40983 [THEN]
40984
40985 [UNDEFINED] >BODY [IF]
40986 \ https://forth-standard.org/standard/core/toBODY
40987 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
40988 CODE >BODY
40989 ADD #4,TOS
40990 MOV @IP+,PC
40991 ENDCODE
40992 [THEN]
40993
40994 \ CODE 20uS           \ n --      8MHz version
40995 \ BEGIN               \ 4 + 16 ~ loop
40996 \     MOV #39,rDOCON   \ 39
40997 \     BEGIN           \ 4 ~ loop
40998 \         NOP
40999 \         SUB #1,rDOCON
41000 \     0=  UNTIL
41001 \     SUB #1,TOS      \ 1
41002 \ 0= UNTIL
41003 \ MOV #XDOCON,rDOCON  \ 2
41004 \ MOV @PSP+,TOS
41005 \ MOV @RSP+,IP        \
41006 \ ENDCODE
41007
41008 CODE 20_US                      \ n --      n * 20 us
41009 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
41010     BEGIN
41011         BIT #1,&LCD_TIM_CTL     \ 3
41012     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
41013     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
41014     SUB #1,TOS                  \ 1
41015 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
41016 MOV @PSP+,TOS                   \ 2
41017 MOV @IP+,PC                     \ 4
41018 ENDCODE
41019
41020 CODE TOP_LCD                    \ LCD Sample
41021 \                               \ if write : %xxxx_WWWW --
41022 \                               \ if read  : -- %0000_RRRR
41023     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
41024     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
41025 0= IF                           \ write LCD bits pattern
41026     AND.B #LCD_DB,TOS           \ 
41027     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
41028     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
41029     MOV @PSP+,TOS               \
41030     MOV @IP+,PC
41031 THEN                            \ read LCD bits pattern
41032     SUB #2,PSP
41033     MOV TOS,0(PSP)
41034     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
41035     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
41036     AND.B #LCD_DB,TOS           \
41037     MOV @IP+,PC
41038 ENDCODE
41039
41040 CODE LCD_WRC                    \ char --         Write Char
41041     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
41042 BW1 SUB #2,PSP                  \
41043     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
41044     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
41045     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
41046     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
41047 COLON                           \ high level word starts here 
41048     TOP_LCD 2 20_US             \ write high nibble first
41049     TOP_LCD 2 20_US 
41050 ;
41051
41052 CODE LCD_WRF                    \ func --         Write Fonction
41053     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
41054     GOTO BW1
41055 ENDCODE
41056
41057 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
41058 : LCD_HOME $02 LCD_WRF 100 20_us ;
41059
41060 \ [UNDEFINED] OR [IF]
41061
41062 \ \ https://forth-standard.org/standard/core/OR
41063 \ \ C OR     x1 x2 -- x3           logical OR
41064 \ CODE OR
41065 \ BIS @PSP+,TOS
41066 \ MOV @IP+,PC
41067 \ ENDCODE
41068
41069 \ [THEN]
41070
41071 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
41072 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
41073 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
41074 \ : LCD_FN_SET        $20 OR LCD_WrF ;
41075 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
41076 \ : LCD_GOTO          $80 OR LCD_WrF ;
41077
41078
41079 \ CODE LCD_RDS                    \ -- status       Read Status
41080 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
41081 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
41082 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
41083 \ COLON                           \ starts a FORTH word
41084 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
41085 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
41086 \ HI2LO                           \ switch from FORTH to assembler
41087 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
41088 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
41089 \     MOV @RSP+,IP                \ restore IP saved by COLON
41090 \     MOV @IP+,PC                 \
41091 \ ENDCODE
41092
41093 \ CODE LCD_RDC                    \ -- char         Read Char
41094 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
41095 \     GOTO BW1
41096 \ ENDCODE
41097
41098
41099 \ ******************************\
41100 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
41101 \ ******************************\
41102 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
41103 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
41104 BIT.B #SW2,&SW2_IN              \ test switch S2
41105 0= IF                           \ case of switch S2 pressed
41106     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
41107     U< IF
41108         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
41109     THEN
41110 ELSE
41111     BIT.B #SW1,&SW1_IN          \ test switch S1 input
41112     0= IF                       \ case of Switch S1 pressed
41113         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
41114         U>= IF                  \
41115            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
41116         THEN                    \
41117     THEN                        \
41118 THEN                            \
41119 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
41120 RET                             \ 5
41121 ENDASM
41122
41123 \ ******************************\
41124 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
41125 \ ******************************\
41126 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
41127 \ ******************************\
41128 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
41129 \                               \       SMclock = 8|16|24 MHz
41130 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
41131 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
41132 \                               \       SR(9)=new Toggle bit memory (ADD on)
41133 \ ******************************\
41134 \ RC5_FirstStartBitHalfCycle:   \
41135 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
41136 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
41137 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
41138 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
41139 \ [THEN]
41140 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
41141     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
41142 [THEN]
41143 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
41144     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
41145 [THEN]
41146 MOV #1778,X                     \ RC5_Period * 1us
41147 MOV #14,W                       \ count of loop
41148 BEGIN                           \
41149 \ ******************************\
41150 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
41151 \ ******************************\                   |
41152 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
41153 \ RC5_Compute_3/4_Period:       \                   |
41154     RRUM    #1,X                \ X=1/2 cycle       |
41155     MOV     X,Y                 \                   ^
41156     RRUM    #1,Y                \ Y=1/4
41157     ADD     X,Y                 \ Y=3/4 cycle
41158     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
41159     U>= UNTIL                   \ 2
41160 \ ******************************\
41161 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
41162 \ ******************************\
41163     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
41164     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
41165     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
41166     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
41167     SUB     #1,W                \ decrement count loop
41168 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
41169 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
41170 0<> WHILE                       \ ----> out of loop ----+
41171     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
41172     BEGIN                       \                       |
41173         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
41174         CMP Y,X                 \ 1                     |   cycle time out of bound ?
41175         U>= IF                  \ 2                 ^   |   yes:
41176         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
41177         GOTO BW1                \                   |   |      quit on truncated RC5 message
41178         THEN                    \                   |   |
41179         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
41180     0<> UNTIL                   \ 2                 |   |
41181 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
41182 \ ******************************\                       |
41183 \ RC5_SampleEndOf:              \ <---------------------+
41184 \ ******************************\
41185 BIC #$30,&RC5_TIM_CTL           \   stop timer
41186 \ ******************************\
41187 \ RC5_ComputeNewRC5word         \
41188 \ ******************************\
41189 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
41190 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
41191 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
41192 \ ******************************\
41193 \ RC5_ComputeC6bit              \
41194 \ ******************************\
41195 BIT     #BIT14,T                \ test /C6 bit in T
41196 0= IF   BIS #BIT6,X             \ set C6 bit in X
41197 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
41198 \ ******************************\
41199 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
41200 \ ******************************\
41201 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
41202 \ ******************************\
41203 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
41204 XOR     @RSP,T                  \ (new XOR old) Toggle bits
41205 BIT     #UF10,T                 \ repeated RC5_command ?
41206 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
41207 XOR #UF10,0(RSP)                \ 5 toggle bit memory
41208 \ ******************************\
41209 \ Display IR_RC5 code           \
41210 \ ******************************\
41211 SUB #8,PSP                      \ TOS -- x x x x TOS
41212 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
41213 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
41214 MOV #$10,&BASEADR               \                                               set hexadecimal base
41215 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
41216 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
41217 LO2HI                           \                                               switch from assembler to FORTH
41218     LCD_CLEAR                   \                                               set LCD cursor at home
41219     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
41220     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
41221     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
41222     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
41223 HI2LO                           \     --                                        switch from FORTH to assembler
41224 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
41225 MOV @PSP+,TOS                   \     -- TOS
41226 RET
41227 ENDASM
41228
41229 \ ******************************\
41230 ASM BACKGROUND                  \
41231 \ ******************************\
41232 BEGIN
41233 \     ...                         \ insert here your background task
41234 \     ...                         \
41235 \     ...                         \
41236     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
41237     BIS &LPM_MODE,SR            \
41238 \ ******************************\
41239 \ here start all interrupts     \
41240 \ ******************************\
41241 \ here return all interrupts    \
41242 \ ******************************\
41243 AGAIN                           \
41244 ENDASM                          \
41245 \ ******************************\
41246
41247 \ ------------------------------\
41248 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
41249 \ ------------------------------\
41250 \     ...                         \ init specific I/O sys as you want
41251 \     ...                         \ before executing default WARM
41252     MOV #WARM,X                 \ ['] WARM 
41253     ADD #4,X                    \ >BODY
41254     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
41255 ENDASM
41256 \ ------------------------------\
41257
41258 \ ------------------------------\
41259 CODE STOP                       \ stops multitasking, must to be used before downloading app
41260 \ ------------------------------\
41261 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
41262     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
41263     MOV X,-2(X)                 \ restore the default background: SLEEP
41264     MOV #WARM,X
41265     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
41266     BIC.B #RC5,&IR_IE           \ clear RC5_Int
41267     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
41268     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
41269     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
41270     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
41271     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
41272 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
41273 ECHO                            \
41274 ." RC5toLCD is removed,"
41275 ."  type START to restart"
41276  WARM                           \ performs reset to reset all interrupt vectors.    
41277 ;
41278 \ ------------------------------\
41279
41280 \ ------------------------------\
41281 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
41282 \ ------------------------------\
41283 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
41284 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
41285 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
41286 \                           --       \ID input divider \ 10 = /4
41287 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
41288 \                                 -  \TBCLR TimerB Clear
41289 \                                  - \TBIE
41290 \                                   -\TBIFG
41291 \ -------------------------------\
41292 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
41293 \                  --                 \CM Capture Mode
41294 \                    --               \CCIS
41295 \                       -             \SCS
41296 \                        --           \CLLD
41297 \                          -          \CAP
41298 \                            ---      \OUTMOD \ 011 = set/reset
41299 \                               -     \CCIE
41300 \                                 -   \CCI
41301 \                                  -  \OUT
41302 \                                   - \COV
41303 \                                    -\CCIFG
41304 \ -------------------------------\
41305 \ LCD_TIM_CCRx                   \
41306 \ -------------------------------\
41307 \ LCD_TIM_EX0                    \ 
41308 \ ------------------------------\
41309 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
41310 \ ------------------------------\
41311 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
41312 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
41313 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
41314     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
41315 [THEN]
41316 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
41317     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
41318 [THEN]
41319     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
41320 \ ------------------------------\
41321 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
41322 \ ------------------------------\
41323 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
41324     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
41325 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
41326 \ ------------------------------\
41327     BIS.B #LCDVo,&LCDVo_DIR     \
41328     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
41329 \ ------------------------------\
41330     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
41331     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
41332 \ ------------------------------\
41333     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
41334     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
41335 \ ******************************\
41336 \ init RC5_Int                  \
41337 \ ******************************\
41338     BIS.B #RC5,&IR_IE           \ enable RC5_Int
41339     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
41340     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
41341 \ ******************************\
41342 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
41343 \ ******************************\
41344 \              %01 0001 0100    \ TAxCTL
41345 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
41346 \                  --           \ ID        divided by 1
41347 \                    --         \ MC        MODE = up to TAxCCRn
41348 \                        -      \ TACLR     clear timer count
41349 \                         -     \ TAIE
41350 \                          -    \ TAIFG
41351 \ ------------------------------\
41352 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
41353 \ ------------------------------\
41354 \                        000    \ TAxEX0
41355 \                        ---    \ TAIDEX    pre divisor
41356 \ ------------------------------\
41357 \          %0000 0000 0000 0101 \ TAxCCR0
41358     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
41359 \ ------------------------------\
41360 \          %0000 0000 0001 0000 \ TAxCCTL0
41361 \                   -           \ CAP capture/compare mode = compare
41362 \                        -      \ CCIEn
41363 \                             - \ CCIFGn
41364     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
41365 \ ------------------------------\
41366     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
41367 \ ------------------------------\
41368 \ define LPM mode for ACCEPT    \
41369 \ ------------------------------\
41370 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
41371 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
41372 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
41373 \ ------------------------------\
41374 \ activate I/O                  \
41375 \ ------------------------------\
41376 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
41377 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
41378 \ ------------------------------\
41379 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
41380 \ ------------------------------\
41381 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
41382 \ CMP #2,Y                        \ Power_ON event
41383 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
41384 CMP #4,Y                        \
41385 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
41386 \ CMP #6,Y                        \
41387 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
41388 \ CMP #$0A,Y                      \
41389 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
41390 \ CMP #$16,Y                      \
41391 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
41392 \ ------------------------------\
41393 COLON                           \
41394 \ ------------------------------\
41395 \ Init LCD 2x20                 \
41396 \ ------------------------------\
41397     #1000 20_US                 \ 1- wait 20 ms
41398     %011 TOP_LCD                \ 2- send DB5=DB4=1
41399     #205 20_US                  \ 3- wait 4,1 ms
41400     %011 TOP_LCD                \ 4- send again DB5=DB4=1
41401     #5 20_US                    \ 5- wait 0,1 ms
41402     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
41403     #2 20_US                    \    wait 40 us = LCD cycle
41404     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
41405     #2 20_US                    \    wait 40 us = LCD cycle
41406     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
41407     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
41408     LCD_CLEAR                   \ 10- "LCD_Clear"
41409     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
41410     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
41411     LCD_CLEAR                   \ 10- "LCD_Clear"
41412     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
41413     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
41414     CR ." I love you"           \ display message on LCD
41415     ['] CR >BODY IS CR          \ CR executes its default value
41416     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
41417     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
41418     PWR_STATE ABORT             \ init DP and continues with ABORT
41419 ;                               \
41420 \ ------------------------------\
41421
41422 \ ------------------------------\
41423 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
41424 \ ------------------------------\
41425 MOV #SLEEP,X                    \ replace default background process SLEEP
41426 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
41427 MOV #WARM,X                     \ replace default WARM
41428 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
41429 MOV X,PC                        \ then execute new WARM
41430 ENDCODE 
41431 \ ------------------------------\
41432
41433 ECHO
41434             ; downloading RC5toLCD.4th is done
41435 RST_HERE    ; this app is protected against <reset>
41436
41437
41438 RST_STATE
41439
41440 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
41441
41442 [UNDEFINED] MARKER [IF]
41443 \  https://forth-standard.org/standard/core/MARKER
41444 \  MARKER
41445 \ ( "<spaces>name" -- )
41446 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
41447 \ with the execution semantics defined below.
41448
41449 \ name Execution: ( -- )
41450 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
41451 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
41452 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
41453 \ not necessarily provided. No other contextual information such as numeric base is affected
41454 \
41455 : MARKER
41456 CREATE
41457 HI2LO
41458 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
41459 SUB #2,Y            \ 1 Y = LFA
41460 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
41461 ADD #4,&DP          \ 3 add 2 cells
41462 LO2HI
41463 DOES>
41464 HI2LO
41465 MOV @RSP+,IP        \ -- PFA
41466 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
41467 MOV @TOS,&INIDP     \       set DP value for RST_STATE
41468 MOV @PSP+,TOS       \ --
41469 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
41470 ENDCODE
41471 [THEN]
41472
41473 MARKER {RC5TOLCD}
41474
41475 [UNDEFINED] @ [IF]
41476 \ https://forth-standard.org/standard/core/Fetch
41477 \ @     c-addr -- char   fetch char from memory
41478 CODE @
41479 MOV @TOS,TOS
41480 MOV @IP+,PC
41481 ENDCODE
41482 [THEN]
41483
41484 [UNDEFINED] CONSTANT [IF]
41485 \ https://forth-standard.org/standard/core/CONSTANT
41486 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
41487 : CONSTANT 
41488 CREATE
41489 HI2LO
41490 MOV TOS,-2(W)           \   PFA = n
41491 MOV @PSP+,TOS
41492 MOV @RSP+,IP
41493 MOV @IP+,PC
41494 ENDCODE
41495 [THEN]
41496
41497 [UNDEFINED] STATE [IF]
41498 \ https://forth-standard.org/standard/core/STATE
41499 \ STATE   -- a-addr       holds compiler state
41500 STATEADR CONSTANT STATE
41501 [THEN]
41502
41503 [UNDEFINED] = [IF]
41504 \ https://forth-standard.org/standard/core/Equal
41505 \ =      x1 x2 -- flag         test x1=x2
41506 CODE =
41507 SUB @PSP+,TOS   \ 2
41508 0<> IF          \ 2
41509     AND #0,TOS  \ 1
41510     MOV @IP+,PC \ 4
41511 THEN
41512 XOR #-1,TOS     \ 1 flag Z = 1
41513 MOV @IP+,PC     \ 4
41514 ENDCODE
41515 [THEN]
41516
41517 [UNDEFINED] IF [IF]
41518 \ https://forth-standard.org/standard/core/IF
41519 \ IF       -- IFadr    initialize conditional forward branch
41520 CODE IF       \ immediate
41521 SUB #2,PSP              \
41522 MOV TOS,0(PSP)          \
41523 MOV &DP,TOS             \ -- HERE
41524 ADD #4,&DP            \           compile one word, reserve one word
41525 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
41526 ADD #2,TOS              \ -- HERE+2=IFadr
41527 MOV @IP+,PC
41528 ENDCODE IMMEDIATE
41529 [THEN]
41530
41531 [UNDEFINED] THEN [IF]
41532 \ https://forth-standard.org/standard/core/THEN
41533 \ THEN     IFadr --                resolve forward branch
41534 CODE THEN               \ immediate
41535 MOV &DP,0(TOS)          \ -- IFadr
41536 MOV @PSP+,TOS           \ --
41537 MOV @IP+,PC
41538 ENDCODE IMMEDIATE
41539 [THEN]
41540
41541 [UNDEFINED] ELSE [IF]
41542 \ https://forth-standard.org/standard/core/ELSE
41543 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
41544 CODE ELSE     \ immediate
41545 ADD #4,&DP              \ make room to compile two words
41546 MOV &DP,W               \ W=HERE+4
41547 MOV #BRAN,-4(W)
41548 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
41549 SUB #2,W                \ HERE+2
41550 MOV W,TOS               \ -- ELSEadr
41551 MOV @IP+,PC
41552 ENDCODE IMMEDIATE
41553 [THEN]
41554
41555 [UNDEFINED] DEFER [IF]
41556 \ https://forth-standard.org/standard/core/DEFER
41557 \ DEFER "<spaces>name"   --
41558 \ Skip leading space delimiters. Parse name delimited by a space.
41559 \ Create a definition for name with the execution semantics defined below.
41560
41561 \ name Execution:   --
41562 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
41563 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
41564 : DEFER
41565 CREATE
41566 HI2LO
41567 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
41568 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
41569 MOV @RSP+,IP
41570 MOV @IP+,PC
41571 ENDCODE
41572 [THEN]
41573
41574 [UNDEFINED] DEFER! [IF]
41575 \ https://forth-standard.org/standard/core/DEFERStore
41576 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
41577 CODE DEFER!             \ xt2 xt1 --
41578 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
41579 MOV @PSP+,TOS           \ --
41580 MOV @IP+,PC
41581 ENDCODE
41582 [THEN]
41583
41584 [UNDEFINED] IS [IF]
41585 \ https://forth-standard.org/standard/core/IS
41586 \ IS <name>        xt --
41587 \ used as is :
41588 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
41589 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
41590 \ or in a definition : ... ['] U. IS DISPLAY ...
41591 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
41592 \
41593 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
41594 : IS
41595 STATE @
41596 IF  POSTPONE ['] POSTPONE DEFER! 
41597 ELSE ' DEFER! 
41598 THEN
41599 ; IMMEDIATE
41600 [THEN]
41601
41602 [UNDEFINED] >BODY [IF]
41603 \ https://forth-standard.org/standard/core/toBODY
41604 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
41605 CODE >BODY
41606 ADD #4,TOS
41607 MOV @IP+,PC
41608 ENDCODE
41609 [THEN]
41610
41611 \ CODE 20uS           \ n --      8MHz version
41612 \ BEGIN               \ 4 + 16 ~ loop
41613 \     MOV #39,rDOCON   \ 39
41614 \     BEGIN           \ 4 ~ loop
41615 \         NOP
41616 \         SUB #1,rDOCON
41617 \     0=  UNTIL
41618 \     SUB #1,TOS      \ 1
41619 \ 0= UNTIL
41620 \ MOV #XDOCON,rDOCON  \ 2
41621 \ MOV @PSP+,TOS
41622 \ MOV @RSP+,IP        \
41623 \ ENDCODE
41624
41625 CODE 20_US                      \ n --      n * 20 us
41626 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
41627     BEGIN
41628         BIT #1,&LCD_TIM_CTL     \ 3
41629     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
41630     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
41631     SUB #1,TOS                  \ 1
41632 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
41633 MOV @PSP+,TOS                   \ 2
41634 MOV @IP+,PC                     \ 4
41635 ENDCODE
41636
41637 CODE TOP_LCD                    \ LCD Sample
41638 \                               \ if write : %xxxx_WWWW --
41639 \                               \ if read  : -- %0000_RRRR
41640     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
41641     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
41642 0= IF                           \ write LCD bits pattern
41643     AND.B #LCD_DB,TOS           \ 
41644     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
41645     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
41646     MOV @PSP+,TOS               \
41647     MOV @IP+,PC
41648 THEN                            \ read LCD bits pattern
41649     SUB #2,PSP
41650     MOV TOS,0(PSP)
41651     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
41652     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
41653     AND.B #LCD_DB,TOS           \
41654     MOV @IP+,PC
41655 ENDCODE
41656
41657 CODE LCD_WRC                    \ char --         Write Char
41658     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
41659 BW1 SUB #2,PSP                  \
41660     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
41661     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
41662     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
41663     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
41664 COLON                           \ high level word starts here 
41665     TOP_LCD 2 20_US             \ write high nibble first
41666     TOP_LCD 2 20_US 
41667 ;
41668
41669 CODE LCD_WRF                    \ func --         Write Fonction
41670     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
41671     GOTO BW1
41672 ENDCODE
41673
41674 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
41675 : LCD_HOME $02 LCD_WRF 100 20_us ;
41676
41677 \ [UNDEFINED] OR [IF]
41678
41679 \ \ https://forth-standard.org/standard/core/OR
41680 \ \ C OR     x1 x2 -- x3           logical OR
41681 \ CODE OR
41682 \ BIS @PSP+,TOS
41683 \ MOV @IP+,PC
41684 \ ENDCODE
41685
41686 \ [THEN]
41687
41688 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
41689 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
41690 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
41691 \ : LCD_FN_SET        $20 OR LCD_WrF ;
41692 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
41693 \ : LCD_GOTO          $80 OR LCD_WrF ;
41694
41695
41696 \ CODE LCD_RDS                    \ -- status       Read Status
41697 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
41698 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
41699 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
41700 \ COLON                           \ starts a FORTH word
41701 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
41702 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
41703 \ HI2LO                           \ switch from FORTH to assembler
41704 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
41705 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
41706 \     MOV @RSP+,IP                \ restore IP saved by COLON
41707 \     MOV @IP+,PC                 \
41708 \ ENDCODE
41709
41710 \ CODE LCD_RDC                    \ -- char         Read Char
41711 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
41712 \     GOTO BW1
41713 \ ENDCODE
41714
41715
41716 \ ******************************\
41717 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
41718 \ ******************************\
41719 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
41720 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
41721 BIT.B #SW2,&SW2_IN              \ test switch S2
41722 0= IF                           \ case of switch S2 pressed
41723     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
41724     U< IF
41725         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
41726     THEN
41727 ELSE
41728     BIT.B #SW1,&SW1_IN          \ test switch S1 input
41729     0= IF                       \ case of Switch S1 pressed
41730         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
41731         U>= IF                  \
41732            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
41733         THEN                    \
41734     THEN                        \
41735 THEN                            \
41736 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
41737 RET                             \ 5
41738 ENDASM
41739
41740 \ ******************************\
41741 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
41742 \ ******************************\
41743 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
41744 \ ******************************\
41745 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
41746 \                               \       SMclock = 8|16|24 MHz
41747 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
41748 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
41749 \                               \       SR(9)=new Toggle bit memory (ADD on)
41750 \ ******************************\
41751 \ RC5_FirstStartBitHalfCycle:   \
41752 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
41753 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
41754 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
41755 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
41756 \ [THEN]
41757 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
41758     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
41759 [THEN]
41760 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
41761     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
41762 [THEN]
41763 MOV #1778,X                     \ RC5_Period * 1us
41764 MOV #14,W                       \ count of loop
41765 BEGIN                           \
41766 \ ******************************\
41767 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
41768 \ ******************************\                   |
41769 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
41770 \ RC5_Compute_3/4_Period:       \                   |
41771     RRUM    #1,X                \ X=1/2 cycle       |
41772     MOV     X,Y                 \                   ^
41773     RRUM    #1,Y                \ Y=1/4
41774     ADD     X,Y                 \ Y=3/4 cycle
41775     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
41776     U>= UNTIL                   \ 2
41777 \ ******************************\
41778 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
41779 \ ******************************\
41780     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
41781     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
41782     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
41783     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
41784     SUB     #1,W                \ decrement count loop
41785 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
41786 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
41787 0<> WHILE                       \ ----> out of loop ----+
41788     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
41789     BEGIN                       \                       |
41790         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
41791         CMP Y,X                 \ 1                     |   cycle time out of bound ?
41792         U>= IF                  \ 2                 ^   |   yes:
41793         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
41794         GOTO BW1                \                   |   |      quit on truncated RC5 message
41795         THEN                    \                   |   |
41796         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
41797     0<> UNTIL                   \ 2                 |   |
41798 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
41799 \ ******************************\                       |
41800 \ RC5_SampleEndOf:              \ <---------------------+
41801 \ ******************************\
41802 BIC #$30,&RC5_TIM_CTL           \   stop timer
41803 \ ******************************\
41804 \ RC5_ComputeNewRC5word         \
41805 \ ******************************\
41806 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
41807 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
41808 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
41809 \ ******************************\
41810 \ RC5_ComputeC6bit              \
41811 \ ******************************\
41812 BIT     #BIT14,T                \ test /C6 bit in T
41813 0= IF   BIS #BIT6,X             \ set C6 bit in X
41814 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
41815 \ ******************************\
41816 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
41817 \ ******************************\
41818 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
41819 \ ******************************\
41820 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
41821 XOR     @RSP,T                  \ (new XOR old) Toggle bits
41822 BIT     #UF10,T                 \ repeated RC5_command ?
41823 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
41824 XOR #UF10,0(RSP)                \ 5 toggle bit memory
41825 \ ******************************\
41826 \ Display IR_RC5 code           \
41827 \ ******************************\
41828 SUB #8,PSP                      \ TOS -- x x x x TOS
41829 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
41830 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
41831 MOV #$10,&BASEADR               \                                               set hexadecimal base
41832 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
41833 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
41834 LO2HI                           \                                               switch from assembler to FORTH
41835     LCD_CLEAR                   \                                               set LCD cursor at home
41836     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
41837     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
41838     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
41839     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
41840 HI2LO                           \     --                                        switch from FORTH to assembler
41841 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
41842 MOV @PSP+,TOS                   \     -- TOS
41843 RET
41844 ENDASM
41845
41846 \ ******************************\
41847 ASM BACKGROUND                  \
41848 \ ******************************\
41849 BEGIN
41850 \     ...                         \ insert here your background task
41851 \     ...                         \
41852 \     ...                         \
41853     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
41854     BIS &LPM_MODE,SR            \
41855 \ ******************************\
41856 \ here start all interrupts     \
41857 \ ******************************\
41858 \ here return all interrupts    \
41859 \ ******************************\
41860 AGAIN                           \
41861 ENDASM                          \
41862 \ ******************************\
41863
41864 \ ------------------------------\
41865 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
41866 \ ------------------------------\
41867 \     ...                         \ init specific I/O sys as you want
41868 \     ...                         \ before executing default WARM
41869     MOV #WARM,X                 \ ['] WARM 
41870     ADD #4,X                    \ >BODY
41871     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
41872 ENDASM
41873 \ ------------------------------\
41874
41875 \ ------------------------------\
41876 CODE STOP                       \ stops multitasking, must to be used before downloading app
41877 \ ------------------------------\
41878 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
41879     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
41880     MOV X,-2(X)                 \ restore the default background: SLEEP
41881     MOV #WARM,X
41882     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
41883     BIC.B #RC5,&IR_IE           \ clear RC5_Int
41884     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
41885     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
41886     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
41887     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
41888     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
41889 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
41890 ECHO                            \
41891 ." RC5toLCD is removed,"
41892 ."  type START to restart"
41893  WARM                           \ performs reset to reset all interrupt vectors.    
41894 ;
41895 \ ------------------------------\
41896
41897 \ ------------------------------\
41898 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
41899 \ ------------------------------\
41900 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
41901 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
41902 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
41903 \                           --       \ID input divider \ 10 = /4
41904 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
41905 \                                 -  \TBCLR TimerB Clear
41906 \                                  - \TBIE
41907 \                                   -\TBIFG
41908 \ -------------------------------\
41909 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
41910 \                  --                 \CM Capture Mode
41911 \                    --               \CCIS
41912 \                       -             \SCS
41913 \                        --           \CLLD
41914 \                          -          \CAP
41915 \                            ---      \OUTMOD \ 011 = set/reset
41916 \                               -     \CCIE
41917 \                                 -   \CCI
41918 \                                  -  \OUT
41919 \                                   - \COV
41920 \                                    -\CCIFG
41921 \ -------------------------------\
41922 \ LCD_TIM_CCRx                   \
41923 \ -------------------------------\
41924 \ LCD_TIM_EX0                    \ 
41925 \ ------------------------------\
41926 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
41927 \ ------------------------------\
41928 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
41929 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
41930 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
41931     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
41932 [THEN]
41933 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
41934     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
41935 [THEN]
41936     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
41937 \ ------------------------------\
41938 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
41939 \ ------------------------------\
41940 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
41941     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
41942 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
41943 \ ------------------------------\
41944     BIS.B #LCDVo,&LCDVo_DIR     \
41945     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
41946 \ ------------------------------\
41947     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
41948     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
41949 \ ------------------------------\
41950     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
41951     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
41952 \ ******************************\
41953 \ init RC5_Int                  \
41954 \ ******************************\
41955     BIS.B #RC5,&IR_IE           \ enable RC5_Int
41956     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
41957     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
41958 \ ******************************\
41959 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
41960 \ ******************************\
41961 \              %01 0001 0100    \ TAxCTL
41962 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
41963 \                  --           \ ID        divided by 1
41964 \                    --         \ MC        MODE = up to TAxCCRn
41965 \                        -      \ TACLR     clear timer count
41966 \                         -     \ TAIE
41967 \                          -    \ TAIFG
41968 \ ------------------------------\
41969 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
41970 \ ------------------------------\
41971 \                        000    \ TAxEX0
41972 \                        ---    \ TAIDEX    pre divisor
41973 \ ------------------------------\
41974 \          %0000 0000 0000 0101 \ TAxCCR0
41975     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
41976 \ ------------------------------\
41977 \          %0000 0000 0001 0000 \ TAxCCTL0
41978 \                   -           \ CAP capture/compare mode = compare
41979 \                        -      \ CCIEn
41980 \                             - \ CCIFGn
41981     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
41982 \ ------------------------------\
41983     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
41984 \ ------------------------------\
41985 \ define LPM mode for ACCEPT    \
41986 \ ------------------------------\
41987 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
41988 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
41989 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
41990 \ ------------------------------\
41991 \ activate I/O                  \
41992 \ ------------------------------\
41993 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
41994 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
41995 \ ------------------------------\
41996 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
41997 \ ------------------------------\
41998 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
41999 \ CMP #2,Y                        \ Power_ON event
42000 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
42001 CMP #4,Y                        \
42002 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
42003 \ CMP #6,Y                        \
42004 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
42005 \ CMP #$0A,Y                      \
42006 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
42007 \ CMP #$16,Y                      \
42008 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
42009 \ ------------------------------\
42010 COLON                           \
42011 \ ------------------------------\
42012 \ Init LCD 2x20                 \
42013 \ ------------------------------\
42014     #1000 20_US                 \ 1- wait 20 ms
42015     %011 TOP_LCD                \ 2- send DB5=DB4=1
42016     #205 20_US                  \ 3- wait 4,1 ms
42017     %011 TOP_LCD                \ 4- send again DB5=DB4=1
42018     #5 20_US                    \ 5- wait 0,1 ms
42019     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
42020     #2 20_US                    \    wait 40 us = LCD cycle
42021     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
42022     #2 20_US                    \    wait 40 us = LCD cycle
42023     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
42024     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
42025     LCD_CLEAR                   \ 10- "LCD_Clear"
42026     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
42027     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
42028     LCD_CLEAR                   \ 10- "LCD_Clear"
42029     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
42030     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
42031     CR ." I love you"           \ display message on LCD
42032     ['] CR >BODY IS CR          \ CR executes its default value
42033     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
42034     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
42035     PWR_STATE ABORT             \ init DP and continues with ABORT
42036 ;                               \
42037 \ ------------------------------\
42038
42039 \ ------------------------------\
42040 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
42041 \ ------------------------------\
42042 MOV #SLEEP,X                    \ replace default background process SLEEP
42043 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
42044 MOV #WARM,X                     \ replace default WARM
42045 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
42046 MOV X,PC                        \ then execute new WARM
42047 ENDCODE 
42048 \ ------------------------------\
42049
42050 ECHO
42051             ; downloading RC5toLCD.4th is done
42052 RST_HERE    ; this app is protected against <reset>
42053
42054
42055 RST_STATE
42056
42057 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
42058
42059 [UNDEFINED] MARKER [IF]
42060 \  https://forth-standard.org/standard/core/MARKER
42061 \  MARKER
42062 \ ( "<spaces>name" -- )
42063 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
42064 \ with the execution semantics defined below.
42065
42066 \ name Execution: ( -- )
42067 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
42068 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
42069 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
42070 \ not necessarily provided. No other contextual information such as numeric base is affected
42071 \
42072 : MARKER
42073 CREATE
42074 HI2LO
42075 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
42076 SUB #2,Y            \ 1 Y = LFA
42077 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
42078 ADD #4,&DP          \ 3 add 2 cells
42079 LO2HI
42080 DOES>
42081 HI2LO
42082 MOV @RSP+,IP        \ -- PFA
42083 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
42084 MOV @TOS,&INIDP     \       set DP value for RST_STATE
42085 MOV @PSP+,TOS       \ --
42086 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
42087 ENDCODE
42088 [THEN]
42089
42090 MARKER {RC5TOLCD}
42091
42092 [UNDEFINED] @ [IF]
42093 \ https://forth-standard.org/standard/core/Fetch
42094 \ @     c-addr -- char   fetch char from memory
42095 CODE @
42096 MOV @TOS,TOS
42097 MOV @IP+,PC
42098 ENDCODE
42099 [THEN]
42100
42101 [UNDEFINED] CONSTANT [IF]
42102 \ https://forth-standard.org/standard/core/CONSTANT
42103 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
42104 : CONSTANT 
42105 CREATE
42106 HI2LO
42107 MOV TOS,-2(W)           \   PFA = n
42108 MOV @PSP+,TOS
42109 MOV @RSP+,IP
42110 MOV @IP+,PC
42111 ENDCODE
42112 [THEN]
42113
42114 [UNDEFINED] STATE [IF]
42115 \ https://forth-standard.org/standard/core/STATE
42116 \ STATE   -- a-addr       holds compiler state
42117 STATEADR CONSTANT STATE
42118 [THEN]
42119
42120 [UNDEFINED] = [IF]
42121 \ https://forth-standard.org/standard/core/Equal
42122 \ =      x1 x2 -- flag         test x1=x2
42123 CODE =
42124 SUB @PSP+,TOS   \ 2
42125 0<> IF          \ 2
42126     AND #0,TOS  \ 1
42127     MOV @IP+,PC \ 4
42128 THEN
42129 XOR #-1,TOS     \ 1 flag Z = 1
42130 MOV @IP+,PC     \ 4
42131 ENDCODE
42132 [THEN]
42133
42134 [UNDEFINED] IF [IF]
42135 \ https://forth-standard.org/standard/core/IF
42136 \ IF       -- IFadr    initialize conditional forward branch
42137 CODE IF       \ immediate
42138 SUB #2,PSP              \
42139 MOV TOS,0(PSP)          \
42140 MOV &DP,TOS             \ -- HERE
42141 ADD #4,&DP            \           compile one word, reserve one word
42142 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
42143 ADD #2,TOS              \ -- HERE+2=IFadr
42144 MOV @IP+,PC
42145 ENDCODE IMMEDIATE
42146 [THEN]
42147
42148 [UNDEFINED] THEN [IF]
42149 \ https://forth-standard.org/standard/core/THEN
42150 \ THEN     IFadr --                resolve forward branch
42151 CODE THEN               \ immediate
42152 MOV &DP,0(TOS)          \ -- IFadr
42153 MOV @PSP+,TOS           \ --
42154 MOV @IP+,PC
42155 ENDCODE IMMEDIATE
42156 [THEN]
42157
42158 [UNDEFINED] ELSE [IF]
42159 \ https://forth-standard.org/standard/core/ELSE
42160 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
42161 CODE ELSE     \ immediate
42162 ADD #4,&DP              \ make room to compile two words
42163 MOV &DP,W               \ W=HERE+4
42164 MOV #BRAN,-4(W)
42165 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
42166 SUB #2,W                \ HERE+2
42167 MOV W,TOS               \ -- ELSEadr
42168 MOV @IP+,PC
42169 ENDCODE IMMEDIATE
42170 [THEN]
42171
42172 [UNDEFINED] DEFER [IF]
42173 \ https://forth-standard.org/standard/core/DEFER
42174 \ DEFER "<spaces>name"   --
42175 \ Skip leading space delimiters. Parse name delimited by a space.
42176 \ Create a definition for name with the execution semantics defined below.
42177
42178 \ name Execution:   --
42179 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
42180 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
42181 : DEFER
42182 CREATE
42183 HI2LO
42184 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
42185 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
42186 MOV @RSP+,IP
42187 MOV @IP+,PC
42188 ENDCODE
42189 [THEN]
42190
42191 [UNDEFINED] DEFER! [IF]
42192 \ https://forth-standard.org/standard/core/DEFERStore
42193 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
42194 CODE DEFER!             \ xt2 xt1 --
42195 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
42196 MOV @PSP+,TOS           \ --
42197 MOV @IP+,PC
42198 ENDCODE
42199 [THEN]
42200
42201 [UNDEFINED] IS [IF]
42202 \ https://forth-standard.org/standard/core/IS
42203 \ IS <name>        xt --
42204 \ used as is :
42205 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
42206 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
42207 \ or in a definition : ... ['] U. IS DISPLAY ...
42208 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
42209 \
42210 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
42211 : IS
42212 STATE @
42213 IF  POSTPONE ['] POSTPONE DEFER! 
42214 ELSE ' DEFER! 
42215 THEN
42216 ; IMMEDIATE
42217 [THEN]
42218
42219 [UNDEFINED] >BODY [IF]
42220 \ https://forth-standard.org/standard/core/toBODY
42221 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
42222 CODE >BODY
42223 ADD #4,TOS
42224 MOV @IP+,PC
42225 ENDCODE
42226 [THEN]
42227
42228 \ CODE 20uS           \ n --      8MHz version
42229 \ BEGIN               \ 4 + 16 ~ loop
42230 \     MOV #39,rDOCON   \ 39
42231 \     BEGIN           \ 4 ~ loop
42232 \         NOP
42233 \         SUB #1,rDOCON
42234 \     0=  UNTIL
42235 \     SUB #1,TOS      \ 1
42236 \ 0= UNTIL
42237 \ MOV #XDOCON,rDOCON  \ 2
42238 \ MOV @PSP+,TOS
42239 \ MOV @RSP+,IP        \
42240 \ ENDCODE
42241
42242 CODE 20_US                      \ n --      n * 20 us
42243 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
42244     BEGIN
42245         BIT #1,&LCD_TIM_CTL     \ 3
42246     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
42247     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
42248     SUB #1,TOS                  \ 1
42249 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
42250 MOV @PSP+,TOS                   \ 2
42251 MOV @IP+,PC                     \ 4
42252 ENDCODE
42253
42254 CODE TOP_LCD                    \ LCD Sample
42255 \                               \ if write : %xxxx_WWWW --
42256 \                               \ if read  : -- %0000_RRRR
42257     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
42258     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
42259 0= IF                           \ write LCD bits pattern
42260     AND.B #LCD_DB,TOS           \ 
42261     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
42262     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
42263     MOV @PSP+,TOS               \
42264     MOV @IP+,PC
42265 THEN                            \ read LCD bits pattern
42266     SUB #2,PSP
42267     MOV TOS,0(PSP)
42268     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
42269     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
42270     AND.B #LCD_DB,TOS           \
42271     MOV @IP+,PC
42272 ENDCODE
42273
42274 CODE LCD_WRC                    \ char --         Write Char
42275     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
42276 BW1 SUB #2,PSP                  \
42277     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
42278     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
42279     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
42280     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
42281 COLON                           \ high level word starts here 
42282     TOP_LCD 2 20_US             \ write high nibble first
42283     TOP_LCD 2 20_US 
42284 ;
42285
42286 CODE LCD_WRF                    \ func --         Write Fonction
42287     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
42288     GOTO BW1
42289 ENDCODE
42290
42291 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
42292 : LCD_HOME $02 LCD_WRF 100 20_us ;
42293
42294 \ [UNDEFINED] OR [IF]
42295
42296 \ \ https://forth-standard.org/standard/core/OR
42297 \ \ C OR     x1 x2 -- x3           logical OR
42298 \ CODE OR
42299 \ BIS @PSP+,TOS
42300 \ MOV @IP+,PC
42301 \ ENDCODE
42302
42303 \ [THEN]
42304
42305 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
42306 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
42307 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
42308 \ : LCD_FN_SET        $20 OR LCD_WrF ;
42309 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
42310 \ : LCD_GOTO          $80 OR LCD_WrF ;
42311
42312
42313 \ CODE LCD_RDS                    \ -- status       Read Status
42314 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
42315 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
42316 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
42317 \ COLON                           \ starts a FORTH word
42318 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
42319 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
42320 \ HI2LO                           \ switch from FORTH to assembler
42321 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
42322 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
42323 \     MOV @RSP+,IP                \ restore IP saved by COLON
42324 \     MOV @IP+,PC                 \
42325 \ ENDCODE
42326
42327 \ CODE LCD_RDC                    \ -- char         Read Char
42328 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
42329 \     GOTO BW1
42330 \ ENDCODE
42331
42332
42333 \ ******************************\
42334 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
42335 \ ******************************\
42336 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
42337 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
42338 BIT.B #SW2,&SW2_IN              \ test switch S2
42339 0= IF                           \ case of switch S2 pressed
42340     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
42341     U< IF
42342         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
42343     THEN
42344 ELSE
42345     BIT.B #SW1,&SW1_IN          \ test switch S1 input
42346     0= IF                       \ case of Switch S1 pressed
42347         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
42348         U>= IF                  \
42349            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
42350         THEN                    \
42351     THEN                        \
42352 THEN                            \
42353 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
42354 RET                             \ 5
42355 ENDASM
42356
42357 \ ******************************\
42358 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
42359 \ ******************************\
42360 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
42361 \ ******************************\
42362 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
42363 \                               \       SMclock = 8|16|24 MHz
42364 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
42365 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
42366 \                               \       SR(9)=new Toggle bit memory (ADD on)
42367 \ ******************************\
42368 \ RC5_FirstStartBitHalfCycle:   \
42369 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
42370 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
42371 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
42372 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
42373 \ [THEN]
42374 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
42375     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
42376 [THEN]
42377 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
42378     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
42379 [THEN]
42380 MOV #1778,X                     \ RC5_Period * 1us
42381 MOV #14,W                       \ count of loop
42382 BEGIN                           \
42383 \ ******************************\
42384 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
42385 \ ******************************\                   |
42386 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
42387 \ RC5_Compute_3/4_Period:       \                   |
42388     RRUM    #1,X                \ X=1/2 cycle       |
42389     MOV     X,Y                 \                   ^
42390     RRUM    #1,Y                \ Y=1/4
42391     ADD     X,Y                 \ Y=3/4 cycle
42392     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
42393     U>= UNTIL                   \ 2
42394 \ ******************************\
42395 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
42396 \ ******************************\
42397     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
42398     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
42399     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
42400     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
42401     SUB     #1,W                \ decrement count loop
42402 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
42403 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
42404 0<> WHILE                       \ ----> out of loop ----+
42405     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
42406     BEGIN                       \                       |
42407         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
42408         CMP Y,X                 \ 1                     |   cycle time out of bound ?
42409         U>= IF                  \ 2                 ^   |   yes:
42410         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
42411         GOTO BW1                \                   |   |      quit on truncated RC5 message
42412         THEN                    \                   |   |
42413         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
42414     0<> UNTIL                   \ 2                 |   |
42415 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
42416 \ ******************************\                       |
42417 \ RC5_SampleEndOf:              \ <---------------------+
42418 \ ******************************\
42419 BIC #$30,&RC5_TIM_CTL           \   stop timer
42420 \ ******************************\
42421 \ RC5_ComputeNewRC5word         \
42422 \ ******************************\
42423 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
42424 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
42425 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
42426 \ ******************************\
42427 \ RC5_ComputeC6bit              \
42428 \ ******************************\
42429 BIT     #BIT14,T                \ test /C6 bit in T
42430 0= IF   BIS #BIT6,X             \ set C6 bit in X
42431 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
42432 \ ******************************\
42433 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
42434 \ ******************************\
42435 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
42436 \ ******************************\
42437 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
42438 XOR     @RSP,T                  \ (new XOR old) Toggle bits
42439 BIT     #UF10,T                 \ repeated RC5_command ?
42440 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
42441 XOR #UF10,0(RSP)                \ 5 toggle bit memory
42442 \ ******************************\
42443 \ Display IR_RC5 code           \
42444 \ ******************************\
42445 SUB #8,PSP                      \ TOS -- x x x x TOS
42446 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
42447 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
42448 MOV #$10,&BASEADR               \                                               set hexadecimal base
42449 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
42450 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
42451 LO2HI                           \                                               switch from assembler to FORTH
42452     LCD_CLEAR                   \                                               set LCD cursor at home
42453     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
42454     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
42455     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
42456     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
42457 HI2LO                           \     --                                        switch from FORTH to assembler
42458 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
42459 MOV @PSP+,TOS                   \     -- TOS
42460 RET
42461 ENDASM
42462
42463 \ ******************************\
42464 ASM BACKGROUND                  \
42465 \ ******************************\
42466 BEGIN
42467 \     ...                         \ insert here your background task
42468 \     ...                         \
42469 \     ...                         \
42470     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
42471     BIS &LPM_MODE,SR            \
42472 \ ******************************\
42473 \ here start all interrupts     \
42474 \ ******************************\
42475 \ here return all interrupts    \
42476 \ ******************************\
42477 AGAIN                           \
42478 ENDASM                          \
42479 \ ******************************\
42480
42481 \ ------------------------------\
42482 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
42483 \ ------------------------------\
42484 \     ...                         \ init specific I/O sys as you want
42485 \     ...                         \ before executing default WARM
42486     MOV #WARM,X                 \ ['] WARM 
42487     ADD #4,X                    \ >BODY
42488     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
42489 ENDASM
42490 \ ------------------------------\
42491
42492 \ ------------------------------\
42493 CODE STOP                       \ stops multitasking, must to be used before downloading app
42494 \ ------------------------------\
42495 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
42496     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
42497     MOV X,-2(X)                 \ restore the default background: SLEEP
42498     MOV #WARM,X
42499     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
42500     BIC.B #RC5,&IR_IE           \ clear RC5_Int
42501     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
42502     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
42503     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
42504     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
42505     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
42506 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
42507 ECHO                            \
42508 ." RC5toLCD is removed,"
42509 ."  type START to restart"
42510  WARM                           \ performs reset to reset all interrupt vectors.    
42511 ;
42512 \ ------------------------------\
42513
42514 \ ------------------------------\
42515 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
42516 \ ------------------------------\
42517 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
42518 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
42519 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
42520 \                           --       \ID input divider \ 10 = /4
42521 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
42522 \                                 -  \TBCLR TimerB Clear
42523 \                                  - \TBIE
42524 \                                   -\TBIFG
42525 \ -------------------------------\
42526 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
42527 \                  --                 \CM Capture Mode
42528 \                    --               \CCIS
42529 \                       -             \SCS
42530 \                        --           \CLLD
42531 \                          -          \CAP
42532 \                            ---      \OUTMOD \ 011 = set/reset
42533 \                               -     \CCIE
42534 \                                 -   \CCI
42535 \                                  -  \OUT
42536 \                                   - \COV
42537 \                                    -\CCIFG
42538 \ -------------------------------\
42539 \ LCD_TIM_CCRx                   \
42540 \ -------------------------------\
42541 \ LCD_TIM_EX0                    \ 
42542 \ ------------------------------\
42543 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
42544 \ ------------------------------\
42545 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
42546 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
42547 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
42548     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
42549 [THEN]
42550 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
42551     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
42552 [THEN]
42553     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
42554 \ ------------------------------\
42555 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
42556 \ ------------------------------\
42557 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
42558     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
42559 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
42560 \ ------------------------------\
42561     BIS.B #LCDVo,&LCDVo_DIR     \
42562     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
42563 \ ------------------------------\
42564     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
42565     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
42566 \ ------------------------------\
42567     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
42568     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
42569 \ ******************************\
42570 \ init RC5_Int                  \
42571 \ ******************************\
42572     BIS.B #RC5,&IR_IE           \ enable RC5_Int
42573     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
42574     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
42575 \ ******************************\
42576 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
42577 \ ******************************\
42578 \              %01 0001 0100    \ TAxCTL
42579 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
42580 \                  --           \ ID        divided by 1
42581 \                    --         \ MC        MODE = up to TAxCCRn
42582 \                        -      \ TACLR     clear timer count
42583 \                         -     \ TAIE
42584 \                          -    \ TAIFG
42585 \ ------------------------------\
42586 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
42587 \ ------------------------------\
42588 \                        000    \ TAxEX0
42589 \                        ---    \ TAIDEX    pre divisor
42590 \ ------------------------------\
42591 \          %0000 0000 0000 0101 \ TAxCCR0
42592     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
42593 \ ------------------------------\
42594 \          %0000 0000 0001 0000 \ TAxCCTL0
42595 \                   -           \ CAP capture/compare mode = compare
42596 \                        -      \ CCIEn
42597 \                             - \ CCIFGn
42598     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
42599 \ ------------------------------\
42600     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
42601 \ ------------------------------\
42602 \ define LPM mode for ACCEPT    \
42603 \ ------------------------------\
42604 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
42605 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
42606 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
42607 \ ------------------------------\
42608 \ activate I/O                  \
42609 \ ------------------------------\
42610 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
42611 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
42612 \ ------------------------------\
42613 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
42614 \ ------------------------------\
42615 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
42616 \ CMP #2,Y                        \ Power_ON event
42617 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
42618 CMP #4,Y                        \
42619 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
42620 \ CMP #6,Y                        \
42621 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
42622 \ CMP #$0A,Y                      \
42623 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
42624 \ CMP #$16,Y                      \
42625 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
42626 \ ------------------------------\
42627 COLON                           \
42628 \ ------------------------------\
42629 \ Init LCD 2x20                 \
42630 \ ------------------------------\
42631     #1000 20_US                 \ 1- wait 20 ms
42632     %011 TOP_LCD                \ 2- send DB5=DB4=1
42633     #205 20_US                  \ 3- wait 4,1 ms
42634     %011 TOP_LCD                \ 4- send again DB5=DB4=1
42635     #5 20_US                    \ 5- wait 0,1 ms
42636     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
42637     #2 20_US                    \    wait 40 us = LCD cycle
42638     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
42639     #2 20_US                    \    wait 40 us = LCD cycle
42640     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
42641     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
42642     LCD_CLEAR                   \ 10- "LCD_Clear"
42643     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
42644     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
42645     LCD_CLEAR                   \ 10- "LCD_Clear"
42646     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
42647     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
42648     CR ." I love you"           \ display message on LCD
42649     ['] CR >BODY IS CR          \ CR executes its default value
42650     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
42651     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
42652     PWR_STATE ABORT             \ init DP and continues with ABORT
42653 ;                               \
42654 \ ------------------------------\
42655
42656 \ ------------------------------\
42657 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
42658 \ ------------------------------\
42659 MOV #SLEEP,X                    \ replace default background process SLEEP
42660 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
42661 MOV #WARM,X                     \ replace default WARM
42662 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
42663 MOV X,PC                        \ then execute new WARM
42664 ENDCODE 
42665 \ ------------------------------\
42666
42667 ECHO
42668             ; downloading RC5toLCD.4th is done
42669 RST_HERE    ; this app is protected against <reset>
42670
42671
42672 RST_STATE
42673
42674 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
42675
42676 [UNDEFINED] MARKER [IF]
42677 \  https://forth-standard.org/standard/core/MARKER
42678 \  MARKER
42679 \ ( "<spaces>name" -- )
42680 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
42681 \ with the execution semantics defined below.
42682
42683 \ name Execution: ( -- )
42684 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
42685 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
42686 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
42687 \ not necessarily provided. No other contextual information such as numeric base is affected
42688 \
42689 : MARKER
42690 CREATE
42691 HI2LO
42692 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
42693 SUB #2,Y            \ 1 Y = LFA
42694 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
42695 ADD #4,&DP          \ 3 add 2 cells
42696 LO2HI
42697 DOES>
42698 HI2LO
42699 MOV @RSP+,IP        \ -- PFA
42700 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
42701 MOV @TOS,&INIDP     \       set DP value for RST_STATE
42702 MOV @PSP+,TOS       \ --
42703 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
42704 ENDCODE
42705 [THEN]
42706
42707 MARKER {RC5TOLCD}
42708
42709 [UNDEFINED] @ [IF]
42710 \ https://forth-standard.org/standard/core/Fetch
42711 \ @     c-addr -- char   fetch char from memory
42712 CODE @
42713 MOV @TOS,TOS
42714 MOV @IP+,PC
42715 ENDCODE
42716 [THEN]
42717
42718 [UNDEFINED] CONSTANT [IF]
42719 \ https://forth-standard.org/standard/core/CONSTANT
42720 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
42721 : CONSTANT 
42722 CREATE
42723 HI2LO
42724 MOV TOS,-2(W)           \   PFA = n
42725 MOV @PSP+,TOS
42726 MOV @RSP+,IP
42727 MOV @IP+,PC
42728 ENDCODE
42729 [THEN]
42730
42731 [UNDEFINED] STATE [IF]
42732 \ https://forth-standard.org/standard/core/STATE
42733 \ STATE   -- a-addr       holds compiler state
42734 STATEADR CONSTANT STATE
42735 [THEN]
42736
42737 [UNDEFINED] = [IF]
42738 \ https://forth-standard.org/standard/core/Equal
42739 \ =      x1 x2 -- flag         test x1=x2
42740 CODE =
42741 SUB @PSP+,TOS   \ 2
42742 0<> IF          \ 2
42743     AND #0,TOS  \ 1
42744     MOV @IP+,PC \ 4
42745 THEN
42746 XOR #-1,TOS     \ 1 flag Z = 1
42747 MOV @IP+,PC     \ 4
42748 ENDCODE
42749 [THEN]
42750
42751 [UNDEFINED] IF [IF]
42752 \ https://forth-standard.org/standard/core/IF
42753 \ IF       -- IFadr    initialize conditional forward branch
42754 CODE IF       \ immediate
42755 SUB #2,PSP              \
42756 MOV TOS,0(PSP)          \
42757 MOV &DP,TOS             \ -- HERE
42758 ADD #4,&DP            \           compile one word, reserve one word
42759 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
42760 ADD #2,TOS              \ -- HERE+2=IFadr
42761 MOV @IP+,PC
42762 ENDCODE IMMEDIATE
42763 [THEN]
42764
42765 [UNDEFINED] THEN [IF]
42766 \ https://forth-standard.org/standard/core/THEN
42767 \ THEN     IFadr --                resolve forward branch
42768 CODE THEN               \ immediate
42769 MOV &DP,0(TOS)          \ -- IFadr
42770 MOV @PSP+,TOS           \ --
42771 MOV @IP+,PC
42772 ENDCODE IMMEDIATE
42773 [THEN]
42774
42775 [UNDEFINED] ELSE [IF]
42776 \ https://forth-standard.org/standard/core/ELSE
42777 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
42778 CODE ELSE     \ immediate
42779 ADD #4,&DP              \ make room to compile two words
42780 MOV &DP,W               \ W=HERE+4
42781 MOV #BRAN,-4(W)
42782 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
42783 SUB #2,W                \ HERE+2
42784 MOV W,TOS               \ -- ELSEadr
42785 MOV @IP+,PC
42786 ENDCODE IMMEDIATE
42787 [THEN]
42788
42789 [UNDEFINED] DEFER [IF]
42790 \ https://forth-standard.org/standard/core/DEFER
42791 \ DEFER "<spaces>name"   --
42792 \ Skip leading space delimiters. Parse name delimited by a space.
42793 \ Create a definition for name with the execution semantics defined below.
42794
42795 \ name Execution:   --
42796 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
42797 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
42798 : DEFER
42799 CREATE
42800 HI2LO
42801 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
42802 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
42803 MOV @RSP+,IP
42804 MOV @IP+,PC
42805 ENDCODE
42806 [THEN]
42807
42808 [UNDEFINED] DEFER! [IF]
42809 \ https://forth-standard.org/standard/core/DEFERStore
42810 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
42811 CODE DEFER!             \ xt2 xt1 --
42812 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
42813 MOV @PSP+,TOS           \ --
42814 MOV @IP+,PC
42815 ENDCODE
42816 [THEN]
42817
42818 [UNDEFINED] IS [IF]
42819 \ https://forth-standard.org/standard/core/IS
42820 \ IS <name>        xt --
42821 \ used as is :
42822 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
42823 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
42824 \ or in a definition : ... ['] U. IS DISPLAY ...
42825 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
42826 \
42827 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
42828 : IS
42829 STATE @
42830 IF  POSTPONE ['] POSTPONE DEFER! 
42831 ELSE ' DEFER! 
42832 THEN
42833 ; IMMEDIATE
42834 [THEN]
42835
42836 [UNDEFINED] >BODY [IF]
42837 \ https://forth-standard.org/standard/core/toBODY
42838 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
42839 CODE >BODY
42840 ADD #4,TOS
42841 MOV @IP+,PC
42842 ENDCODE
42843 [THEN]
42844
42845 \ CODE 20uS           \ n --      8MHz version
42846 \ BEGIN               \ 4 + 16 ~ loop
42847 \     MOV #39,rDOCON   \ 39
42848 \     BEGIN           \ 4 ~ loop
42849 \         NOP
42850 \         SUB #1,rDOCON
42851 \     0=  UNTIL
42852 \     SUB #1,TOS      \ 1
42853 \ 0= UNTIL
42854 \ MOV #XDOCON,rDOCON  \ 2
42855 \ MOV @PSP+,TOS
42856 \ MOV @RSP+,IP        \
42857 \ ENDCODE
42858
42859 CODE 20_US                      \ n --      n * 20 us
42860 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
42861     BEGIN
42862         BIT #1,&LCD_TIM_CTL     \ 3
42863     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
42864     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
42865     SUB #1,TOS                  \ 1
42866 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
42867 MOV @PSP+,TOS                   \ 2
42868 MOV @IP+,PC                     \ 4
42869 ENDCODE
42870
42871 CODE TOP_LCD                    \ LCD Sample
42872 \                               \ if write : %xxxx_WWWW --
42873 \                               \ if read  : -- %0000_RRRR
42874     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
42875     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
42876 0= IF                           \ write LCD bits pattern
42877     AND.B #LCD_DB,TOS           \ 
42878     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
42879     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
42880     MOV @PSP+,TOS               \
42881     MOV @IP+,PC
42882 THEN                            \ read LCD bits pattern
42883     SUB #2,PSP
42884     MOV TOS,0(PSP)
42885     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
42886     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
42887     AND.B #LCD_DB,TOS           \
42888     MOV @IP+,PC
42889 ENDCODE
42890
42891 CODE LCD_WRC                    \ char --         Write Char
42892     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
42893 BW1 SUB #2,PSP                  \
42894     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
42895     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
42896     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
42897     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
42898 COLON                           \ high level word starts here 
42899     TOP_LCD 2 20_US             \ write high nibble first
42900     TOP_LCD 2 20_US 
42901 ;
42902
42903 CODE LCD_WRF                    \ func --         Write Fonction
42904     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
42905     GOTO BW1
42906 ENDCODE
42907
42908 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
42909 : LCD_HOME $02 LCD_WRF 100 20_us ;
42910
42911 \ [UNDEFINED] OR [IF]
42912
42913 \ \ https://forth-standard.org/standard/core/OR
42914 \ \ C OR     x1 x2 -- x3           logical OR
42915 \ CODE OR
42916 \ BIS @PSP+,TOS
42917 \ MOV @IP+,PC
42918 \ ENDCODE
42919
42920 \ [THEN]
42921
42922 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
42923 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
42924 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
42925 \ : LCD_FN_SET        $20 OR LCD_WrF ;
42926 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
42927 \ : LCD_GOTO          $80 OR LCD_WrF ;
42928
42929
42930 \ CODE LCD_RDS                    \ -- status       Read Status
42931 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
42932 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
42933 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
42934 \ COLON                           \ starts a FORTH word
42935 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
42936 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
42937 \ HI2LO                           \ switch from FORTH to assembler
42938 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
42939 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
42940 \     MOV @RSP+,IP                \ restore IP saved by COLON
42941 \     MOV @IP+,PC                 \
42942 \ ENDCODE
42943
42944 \ CODE LCD_RDC                    \ -- char         Read Char
42945 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
42946 \     GOTO BW1
42947 \ ENDCODE
42948
42949
42950 \ ******************************\
42951 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
42952 \ ******************************\
42953 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
42954 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
42955 BIT.B #SW2,&SW2_IN              \ test switch S2
42956 0= IF                           \ case of switch S2 pressed
42957     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
42958     U< IF
42959         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
42960     THEN
42961 ELSE
42962     BIT.B #SW1,&SW1_IN          \ test switch S1 input
42963     0= IF                       \ case of Switch S1 pressed
42964         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
42965         U>= IF                  \
42966            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
42967         THEN                    \
42968     THEN                        \
42969 THEN                            \
42970 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
42971 RET                             \ 5
42972 ENDASM
42973
42974 \ ******************************\
42975 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
42976 \ ******************************\
42977 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
42978 \ ******************************\
42979 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
42980 \                               \       SMclock = 8|16|24 MHz
42981 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
42982 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
42983 \                               \       SR(9)=new Toggle bit memory (ADD on)
42984 \ ******************************\
42985 \ RC5_FirstStartBitHalfCycle:   \
42986 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
42987 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
42988 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
42989 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
42990 \ [THEN]
42991 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
42992     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
42993 [THEN]
42994 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
42995     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
42996 [THEN]
42997 MOV #1778,X                     \ RC5_Period * 1us
42998 MOV #14,W                       \ count of loop
42999 BEGIN                           \
43000 \ ******************************\
43001 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
43002 \ ******************************\                   |
43003 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
43004 \ RC5_Compute_3/4_Period:       \                   |
43005     RRUM    #1,X                \ X=1/2 cycle       |
43006     MOV     X,Y                 \                   ^
43007     RRUM    #1,Y                \ Y=1/4
43008     ADD     X,Y                 \ Y=3/4 cycle
43009     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
43010     U>= UNTIL                   \ 2
43011 \ ******************************\
43012 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
43013 \ ******************************\
43014     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
43015     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
43016     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
43017     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
43018     SUB     #1,W                \ decrement count loop
43019 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
43020 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
43021 0<> WHILE                       \ ----> out of loop ----+
43022     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
43023     BEGIN                       \                       |
43024         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
43025         CMP Y,X                 \ 1                     |   cycle time out of bound ?
43026         U>= IF                  \ 2                 ^   |   yes:
43027         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
43028         GOTO BW1                \                   |   |      quit on truncated RC5 message
43029         THEN                    \                   |   |
43030         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
43031     0<> UNTIL                   \ 2                 |   |
43032 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
43033 \ ******************************\                       |
43034 \ RC5_SampleEndOf:              \ <---------------------+
43035 \ ******************************\
43036 BIC #$30,&RC5_TIM_CTL           \   stop timer
43037 \ ******************************\
43038 \ RC5_ComputeNewRC5word         \
43039 \ ******************************\
43040 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
43041 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
43042 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
43043 \ ******************************\
43044 \ RC5_ComputeC6bit              \
43045 \ ******************************\
43046 BIT     #BIT14,T                \ test /C6 bit in T
43047 0= IF   BIS #BIT6,X             \ set C6 bit in X
43048 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
43049 \ ******************************\
43050 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
43051 \ ******************************\
43052 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
43053 \ ******************************\
43054 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
43055 XOR     @RSP,T                  \ (new XOR old) Toggle bits
43056 BIT     #UF10,T                 \ repeated RC5_command ?
43057 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
43058 XOR #UF10,0(RSP)                \ 5 toggle bit memory
43059 \ ******************************\
43060 \ Display IR_RC5 code           \
43061 \ ******************************\
43062 SUB #8,PSP                      \ TOS -- x x x x TOS
43063 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
43064 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
43065 MOV #$10,&BASEADR               \                                               set hexadecimal base
43066 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
43067 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
43068 LO2HI                           \                                               switch from assembler to FORTH
43069     LCD_CLEAR                   \                                               set LCD cursor at home
43070     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
43071     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
43072     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
43073     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
43074 HI2LO                           \     --                                        switch from FORTH to assembler
43075 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
43076 MOV @PSP+,TOS                   \     -- TOS
43077 RET
43078 ENDASM
43079
43080 \ ******************************\
43081 ASM BACKGROUND                  \
43082 \ ******************************\
43083 BEGIN
43084 \     ...                         \ insert here your background task
43085 \     ...                         \
43086 \     ...                         \
43087     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
43088     BIS &LPM_MODE,SR            \
43089 \ ******************************\
43090 \ here start all interrupts     \
43091 \ ******************************\
43092 \ here return all interrupts    \
43093 \ ******************************\
43094 AGAIN                           \
43095 ENDASM                          \
43096 \ ******************************\
43097
43098 \ ------------------------------\
43099 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
43100 \ ------------------------------\
43101 \     ...                         \ init specific I/O sys as you want
43102 \     ...                         \ before executing default WARM
43103     MOV #WARM,X                 \ ['] WARM 
43104     ADD #4,X                    \ >BODY
43105     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
43106 ENDASM
43107 \ ------------------------------\
43108
43109 \ ------------------------------\
43110 CODE STOP                       \ stops multitasking, must to be used before downloading app
43111 \ ------------------------------\
43112 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
43113     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
43114     MOV X,-2(X)                 \ restore the default background: SLEEP
43115     MOV #WARM,X
43116     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
43117     BIC.B #RC5,&IR_IE           \ clear RC5_Int
43118     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
43119     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
43120     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
43121     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
43122     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
43123 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
43124 ECHO                            \
43125 ." RC5toLCD is removed,"
43126 ."  type START to restart"
43127  WARM                           \ performs reset to reset all interrupt vectors.    
43128 ;
43129 \ ------------------------------\
43130
43131 \ ------------------------------\
43132 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
43133 \ ------------------------------\
43134 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
43135 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
43136 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
43137 \                           --       \ID input divider \ 10 = /4
43138 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
43139 \                                 -  \TBCLR TimerB Clear
43140 \                                  - \TBIE
43141 \                                   -\TBIFG
43142 \ -------------------------------\
43143 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
43144 \                  --                 \CM Capture Mode
43145 \                    --               \CCIS
43146 \                       -             \SCS
43147 \                        --           \CLLD
43148 \                          -          \CAP
43149 \                            ---      \OUTMOD \ 011 = set/reset
43150 \                               -     \CCIE
43151 \                                 -   \CCI
43152 \                                  -  \OUT
43153 \                                   - \COV
43154 \                                    -\CCIFG
43155 \ -------------------------------\
43156 \ LCD_TIM_CCRx                   \
43157 \ -------------------------------\
43158 \ LCD_TIM_EX0                    \ 
43159 \ ------------------------------\
43160 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
43161 \ ------------------------------\
43162 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
43163 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
43164 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
43165     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
43166 [THEN]
43167 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
43168     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
43169 [THEN]
43170     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
43171 \ ------------------------------\
43172 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
43173 \ ------------------------------\
43174 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
43175     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
43176 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
43177 \ ------------------------------\
43178     BIS.B #LCDVo,&LCDVo_DIR     \
43179     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
43180 \ ------------------------------\
43181     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
43182     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
43183 \ ------------------------------\
43184     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
43185     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
43186 \ ******************************\
43187 \ init RC5_Int                  \
43188 \ ******************************\
43189     BIS.B #RC5,&IR_IE           \ enable RC5_Int
43190     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
43191     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
43192 \ ******************************\
43193 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
43194 \ ******************************\
43195 \              %01 0001 0100    \ TAxCTL
43196 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
43197 \                  --           \ ID        divided by 1
43198 \                    --         \ MC        MODE = up to TAxCCRn
43199 \                        -      \ TACLR     clear timer count
43200 \                         -     \ TAIE
43201 \                          -    \ TAIFG
43202 \ ------------------------------\
43203 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
43204 \ ------------------------------\
43205 \                        000    \ TAxEX0
43206 \                        ---    \ TAIDEX    pre divisor
43207 \ ------------------------------\
43208 \          %0000 0000 0000 0101 \ TAxCCR0
43209     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
43210 \ ------------------------------\
43211 \          %0000 0000 0001 0000 \ TAxCCTL0
43212 \                   -           \ CAP capture/compare mode = compare
43213 \                        -      \ CCIEn
43214 \                             - \ CCIFGn
43215     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
43216 \ ------------------------------\
43217     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
43218 \ ------------------------------\
43219 \ define LPM mode for ACCEPT    \
43220 \ ------------------------------\
43221 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
43222 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
43223 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
43224 \ ------------------------------\
43225 \ activate I/O                  \
43226 \ ------------------------------\
43227 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
43228 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
43229 \ ------------------------------\
43230 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
43231 \ ------------------------------\
43232 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
43233 \ CMP #2,Y                        \ Power_ON event
43234 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
43235 CMP #4,Y                        \
43236 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
43237 \ CMP #6,Y                        \
43238 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
43239 \ CMP #$0A,Y                      \
43240 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
43241 \ CMP #$16,Y                      \
43242 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
43243 \ ------------------------------\
43244 COLON                           \
43245 \ ------------------------------\
43246 \ Init LCD 2x20                 \
43247 \ ------------------------------\
43248     #1000 20_US                 \ 1- wait 20 ms
43249     %011 TOP_LCD                \ 2- send DB5=DB4=1
43250     #205 20_US                  \ 3- wait 4,1 ms
43251     %011 TOP_LCD                \ 4- send again DB5=DB4=1
43252     #5 20_US                    \ 5- wait 0,1 ms
43253     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
43254     #2 20_US                    \    wait 40 us = LCD cycle
43255     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
43256     #2 20_US                    \    wait 40 us = LCD cycle
43257     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
43258     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
43259     LCD_CLEAR                   \ 10- "LCD_Clear"
43260     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
43261     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
43262     LCD_CLEAR                   \ 10- "LCD_Clear"
43263     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
43264     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
43265     CR ." I love you"           \ display message on LCD
43266     ['] CR >BODY IS CR          \ CR executes its default value
43267     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
43268     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
43269     PWR_STATE ABORT             \ init DP and continues with ABORT
43270 ;                               \
43271 \ ------------------------------\
43272
43273 \ ------------------------------\
43274 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
43275 \ ------------------------------\
43276 MOV #SLEEP,X                    \ replace default background process SLEEP
43277 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
43278 MOV #WARM,X                     \ replace default WARM
43279 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
43280 MOV X,PC                        \ then execute new WARM
43281 ENDCODE 
43282 \ ------------------------------\
43283
43284 ECHO
43285             ; downloading RC5toLCD.4th is done
43286 RST_HERE    ; this app is protected against <reset>
43287
43288
43289 RST_STATE
43290
43291 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
43292
43293 [UNDEFINED] MARKER [IF]
43294 \  https://forth-standard.org/standard/core/MARKER
43295 \  MARKER
43296 \ ( "<spaces>name" -- )
43297 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
43298 \ with the execution semantics defined below.
43299
43300 \ name Execution: ( -- )
43301 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
43302 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
43303 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
43304 \ not necessarily provided. No other contextual information such as numeric base is affected
43305 \
43306 : MARKER
43307 CREATE
43308 HI2LO
43309 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
43310 SUB #2,Y            \ 1 Y = LFA
43311 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
43312 ADD #4,&DP          \ 3 add 2 cells
43313 LO2HI
43314 DOES>
43315 HI2LO
43316 MOV @RSP+,IP        \ -- PFA
43317 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
43318 MOV @TOS,&INIDP     \       set DP value for RST_STATE
43319 MOV @PSP+,TOS       \ --
43320 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
43321 ENDCODE
43322 [THEN]
43323
43324 MARKER {RC5TOLCD}
43325
43326 [UNDEFINED] @ [IF]
43327 \ https://forth-standard.org/standard/core/Fetch
43328 \ @     c-addr -- char   fetch char from memory
43329 CODE @
43330 MOV @TOS,TOS
43331 MOV @IP+,PC
43332 ENDCODE
43333 [THEN]
43334
43335 [UNDEFINED] CONSTANT [IF]
43336 \ https://forth-standard.org/standard/core/CONSTANT
43337 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
43338 : CONSTANT 
43339 CREATE
43340 HI2LO
43341 MOV TOS,-2(W)           \   PFA = n
43342 MOV @PSP+,TOS
43343 MOV @RSP+,IP
43344 MOV @IP+,PC
43345 ENDCODE
43346 [THEN]
43347
43348 [UNDEFINED] STATE [IF]
43349 \ https://forth-standard.org/standard/core/STATE
43350 \ STATE   -- a-addr       holds compiler state
43351 STATEADR CONSTANT STATE
43352 [THEN]
43353
43354 [UNDEFINED] = [IF]
43355 \ https://forth-standard.org/standard/core/Equal
43356 \ =      x1 x2 -- flag         test x1=x2
43357 CODE =
43358 SUB @PSP+,TOS   \ 2
43359 0<> IF          \ 2
43360     AND #0,TOS  \ 1
43361     MOV @IP+,PC \ 4
43362 THEN
43363 XOR #-1,TOS     \ 1 flag Z = 1
43364 MOV @IP+,PC     \ 4
43365 ENDCODE
43366 [THEN]
43367
43368 [UNDEFINED] IF [IF]
43369 \ https://forth-standard.org/standard/core/IF
43370 \ IF       -- IFadr    initialize conditional forward branch
43371 CODE IF       \ immediate
43372 SUB #2,PSP              \
43373 MOV TOS,0(PSP)          \
43374 MOV &DP,TOS             \ -- HERE
43375 ADD #4,&DP            \           compile one word, reserve one word
43376 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
43377 ADD #2,TOS              \ -- HERE+2=IFadr
43378 MOV @IP+,PC
43379 ENDCODE IMMEDIATE
43380 [THEN]
43381
43382 [UNDEFINED] THEN [IF]
43383 \ https://forth-standard.org/standard/core/THEN
43384 \ THEN     IFadr --                resolve forward branch
43385 CODE THEN               \ immediate
43386 MOV &DP,0(TOS)          \ -- IFadr
43387 MOV @PSP+,TOS           \ --
43388 MOV @IP+,PC
43389 ENDCODE IMMEDIATE
43390 [THEN]
43391
43392 [UNDEFINED] ELSE [IF]
43393 \ https://forth-standard.org/standard/core/ELSE
43394 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
43395 CODE ELSE     \ immediate
43396 ADD #4,&DP              \ make room to compile two words
43397 MOV &DP,W               \ W=HERE+4
43398 MOV #BRAN,-4(W)
43399 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
43400 SUB #2,W                \ HERE+2
43401 MOV W,TOS               \ -- ELSEadr
43402 MOV @IP+,PC
43403 ENDCODE IMMEDIATE
43404 [THEN]
43405
43406 [UNDEFINED] DEFER [IF]
43407 \ https://forth-standard.org/standard/core/DEFER
43408 \ DEFER "<spaces>name"   --
43409 \ Skip leading space delimiters. Parse name delimited by a space.
43410 \ Create a definition for name with the execution semantics defined below.
43411
43412 \ name Execution:   --
43413 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
43414 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
43415 : DEFER
43416 CREATE
43417 HI2LO
43418 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
43419 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
43420 MOV @RSP+,IP
43421 MOV @IP+,PC
43422 ENDCODE
43423 [THEN]
43424
43425 [UNDEFINED] DEFER! [IF]
43426 \ https://forth-standard.org/standard/core/DEFERStore
43427 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
43428 CODE DEFER!             \ xt2 xt1 --
43429 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
43430 MOV @PSP+,TOS           \ --
43431 MOV @IP+,PC
43432 ENDCODE
43433 [THEN]
43434
43435 [UNDEFINED] IS [IF]
43436 \ https://forth-standard.org/standard/core/IS
43437 \ IS <name>        xt --
43438 \ used as is :
43439 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
43440 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
43441 \ or in a definition : ... ['] U. IS DISPLAY ...
43442 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
43443 \
43444 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
43445 : IS
43446 STATE @
43447 IF  POSTPONE ['] POSTPONE DEFER! 
43448 ELSE ' DEFER! 
43449 THEN
43450 ; IMMEDIATE
43451 [THEN]
43452
43453 [UNDEFINED] >BODY [IF]
43454 \ https://forth-standard.org/standard/core/toBODY
43455 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
43456 CODE >BODY
43457 ADD #4,TOS
43458 MOV @IP+,PC
43459 ENDCODE
43460 [THEN]
43461
43462 \ CODE 20uS           \ n --      8MHz version
43463 \ BEGIN               \ 4 + 16 ~ loop
43464 \     MOV #39,rDOCON   \ 39
43465 \     BEGIN           \ 4 ~ loop
43466 \         NOP
43467 \         SUB #1,rDOCON
43468 \     0=  UNTIL
43469 \     SUB #1,TOS      \ 1
43470 \ 0= UNTIL
43471 \ MOV #XDOCON,rDOCON  \ 2
43472 \ MOV @PSP+,TOS
43473 \ MOV @RSP+,IP        \
43474 \ ENDCODE
43475
43476 CODE 20_US                      \ n --      n * 20 us
43477 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
43478     BEGIN
43479         BIT #1,&LCD_TIM_CTL     \ 3
43480     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
43481     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
43482     SUB #1,TOS                  \ 1
43483 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
43484 MOV @PSP+,TOS                   \ 2
43485 MOV @IP+,PC                     \ 4
43486 ENDCODE
43487
43488 CODE TOP_LCD                    \ LCD Sample
43489 \                               \ if write : %xxxx_WWWW --
43490 \                               \ if read  : -- %0000_RRRR
43491     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
43492     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
43493 0= IF                           \ write LCD bits pattern
43494     AND.B #LCD_DB,TOS           \ 
43495     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
43496     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
43497     MOV @PSP+,TOS               \
43498     MOV @IP+,PC
43499 THEN                            \ read LCD bits pattern
43500     SUB #2,PSP
43501     MOV TOS,0(PSP)
43502     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
43503     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
43504     AND.B #LCD_DB,TOS           \
43505     MOV @IP+,PC
43506 ENDCODE
43507
43508 CODE LCD_WRC                    \ char --         Write Char
43509     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
43510 BW1 SUB #2,PSP                  \
43511     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
43512     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
43513     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
43514     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
43515 COLON                           \ high level word starts here 
43516     TOP_LCD 2 20_US             \ write high nibble first
43517     TOP_LCD 2 20_US 
43518 ;
43519
43520 CODE LCD_WRF                    \ func --         Write Fonction
43521     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
43522     GOTO BW1
43523 ENDCODE
43524
43525 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
43526 : LCD_HOME $02 LCD_WRF 100 20_us ;
43527
43528 \ [UNDEFINED] OR [IF]
43529
43530 \ \ https://forth-standard.org/standard/core/OR
43531 \ \ C OR     x1 x2 -- x3           logical OR
43532 \ CODE OR
43533 \ BIS @PSP+,TOS
43534 \ MOV @IP+,PC
43535 \ ENDCODE
43536
43537 \ [THEN]
43538
43539 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
43540 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
43541 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
43542 \ : LCD_FN_SET        $20 OR LCD_WrF ;
43543 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
43544 \ : LCD_GOTO          $80 OR LCD_WrF ;
43545
43546
43547 \ CODE LCD_RDS                    \ -- status       Read Status
43548 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
43549 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
43550 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
43551 \ COLON                           \ starts a FORTH word
43552 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
43553 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
43554 \ HI2LO                           \ switch from FORTH to assembler
43555 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
43556 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
43557 \     MOV @RSP+,IP                \ restore IP saved by COLON
43558 \     MOV @IP+,PC                 \
43559 \ ENDCODE
43560
43561 \ CODE LCD_RDC                    \ -- char         Read Char
43562 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
43563 \     GOTO BW1
43564 \ ENDCODE
43565
43566
43567 \ ******************************\
43568 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
43569 \ ******************************\
43570 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
43571 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
43572 BIT.B #SW2,&SW2_IN              \ test switch S2
43573 0= IF                           \ case of switch S2 pressed
43574     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
43575     U< IF
43576         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
43577     THEN
43578 ELSE
43579     BIT.B #SW1,&SW1_IN          \ test switch S1 input
43580     0= IF                       \ case of Switch S1 pressed
43581         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
43582         U>= IF                  \
43583            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
43584         THEN                    \
43585     THEN                        \
43586 THEN                            \
43587 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
43588 RET                             \ 5
43589 ENDASM
43590
43591 \ ******************************\
43592 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
43593 \ ******************************\
43594 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
43595 \ ******************************\
43596 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
43597 \                               \       SMclock = 8|16|24 MHz
43598 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
43599 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
43600 \                               \       SR(9)=new Toggle bit memory (ADD on)
43601 \ ******************************\
43602 \ RC5_FirstStartBitHalfCycle:   \
43603 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
43604 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
43605 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
43606 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
43607 \ [THEN]
43608 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
43609     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
43610 [THEN]
43611 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
43612     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
43613 [THEN]
43614 MOV #1778,X                     \ RC5_Period * 1us
43615 MOV #14,W                       \ count of loop
43616 BEGIN                           \
43617 \ ******************************\
43618 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
43619 \ ******************************\                   |
43620 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
43621 \ RC5_Compute_3/4_Period:       \                   |
43622     RRUM    #1,X                \ X=1/2 cycle       |
43623     MOV     X,Y                 \                   ^
43624     RRUM    #1,Y                \ Y=1/4
43625     ADD     X,Y                 \ Y=3/4 cycle
43626     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
43627     U>= UNTIL                   \ 2
43628 \ ******************************\
43629 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
43630 \ ******************************\
43631     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
43632     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
43633     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
43634     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
43635     SUB     #1,W                \ decrement count loop
43636 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
43637 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
43638 0<> WHILE                       \ ----> out of loop ----+
43639     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
43640     BEGIN                       \                       |
43641         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
43642         CMP Y,X                 \ 1                     |   cycle time out of bound ?
43643         U>= IF                  \ 2                 ^   |   yes:
43644         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
43645         GOTO BW1                \                   |   |      quit on truncated RC5 message
43646         THEN                    \                   |   |
43647         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
43648     0<> UNTIL                   \ 2                 |   |
43649 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
43650 \ ******************************\                       |
43651 \ RC5_SampleEndOf:              \ <---------------------+
43652 \ ******************************\
43653 BIC #$30,&RC5_TIM_CTL           \   stop timer
43654 \ ******************************\
43655 \ RC5_ComputeNewRC5word         \
43656 \ ******************************\
43657 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
43658 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
43659 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
43660 \ ******************************\
43661 \ RC5_ComputeC6bit              \
43662 \ ******************************\
43663 BIT     #BIT14,T                \ test /C6 bit in T
43664 0= IF   BIS #BIT6,X             \ set C6 bit in X
43665 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
43666 \ ******************************\
43667 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
43668 \ ******************************\
43669 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
43670 \ ******************************\
43671 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
43672 XOR     @RSP,T                  \ (new XOR old) Toggle bits
43673 BIT     #UF10,T                 \ repeated RC5_command ?
43674 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
43675 XOR #UF10,0(RSP)                \ 5 toggle bit memory
43676 \ ******************************\
43677 \ Display IR_RC5 code           \
43678 \ ******************************\
43679 SUB #8,PSP                      \ TOS -- x x x x TOS
43680 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
43681 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
43682 MOV #$10,&BASEADR               \                                               set hexadecimal base
43683 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
43684 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
43685 LO2HI                           \                                               switch from assembler to FORTH
43686     LCD_CLEAR                   \                                               set LCD cursor at home
43687     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
43688     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
43689     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
43690     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
43691 HI2LO                           \     --                                        switch from FORTH to assembler
43692 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
43693 MOV @PSP+,TOS                   \     -- TOS
43694 RET
43695 ENDASM
43696
43697 \ ******************************\
43698 ASM BACKGROUND                  \
43699 \ ******************************\
43700 BEGIN
43701 \     ...                         \ insert here your background task
43702 \     ...                         \
43703 \     ...                         \
43704     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
43705     BIS &LPM_MODE,SR            \
43706 \ ******************************\
43707 \ here start all interrupts     \
43708 \ ******************************\
43709 \ here return all interrupts    \
43710 \ ******************************\
43711 AGAIN                           \
43712 ENDASM                          \
43713 \ ******************************\
43714
43715 \ ------------------------------\
43716 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
43717 \ ------------------------------\
43718 \     ...                         \ init specific I/O sys as you want
43719 \     ...                         \ before executing default WARM
43720     MOV #WARM,X                 \ ['] WARM 
43721     ADD #4,X                    \ >BODY
43722     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
43723 ENDASM
43724 \ ------------------------------\
43725
43726 \ ------------------------------\
43727 CODE STOP                       \ stops multitasking, must to be used before downloading app
43728 \ ------------------------------\
43729 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
43730     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
43731     MOV X,-2(X)                 \ restore the default background: SLEEP
43732     MOV #WARM,X
43733     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
43734     BIC.B #RC5,&IR_IE           \ clear RC5_Int
43735     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
43736     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
43737     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
43738     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
43739     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
43740 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
43741 ECHO                            \
43742 ." RC5toLCD is removed,"
43743 ."  type START to restart"
43744  WARM                           \ performs reset to reset all interrupt vectors.    
43745 ;
43746 \ ------------------------------\
43747
43748 \ ------------------------------\
43749 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
43750 \ ------------------------------\
43751 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
43752 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
43753 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
43754 \                           --       \ID input divider \ 10 = /4
43755 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
43756 \                                 -  \TBCLR TimerB Clear
43757 \                                  - \TBIE
43758 \                                   -\TBIFG
43759 \ -------------------------------\
43760 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
43761 \                  --                 \CM Capture Mode
43762 \                    --               \CCIS
43763 \                       -             \SCS
43764 \                        --           \CLLD
43765 \                          -          \CAP
43766 \                            ---      \OUTMOD \ 011 = set/reset
43767 \                               -     \CCIE
43768 \                                 -   \CCI
43769 \                                  -  \OUT
43770 \                                   - \COV
43771 \                                    -\CCIFG
43772 \ -------------------------------\
43773 \ LCD_TIM_CCRx                   \
43774 \ -------------------------------\
43775 \ LCD_TIM_EX0                    \ 
43776 \ ------------------------------\
43777 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
43778 \ ------------------------------\
43779 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
43780 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
43781 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
43782     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
43783 [THEN]
43784 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
43785     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
43786 [THEN]
43787     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
43788 \ ------------------------------\
43789 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
43790 \ ------------------------------\
43791 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
43792     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
43793 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
43794 \ ------------------------------\
43795     BIS.B #LCDVo,&LCDVo_DIR     \
43796     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
43797 \ ------------------------------\
43798     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
43799     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
43800 \ ------------------------------\
43801     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
43802     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
43803 \ ******************************\
43804 \ init RC5_Int                  \
43805 \ ******************************\
43806     BIS.B #RC5,&IR_IE           \ enable RC5_Int
43807     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
43808     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
43809 \ ******************************\
43810 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
43811 \ ******************************\
43812 \              %01 0001 0100    \ TAxCTL
43813 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
43814 \                  --           \ ID        divided by 1
43815 \                    --         \ MC        MODE = up to TAxCCRn
43816 \                        -      \ TACLR     clear timer count
43817 \                         -     \ TAIE
43818 \                          -    \ TAIFG
43819 \ ------------------------------\
43820 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
43821 \ ------------------------------\
43822 \                        000    \ TAxEX0
43823 \                        ---    \ TAIDEX    pre divisor
43824 \ ------------------------------\
43825 \          %0000 0000 0000 0101 \ TAxCCR0
43826     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
43827 \ ------------------------------\
43828 \          %0000 0000 0001 0000 \ TAxCCTL0
43829 \                   -           \ CAP capture/compare mode = compare
43830 \                        -      \ CCIEn
43831 \                             - \ CCIFGn
43832     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
43833 \ ------------------------------\
43834     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
43835 \ ------------------------------\
43836 \ define LPM mode for ACCEPT    \
43837 \ ------------------------------\
43838 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
43839 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
43840 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
43841 \ ------------------------------\
43842 \ activate I/O                  \
43843 \ ------------------------------\
43844 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
43845 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
43846 \ ------------------------------\
43847 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
43848 \ ------------------------------\
43849 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
43850 \ CMP #2,Y                        \ Power_ON event
43851 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
43852 CMP #4,Y                        \
43853 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
43854 \ CMP #6,Y                        \
43855 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
43856 \ CMP #$0A,Y                      \
43857 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
43858 \ CMP #$16,Y                      \
43859 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
43860 \ ------------------------------\
43861 COLON                           \
43862 \ ------------------------------\
43863 \ Init LCD 2x20                 \
43864 \ ------------------------------\
43865     #1000 20_US                 \ 1- wait 20 ms
43866     %011 TOP_LCD                \ 2- send DB5=DB4=1
43867     #205 20_US                  \ 3- wait 4,1 ms
43868     %011 TOP_LCD                \ 4- send again DB5=DB4=1
43869     #5 20_US                    \ 5- wait 0,1 ms
43870     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
43871     #2 20_US                    \    wait 40 us = LCD cycle
43872     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
43873     #2 20_US                    \    wait 40 us = LCD cycle
43874     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
43875     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
43876     LCD_CLEAR                   \ 10- "LCD_Clear"
43877     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
43878     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
43879     LCD_CLEAR                   \ 10- "LCD_Clear"
43880     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
43881     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
43882     CR ." I love you"           \ display message on LCD
43883     ['] CR >BODY IS CR          \ CR executes its default value
43884     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
43885     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
43886     PWR_STATE ABORT             \ init DP and continues with ABORT
43887 ;                               \
43888 \ ------------------------------\
43889
43890 \ ------------------------------\
43891 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
43892 \ ------------------------------\
43893 MOV #SLEEP,X                    \ replace default background process SLEEP
43894 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
43895 MOV #WARM,X                     \ replace default WARM
43896 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
43897 MOV X,PC                        \ then execute new WARM
43898 ENDCODE 
43899 \ ------------------------------\
43900
43901 ECHO
43902             ; downloading RC5toLCD.4th is done
43903 RST_HERE    ; this app is protected against <reset>
43904
43905
43906 RST_STATE
43907
43908 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
43909
43910 [UNDEFINED] MARKER [IF]
43911 \  https://forth-standard.org/standard/core/MARKER
43912 \  MARKER
43913 \ ( "<spaces>name" -- )
43914 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
43915 \ with the execution semantics defined below.
43916
43917 \ name Execution: ( -- )
43918 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
43919 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
43920 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
43921 \ not necessarily provided. No other contextual information such as numeric base is affected
43922 \
43923 : MARKER
43924 CREATE
43925 HI2LO
43926 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
43927 SUB #2,Y            \ 1 Y = LFA
43928 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
43929 ADD #4,&DP          \ 3 add 2 cells
43930 LO2HI
43931 DOES>
43932 HI2LO
43933 MOV @RSP+,IP        \ -- PFA
43934 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
43935 MOV @TOS,&INIDP     \       set DP value for RST_STATE
43936 MOV @PSP+,TOS       \ --
43937 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
43938 ENDCODE
43939 [THEN]
43940
43941 MARKER {RC5TOLCD}
43942
43943 [UNDEFINED] @ [IF]
43944 \ https://forth-standard.org/standard/core/Fetch
43945 \ @     c-addr -- char   fetch char from memory
43946 CODE @
43947 MOV @TOS,TOS
43948 MOV @IP+,PC
43949 ENDCODE
43950 [THEN]
43951
43952 [UNDEFINED] CONSTANT [IF]
43953 \ https://forth-standard.org/standard/core/CONSTANT
43954 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
43955 : CONSTANT 
43956 CREATE
43957 HI2LO
43958 MOV TOS,-2(W)           \   PFA = n
43959 MOV @PSP+,TOS
43960 MOV @RSP+,IP
43961 MOV @IP+,PC
43962 ENDCODE
43963 [THEN]
43964
43965 [UNDEFINED] STATE [IF]
43966 \ https://forth-standard.org/standard/core/STATE
43967 \ STATE   -- a-addr       holds compiler state
43968 STATEADR CONSTANT STATE
43969 [THEN]
43970
43971 [UNDEFINED] = [IF]
43972 \ https://forth-standard.org/standard/core/Equal
43973 \ =      x1 x2 -- flag         test x1=x2
43974 CODE =
43975 SUB @PSP+,TOS   \ 2
43976 0<> IF          \ 2
43977     AND #0,TOS  \ 1
43978     MOV @IP+,PC \ 4
43979 THEN
43980 XOR #-1,TOS     \ 1 flag Z = 1
43981 MOV @IP+,PC     \ 4
43982 ENDCODE
43983 [THEN]
43984
43985 [UNDEFINED] IF [IF]
43986 \ https://forth-standard.org/standard/core/IF
43987 \ IF       -- IFadr    initialize conditional forward branch
43988 CODE IF       \ immediate
43989 SUB #2,PSP              \
43990 MOV TOS,0(PSP)          \
43991 MOV &DP,TOS             \ -- HERE
43992 ADD #4,&DP            \           compile one word, reserve one word
43993 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
43994 ADD #2,TOS              \ -- HERE+2=IFadr
43995 MOV @IP+,PC
43996 ENDCODE IMMEDIATE
43997 [THEN]
43998
43999 [UNDEFINED] THEN [IF]
44000 \ https://forth-standard.org/standard/core/THEN
44001 \ THEN     IFadr --                resolve forward branch
44002 CODE THEN               \ immediate
44003 MOV &DP,0(TOS)          \ -- IFadr
44004 MOV @PSP+,TOS           \ --
44005 MOV @IP+,PC
44006 ENDCODE IMMEDIATE
44007 [THEN]
44008
44009 [UNDEFINED] ELSE [IF]
44010 \ https://forth-standard.org/standard/core/ELSE
44011 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
44012 CODE ELSE     \ immediate
44013 ADD #4,&DP              \ make room to compile two words
44014 MOV &DP,W               \ W=HERE+4
44015 MOV #BRAN,-4(W)
44016 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
44017 SUB #2,W                \ HERE+2
44018 MOV W,TOS               \ -- ELSEadr
44019 MOV @IP+,PC
44020 ENDCODE IMMEDIATE
44021 [THEN]
44022
44023 [UNDEFINED] DEFER [IF]
44024 \ https://forth-standard.org/standard/core/DEFER
44025 \ DEFER "<spaces>name"   --
44026 \ Skip leading space delimiters. Parse name delimited by a space.
44027 \ Create a definition for name with the execution semantics defined below.
44028
44029 \ name Execution:   --
44030 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
44031 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
44032 : DEFER
44033 CREATE
44034 HI2LO
44035 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
44036 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
44037 MOV @RSP+,IP
44038 MOV @IP+,PC
44039 ENDCODE
44040 [THEN]
44041
44042 [UNDEFINED] DEFER! [IF]
44043 \ https://forth-standard.org/standard/core/DEFERStore
44044 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
44045 CODE DEFER!             \ xt2 xt1 --
44046 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
44047 MOV @PSP+,TOS           \ --
44048 MOV @IP+,PC
44049 ENDCODE
44050 [THEN]
44051
44052 [UNDEFINED] IS [IF]
44053 \ https://forth-standard.org/standard/core/IS
44054 \ IS <name>        xt --
44055 \ used as is :
44056 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
44057 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
44058 \ or in a definition : ... ['] U. IS DISPLAY ...
44059 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
44060 \
44061 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
44062 : IS
44063 STATE @
44064 IF  POSTPONE ['] POSTPONE DEFER! 
44065 ELSE ' DEFER! 
44066 THEN
44067 ; IMMEDIATE
44068 [THEN]
44069
44070 [UNDEFINED] >BODY [IF]
44071 \ https://forth-standard.org/standard/core/toBODY
44072 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
44073 CODE >BODY
44074 ADD #4,TOS
44075 MOV @IP+,PC
44076 ENDCODE
44077 [THEN]
44078
44079 \ CODE 20uS           \ n --      8MHz version
44080 \ BEGIN               \ 4 + 16 ~ loop
44081 \     MOV #39,rDOCON   \ 39
44082 \     BEGIN           \ 4 ~ loop
44083 \         NOP
44084 \         SUB #1,rDOCON
44085 \     0=  UNTIL
44086 \     SUB #1,TOS      \ 1
44087 \ 0= UNTIL
44088 \ MOV #XDOCON,rDOCON  \ 2
44089 \ MOV @PSP+,TOS
44090 \ MOV @RSP+,IP        \
44091 \ ENDCODE
44092
44093 CODE 20_US                      \ n --      n * 20 us
44094 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
44095     BEGIN
44096         BIT #1,&LCD_TIM_CTL     \ 3
44097     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
44098     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
44099     SUB #1,TOS                  \ 1
44100 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
44101 MOV @PSP+,TOS                   \ 2
44102 MOV @IP+,PC                     \ 4
44103 ENDCODE
44104
44105 CODE TOP_LCD                    \ LCD Sample
44106 \                               \ if write : %xxxx_WWWW --
44107 \                               \ if read  : -- %0000_RRRR
44108     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
44109     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
44110 0= IF                           \ write LCD bits pattern
44111     AND.B #LCD_DB,TOS           \ 
44112     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
44113     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
44114     MOV @PSP+,TOS               \
44115     MOV @IP+,PC
44116 THEN                            \ read LCD bits pattern
44117     SUB #2,PSP
44118     MOV TOS,0(PSP)
44119     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
44120     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
44121     AND.B #LCD_DB,TOS           \
44122     MOV @IP+,PC
44123 ENDCODE
44124
44125 CODE LCD_WRC                    \ char --         Write Char
44126     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
44127 BW1 SUB #2,PSP                  \
44128     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
44129     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
44130     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
44131     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
44132 COLON                           \ high level word starts here 
44133     TOP_LCD 2 20_US             \ write high nibble first
44134     TOP_LCD 2 20_US 
44135 ;
44136
44137 CODE LCD_WRF                    \ func --         Write Fonction
44138     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
44139     GOTO BW1
44140 ENDCODE
44141
44142 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
44143 : LCD_HOME $02 LCD_WRF 100 20_us ;
44144
44145 \ [UNDEFINED] OR [IF]
44146
44147 \ \ https://forth-standard.org/standard/core/OR
44148 \ \ C OR     x1 x2 -- x3           logical OR
44149 \ CODE OR
44150 \ BIS @PSP+,TOS
44151 \ MOV @IP+,PC
44152 \ ENDCODE
44153
44154 \ [THEN]
44155
44156 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
44157 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
44158 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
44159 \ : LCD_FN_SET        $20 OR LCD_WrF ;
44160 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
44161 \ : LCD_GOTO          $80 OR LCD_WrF ;
44162
44163
44164 \ CODE LCD_RDS                    \ -- status       Read Status
44165 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
44166 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
44167 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
44168 \ COLON                           \ starts a FORTH word
44169 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
44170 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
44171 \ HI2LO                           \ switch from FORTH to assembler
44172 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
44173 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
44174 \     MOV @RSP+,IP                \ restore IP saved by COLON
44175 \     MOV @IP+,PC                 \
44176 \ ENDCODE
44177
44178 \ CODE LCD_RDC                    \ -- char         Read Char
44179 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
44180 \     GOTO BW1
44181 \ ENDCODE
44182
44183
44184 \ ******************************\
44185 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
44186 \ ******************************\
44187 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
44188 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
44189 BIT.B #SW2,&SW2_IN              \ test switch S2
44190 0= IF                           \ case of switch S2 pressed
44191     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
44192     U< IF
44193         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
44194     THEN
44195 ELSE
44196     BIT.B #SW1,&SW1_IN          \ test switch S1 input
44197     0= IF                       \ case of Switch S1 pressed
44198         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
44199         U>= IF                  \
44200            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
44201         THEN                    \
44202     THEN                        \
44203 THEN                            \
44204 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
44205 RET                             \ 5
44206 ENDASM
44207
44208 \ ******************************\
44209 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
44210 \ ******************************\
44211 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
44212 \ ******************************\
44213 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
44214 \                               \       SMclock = 8|16|24 MHz
44215 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
44216 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
44217 \                               \       SR(9)=new Toggle bit memory (ADD on)
44218 \ ******************************\
44219 \ RC5_FirstStartBitHalfCycle:   \
44220 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
44221 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
44222 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
44223 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
44224 \ [THEN]
44225 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
44226     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
44227 [THEN]
44228 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
44229     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
44230 [THEN]
44231 MOV #1778,X                     \ RC5_Period * 1us
44232 MOV #14,W                       \ count of loop
44233 BEGIN                           \
44234 \ ******************************\
44235 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
44236 \ ******************************\                   |
44237 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
44238 \ RC5_Compute_3/4_Period:       \                   |
44239     RRUM    #1,X                \ X=1/2 cycle       |
44240     MOV     X,Y                 \                   ^
44241     RRUM    #1,Y                \ Y=1/4
44242     ADD     X,Y                 \ Y=3/4 cycle
44243     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
44244     U>= UNTIL                   \ 2
44245 \ ******************************\
44246 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
44247 \ ******************************\
44248     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
44249     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
44250     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
44251     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
44252     SUB     #1,W                \ decrement count loop
44253 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
44254 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
44255 0<> WHILE                       \ ----> out of loop ----+
44256     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
44257     BEGIN                       \                       |
44258         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
44259         CMP Y,X                 \ 1                     |   cycle time out of bound ?
44260         U>= IF                  \ 2                 ^   |   yes:
44261         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
44262         GOTO BW1                \                   |   |      quit on truncated RC5 message
44263         THEN                    \                   |   |
44264         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
44265     0<> UNTIL                   \ 2                 |   |
44266 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
44267 \ ******************************\                       |
44268 \ RC5_SampleEndOf:              \ <---------------------+
44269 \ ******************************\
44270 BIC #$30,&RC5_TIM_CTL           \   stop timer
44271 \ ******************************\
44272 \ RC5_ComputeNewRC5word         \
44273 \ ******************************\
44274 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
44275 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
44276 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
44277 \ ******************************\
44278 \ RC5_ComputeC6bit              \
44279 \ ******************************\
44280 BIT     #BIT14,T                \ test /C6 bit in T
44281 0= IF   BIS #BIT6,X             \ set C6 bit in X
44282 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
44283 \ ******************************\
44284 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
44285 \ ******************************\
44286 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
44287 \ ******************************\
44288 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
44289 XOR     @RSP,T                  \ (new XOR old) Toggle bits
44290 BIT     #UF10,T                 \ repeated RC5_command ?
44291 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
44292 XOR #UF10,0(RSP)                \ 5 toggle bit memory
44293 \ ******************************\
44294 \ Display IR_RC5 code           \
44295 \ ******************************\
44296 SUB #8,PSP                      \ TOS -- x x x x TOS
44297 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
44298 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
44299 MOV #$10,&BASEADR               \                                               set hexadecimal base
44300 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
44301 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
44302 LO2HI                           \                                               switch from assembler to FORTH
44303     LCD_CLEAR                   \                                               set LCD cursor at home
44304     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
44305     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
44306     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
44307     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
44308 HI2LO                           \     --                                        switch from FORTH to assembler
44309 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
44310 MOV @PSP+,TOS                   \     -- TOS
44311 RET
44312 ENDASM
44313
44314 \ ******************************\
44315 ASM BACKGROUND                  \
44316 \ ******************************\
44317 BEGIN
44318 \     ...                         \ insert here your background task
44319 \     ...                         \
44320 \     ...                         \
44321     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
44322     BIS &LPM_MODE,SR            \
44323 \ ******************************\
44324 \ here start all interrupts     \
44325 \ ******************************\
44326 \ here return all interrupts    \
44327 \ ******************************\
44328 AGAIN                           \
44329 ENDASM                          \
44330 \ ******************************\
44331
44332 \ ------------------------------\
44333 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
44334 \ ------------------------------\
44335 \     ...                         \ init specific I/O sys as you want
44336 \     ...                         \ before executing default WARM
44337     MOV #WARM,X                 \ ['] WARM 
44338     ADD #4,X                    \ >BODY
44339     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
44340 ENDASM
44341 \ ------------------------------\
44342
44343 \ ------------------------------\
44344 CODE STOP                       \ stops multitasking, must to be used before downloading app
44345 \ ------------------------------\
44346 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
44347     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
44348     MOV X,-2(X)                 \ restore the default background: SLEEP
44349     MOV #WARM,X
44350     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
44351     BIC.B #RC5,&IR_IE           \ clear RC5_Int
44352     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
44353     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
44354     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
44355     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
44356     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
44357 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
44358 ECHO                            \
44359 ." RC5toLCD is removed,"
44360 ."  type START to restart"
44361  WARM                           \ performs reset to reset all interrupt vectors.    
44362 ;
44363 \ ------------------------------\
44364
44365 \ ------------------------------\
44366 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
44367 \ ------------------------------\
44368 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
44369 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
44370 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
44371 \                           --       \ID input divider \ 10 = /4
44372 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
44373 \                                 -  \TBCLR TimerB Clear
44374 \                                  - \TBIE
44375 \                                   -\TBIFG
44376 \ -------------------------------\
44377 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
44378 \                  --                 \CM Capture Mode
44379 \                    --               \CCIS
44380 \                       -             \SCS
44381 \                        --           \CLLD
44382 \                          -          \CAP
44383 \                            ---      \OUTMOD \ 011 = set/reset
44384 \                               -     \CCIE
44385 \                                 -   \CCI
44386 \                                  -  \OUT
44387 \                                   - \COV
44388 \                                    -\CCIFG
44389 \ -------------------------------\
44390 \ LCD_TIM_CCRx                   \
44391 \ -------------------------------\
44392 \ LCD_TIM_EX0                    \ 
44393 \ ------------------------------\
44394 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
44395 \ ------------------------------\
44396 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
44397 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
44398 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
44399     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
44400 [THEN]
44401 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
44402     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
44403 [THEN]
44404     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
44405 \ ------------------------------\
44406 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
44407 \ ------------------------------\
44408 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
44409     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
44410 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
44411 \ ------------------------------\
44412     BIS.B #LCDVo,&LCDVo_DIR     \
44413     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
44414 \ ------------------------------\
44415     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
44416     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
44417 \ ------------------------------\
44418     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
44419     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
44420 \ ******************************\
44421 \ init RC5_Int                  \
44422 \ ******************************\
44423     BIS.B #RC5,&IR_IE           \ enable RC5_Int
44424     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
44425     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
44426 \ ******************************\
44427 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
44428 \ ******************************\
44429 \              %01 0001 0100    \ TAxCTL
44430 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
44431 \                  --           \ ID        divided by 1
44432 \                    --         \ MC        MODE = up to TAxCCRn
44433 \                        -      \ TACLR     clear timer count
44434 \                         -     \ TAIE
44435 \                          -    \ TAIFG
44436 \ ------------------------------\
44437 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
44438 \ ------------------------------\
44439 \                        000    \ TAxEX0
44440 \                        ---    \ TAIDEX    pre divisor
44441 \ ------------------------------\
44442 \          %0000 0000 0000 0101 \ TAxCCR0
44443     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
44444 \ ------------------------------\
44445 \          %0000 0000 0001 0000 \ TAxCCTL0
44446 \                   -           \ CAP capture/compare mode = compare
44447 \                        -      \ CCIEn
44448 \                             - \ CCIFGn
44449     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
44450 \ ------------------------------\
44451     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
44452 \ ------------------------------\
44453 \ define LPM mode for ACCEPT    \
44454 \ ------------------------------\
44455 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
44456 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
44457 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
44458 \ ------------------------------\
44459 \ activate I/O                  \
44460 \ ------------------------------\
44461 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
44462 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
44463 \ ------------------------------\
44464 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
44465 \ ------------------------------\
44466 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
44467 \ CMP #2,Y                        \ Power_ON event
44468 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
44469 CMP #4,Y                        \
44470 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
44471 \ CMP #6,Y                        \
44472 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
44473 \ CMP #$0A,Y                      \
44474 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
44475 \ CMP #$16,Y                      \
44476 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
44477 \ ------------------------------\
44478 COLON                           \
44479 \ ------------------------------\
44480 \ Init LCD 2x20                 \
44481 \ ------------------------------\
44482     #1000 20_US                 \ 1- wait 20 ms
44483     %011 TOP_LCD                \ 2- send DB5=DB4=1
44484     #205 20_US                  \ 3- wait 4,1 ms
44485     %011 TOP_LCD                \ 4- send again DB5=DB4=1
44486     #5 20_US                    \ 5- wait 0,1 ms
44487     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
44488     #2 20_US                    \    wait 40 us = LCD cycle
44489     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
44490     #2 20_US                    \    wait 40 us = LCD cycle
44491     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
44492     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
44493     LCD_CLEAR                   \ 10- "LCD_Clear"
44494     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
44495     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
44496     LCD_CLEAR                   \ 10- "LCD_Clear"
44497     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
44498     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
44499     CR ." I love you"           \ display message on LCD
44500     ['] CR >BODY IS CR          \ CR executes its default value
44501     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
44502     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
44503     PWR_STATE ABORT             \ init DP and continues with ABORT
44504 ;                               \
44505 \ ------------------------------\
44506
44507 \ ------------------------------\
44508 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
44509 \ ------------------------------\
44510 MOV #SLEEP,X                    \ replace default background process SLEEP
44511 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
44512 MOV #WARM,X                     \ replace default WARM
44513 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
44514 MOV X,PC                        \ then execute new WARM
44515 ENDCODE 
44516 \ ------------------------------\
44517
44518 ECHO
44519             ; downloading RC5toLCD.4th is done
44520 RST_HERE    ; this app is protected against <reset>
44521
44522
44523 RST_STATE
44524
44525 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
44526
44527 [UNDEFINED] MARKER [IF]
44528 \  https://forth-standard.org/standard/core/MARKER
44529 \  MARKER
44530 \ ( "<spaces>name" -- )
44531 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
44532 \ with the execution semantics defined below.
44533
44534 \ name Execution: ( -- )
44535 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
44536 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
44537 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
44538 \ not necessarily provided. No other contextual information such as numeric base is affected
44539 \
44540 : MARKER
44541 CREATE
44542 HI2LO
44543 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
44544 SUB #2,Y            \ 1 Y = LFA
44545 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
44546 ADD #4,&DP          \ 3 add 2 cells
44547 LO2HI
44548 DOES>
44549 HI2LO
44550 MOV @RSP+,IP        \ -- PFA
44551 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
44552 MOV @TOS,&INIDP     \       set DP value for RST_STATE
44553 MOV @PSP+,TOS       \ --
44554 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
44555 ENDCODE
44556 [THEN]
44557
44558 MARKER {RC5TOLCD}
44559
44560 [UNDEFINED] @ [IF]
44561 \ https://forth-standard.org/standard/core/Fetch
44562 \ @     c-addr -- char   fetch char from memory
44563 CODE @
44564 MOV @TOS,TOS
44565 MOV @IP+,PC
44566 ENDCODE
44567 [THEN]
44568
44569 [UNDEFINED] CONSTANT [IF]
44570 \ https://forth-standard.org/standard/core/CONSTANT
44571 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
44572 : CONSTANT 
44573 CREATE
44574 HI2LO
44575 MOV TOS,-2(W)           \   PFA = n
44576 MOV @PSP+,TOS
44577 MOV @RSP+,IP
44578 MOV @IP+,PC
44579 ENDCODE
44580 [THEN]
44581
44582 [UNDEFINED] STATE [IF]
44583 \ https://forth-standard.org/standard/core/STATE
44584 \ STATE   -- a-addr       holds compiler state
44585 STATEADR CONSTANT STATE
44586 [THEN]
44587
44588 [UNDEFINED] = [IF]
44589 \ https://forth-standard.org/standard/core/Equal
44590 \ =      x1 x2 -- flag         test x1=x2
44591 CODE =
44592 SUB @PSP+,TOS   \ 2
44593 0<> IF          \ 2
44594     AND #0,TOS  \ 1
44595     MOV @IP+,PC \ 4
44596 THEN
44597 XOR #-1,TOS     \ 1 flag Z = 1
44598 MOV @IP+,PC     \ 4
44599 ENDCODE
44600 [THEN]
44601
44602 [UNDEFINED] IF [IF]
44603 \ https://forth-standard.org/standard/core/IF
44604 \ IF       -- IFadr    initialize conditional forward branch
44605 CODE IF       \ immediate
44606 SUB #2,PSP              \
44607 MOV TOS,0(PSP)          \
44608 MOV &DP,TOS             \ -- HERE
44609 ADD #4,&DP            \           compile one word, reserve one word
44610 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
44611 ADD #2,TOS              \ -- HERE+2=IFadr
44612 MOV @IP+,PC
44613 ENDCODE IMMEDIATE
44614 [THEN]
44615
44616 [UNDEFINED] THEN [IF]
44617 \ https://forth-standard.org/standard/core/THEN
44618 \ THEN     IFadr --                resolve forward branch
44619 CODE THEN               \ immediate
44620 MOV &DP,0(TOS)          \ -- IFadr
44621 MOV @PSP+,TOS           \ --
44622 MOV @IP+,PC
44623 ENDCODE IMMEDIATE
44624 [THEN]
44625
44626 [UNDEFINED] ELSE [IF]
44627 \ https://forth-standard.org/standard/core/ELSE
44628 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
44629 CODE ELSE     \ immediate
44630 ADD #4,&DP              \ make room to compile two words
44631 MOV &DP,W               \ W=HERE+4
44632 MOV #BRAN,-4(W)
44633 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
44634 SUB #2,W                \ HERE+2
44635 MOV W,TOS               \ -- ELSEadr
44636 MOV @IP+,PC
44637 ENDCODE IMMEDIATE
44638 [THEN]
44639
44640 [UNDEFINED] DEFER [IF]
44641 \ https://forth-standard.org/standard/core/DEFER
44642 \ DEFER "<spaces>name"   --
44643 \ Skip leading space delimiters. Parse name delimited by a space.
44644 \ Create a definition for name with the execution semantics defined below.
44645
44646 \ name Execution:   --
44647 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
44648 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
44649 : DEFER
44650 CREATE
44651 HI2LO
44652 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
44653 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
44654 MOV @RSP+,IP
44655 MOV @IP+,PC
44656 ENDCODE
44657 [THEN]
44658
44659 [UNDEFINED] DEFER! [IF]
44660 \ https://forth-standard.org/standard/core/DEFERStore
44661 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
44662 CODE DEFER!             \ xt2 xt1 --
44663 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
44664 MOV @PSP+,TOS           \ --
44665 MOV @IP+,PC
44666 ENDCODE
44667 [THEN]
44668
44669 [UNDEFINED] IS [IF]
44670 \ https://forth-standard.org/standard/core/IS
44671 \ IS <name>        xt --
44672 \ used as is :
44673 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
44674 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
44675 \ or in a definition : ... ['] U. IS DISPLAY ...
44676 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
44677 \
44678 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
44679 : IS
44680 STATE @
44681 IF  POSTPONE ['] POSTPONE DEFER! 
44682 ELSE ' DEFER! 
44683 THEN
44684 ; IMMEDIATE
44685 [THEN]
44686
44687 [UNDEFINED] >BODY [IF]
44688 \ https://forth-standard.org/standard/core/toBODY
44689 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
44690 CODE >BODY
44691 ADD #4,TOS
44692 MOV @IP+,PC
44693 ENDCODE
44694 [THEN]
44695
44696 \ CODE 20uS           \ n --      8MHz version
44697 \ BEGIN               \ 4 + 16 ~ loop
44698 \     MOV #39,rDOCON   \ 39
44699 \     BEGIN           \ 4 ~ loop
44700 \         NOP
44701 \         SUB #1,rDOCON
44702 \     0=  UNTIL
44703 \     SUB #1,TOS      \ 1
44704 \ 0= UNTIL
44705 \ MOV #XDOCON,rDOCON  \ 2
44706 \ MOV @PSP+,TOS
44707 \ MOV @RSP+,IP        \
44708 \ ENDCODE
44709
44710 CODE 20_US                      \ n --      n * 20 us
44711 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
44712     BEGIN
44713         BIT #1,&LCD_TIM_CTL     \ 3
44714     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
44715     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
44716     SUB #1,TOS                  \ 1
44717 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
44718 MOV @PSP+,TOS                   \ 2
44719 MOV @IP+,PC                     \ 4
44720 ENDCODE
44721
44722 CODE TOP_LCD                    \ LCD Sample
44723 \                               \ if write : %xxxx_WWWW --
44724 \                               \ if read  : -- %0000_RRRR
44725     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
44726     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
44727 0= IF                           \ write LCD bits pattern
44728     AND.B #LCD_DB,TOS           \ 
44729     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
44730     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
44731     MOV @PSP+,TOS               \
44732     MOV @IP+,PC
44733 THEN                            \ read LCD bits pattern
44734     SUB #2,PSP
44735     MOV TOS,0(PSP)
44736     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
44737     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
44738     AND.B #LCD_DB,TOS           \
44739     MOV @IP+,PC
44740 ENDCODE
44741
44742 CODE LCD_WRC                    \ char --         Write Char
44743     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
44744 BW1 SUB #2,PSP                  \
44745     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
44746     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
44747     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
44748     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
44749 COLON                           \ high level word starts here 
44750     TOP_LCD 2 20_US             \ write high nibble first
44751     TOP_LCD 2 20_US 
44752 ;
44753
44754 CODE LCD_WRF                    \ func --         Write Fonction
44755     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
44756     GOTO BW1
44757 ENDCODE
44758
44759 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
44760 : LCD_HOME $02 LCD_WRF 100 20_us ;
44761
44762 \ [UNDEFINED] OR [IF]
44763
44764 \ \ https://forth-standard.org/standard/core/OR
44765 \ \ C OR     x1 x2 -- x3           logical OR
44766 \ CODE OR
44767 \ BIS @PSP+,TOS
44768 \ MOV @IP+,PC
44769 \ ENDCODE
44770
44771 \ [THEN]
44772
44773 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
44774 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
44775 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
44776 \ : LCD_FN_SET        $20 OR LCD_WrF ;
44777 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
44778 \ : LCD_GOTO          $80 OR LCD_WrF ;
44779
44780
44781 \ CODE LCD_RDS                    \ -- status       Read Status
44782 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
44783 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
44784 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
44785 \ COLON                           \ starts a FORTH word
44786 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
44787 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
44788 \ HI2LO                           \ switch from FORTH to assembler
44789 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
44790 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
44791 \     MOV @RSP+,IP                \ restore IP saved by COLON
44792 \     MOV @IP+,PC                 \
44793 \ ENDCODE
44794
44795 \ CODE LCD_RDC                    \ -- char         Read Char
44796 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
44797 \     GOTO BW1
44798 \ ENDCODE
44799
44800
44801 \ ******************************\
44802 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
44803 \ ******************************\
44804 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
44805 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
44806 BIT.B #SW2,&SW2_IN              \ test switch S2
44807 0= IF                           \ case of switch S2 pressed
44808     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
44809     U< IF
44810         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
44811     THEN
44812 ELSE
44813     BIT.B #SW1,&SW1_IN          \ test switch S1 input
44814     0= IF                       \ case of Switch S1 pressed
44815         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
44816         U>= IF                  \
44817            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
44818         THEN                    \
44819     THEN                        \
44820 THEN                            \
44821 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
44822 RET                             \ 5
44823 ENDASM
44824
44825 \ ******************************\
44826 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
44827 \ ******************************\
44828 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
44829 \ ******************************\
44830 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
44831 \                               \       SMclock = 8|16|24 MHz
44832 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
44833 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
44834 \                               \       SR(9)=new Toggle bit memory (ADD on)
44835 \ ******************************\
44836 \ RC5_FirstStartBitHalfCycle:   \
44837 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
44838 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
44839 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
44840 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
44841 \ [THEN]
44842 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
44843     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
44844 [THEN]
44845 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
44846     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
44847 [THEN]
44848 MOV #1778,X                     \ RC5_Period * 1us
44849 MOV #14,W                       \ count of loop
44850 BEGIN                           \
44851 \ ******************************\
44852 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
44853 \ ******************************\                   |
44854 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
44855 \ RC5_Compute_3/4_Period:       \                   |
44856     RRUM    #1,X                \ X=1/2 cycle       |
44857     MOV     X,Y                 \                   ^
44858     RRUM    #1,Y                \ Y=1/4
44859     ADD     X,Y                 \ Y=3/4 cycle
44860     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
44861     U>= UNTIL                   \ 2
44862 \ ******************************\
44863 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
44864 \ ******************************\
44865     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
44866     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
44867     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
44868     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
44869     SUB     #1,W                \ decrement count loop
44870 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
44871 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
44872 0<> WHILE                       \ ----> out of loop ----+
44873     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
44874     BEGIN                       \                       |
44875         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
44876         CMP Y,X                 \ 1                     |   cycle time out of bound ?
44877         U>= IF                  \ 2                 ^   |   yes:
44878         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
44879         GOTO BW1                \                   |   |      quit on truncated RC5 message
44880         THEN                    \                   |   |
44881         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
44882     0<> UNTIL                   \ 2                 |   |
44883 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
44884 \ ******************************\                       |
44885 \ RC5_SampleEndOf:              \ <---------------------+
44886 \ ******************************\
44887 BIC #$30,&RC5_TIM_CTL           \   stop timer
44888 \ ******************************\
44889 \ RC5_ComputeNewRC5word         \
44890 \ ******************************\
44891 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
44892 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
44893 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
44894 \ ******************************\
44895 \ RC5_ComputeC6bit              \
44896 \ ******************************\
44897 BIT     #BIT14,T                \ test /C6 bit in T
44898 0= IF   BIS #BIT6,X             \ set C6 bit in X
44899 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
44900 \ ******************************\
44901 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
44902 \ ******************************\
44903 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
44904 \ ******************************\
44905 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
44906 XOR     @RSP,T                  \ (new XOR old) Toggle bits
44907 BIT     #UF10,T                 \ repeated RC5_command ?
44908 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
44909 XOR #UF10,0(RSP)                \ 5 toggle bit memory
44910 \ ******************************\
44911 \ Display IR_RC5 code           \
44912 \ ******************************\
44913 SUB #8,PSP                      \ TOS -- x x x x TOS
44914 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
44915 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
44916 MOV #$10,&BASEADR               \                                               set hexadecimal base
44917 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
44918 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
44919 LO2HI                           \                                               switch from assembler to FORTH
44920     LCD_CLEAR                   \                                               set LCD cursor at home
44921     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
44922     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
44923     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
44924     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
44925 HI2LO                           \     --                                        switch from FORTH to assembler
44926 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
44927 MOV @PSP+,TOS                   \     -- TOS
44928 RET
44929 ENDASM
44930
44931 \ ******************************\
44932 ASM BACKGROUND                  \
44933 \ ******************************\
44934 BEGIN
44935 \     ...                         \ insert here your background task
44936 \     ...                         \
44937 \     ...                         \
44938     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
44939     BIS &LPM_MODE,SR            \
44940 \ ******************************\
44941 \ here start all interrupts     \
44942 \ ******************************\
44943 \ here return all interrupts    \
44944 \ ******************************\
44945 AGAIN                           \
44946 ENDASM                          \
44947 \ ******************************\
44948
44949 \ ------------------------------\
44950 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
44951 \ ------------------------------\
44952 \     ...                         \ init specific I/O sys as you want
44953 \     ...                         \ before executing default WARM
44954     MOV #WARM,X                 \ ['] WARM 
44955     ADD #4,X                    \ >BODY
44956     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
44957 ENDASM
44958 \ ------------------------------\
44959
44960 \ ------------------------------\
44961 CODE STOP                       \ stops multitasking, must to be used before downloading app
44962 \ ------------------------------\
44963 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
44964     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
44965     MOV X,-2(X)                 \ restore the default background: SLEEP
44966     MOV #WARM,X
44967     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
44968     BIC.B #RC5,&IR_IE           \ clear RC5_Int
44969     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
44970     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
44971     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
44972     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
44973     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
44974 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
44975 ECHO                            \
44976 ." RC5toLCD is removed,"
44977 ."  type START to restart"
44978  WARM                           \ performs reset to reset all interrupt vectors.    
44979 ;
44980 \ ------------------------------\
44981
44982 \ ------------------------------\
44983 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
44984 \ ------------------------------\
44985 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
44986 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
44987 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
44988 \                           --       \ID input divider \ 10 = /4
44989 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
44990 \                                 -  \TBCLR TimerB Clear
44991 \                                  - \TBIE
44992 \                                   -\TBIFG
44993 \ -------------------------------\
44994 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
44995 \                  --                 \CM Capture Mode
44996 \                    --               \CCIS
44997 \                       -             \SCS
44998 \                        --           \CLLD
44999 \                          -          \CAP
45000 \                            ---      \OUTMOD \ 011 = set/reset
45001 \                               -     \CCIE
45002 \                                 -   \CCI
45003 \                                  -  \OUT
45004 \                                   - \COV
45005 \                                    -\CCIFG
45006 \ -------------------------------\
45007 \ LCD_TIM_CCRx                   \
45008 \ -------------------------------\
45009 \ LCD_TIM_EX0                    \ 
45010 \ ------------------------------\
45011 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
45012 \ ------------------------------\
45013 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
45014 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
45015 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
45016     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
45017 [THEN]
45018 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
45019     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
45020 [THEN]
45021     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
45022 \ ------------------------------\
45023 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
45024 \ ------------------------------\
45025 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
45026     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
45027 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
45028 \ ------------------------------\
45029     BIS.B #LCDVo,&LCDVo_DIR     \
45030     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
45031 \ ------------------------------\
45032     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
45033     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
45034 \ ------------------------------\
45035     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
45036     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
45037 \ ******************************\
45038 \ init RC5_Int                  \
45039 \ ******************************\
45040     BIS.B #RC5,&IR_IE           \ enable RC5_Int
45041     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
45042     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
45043 \ ******************************\
45044 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
45045 \ ******************************\
45046 \              %01 0001 0100    \ TAxCTL
45047 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
45048 \                  --           \ ID        divided by 1
45049 \                    --         \ MC        MODE = up to TAxCCRn
45050 \                        -      \ TACLR     clear timer count
45051 \                         -     \ TAIE
45052 \                          -    \ TAIFG
45053 \ ------------------------------\
45054 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
45055 \ ------------------------------\
45056 \                        000    \ TAxEX0
45057 \                        ---    \ TAIDEX    pre divisor
45058 \ ------------------------------\
45059 \          %0000 0000 0000 0101 \ TAxCCR0
45060     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
45061 \ ------------------------------\
45062 \          %0000 0000 0001 0000 \ TAxCCTL0
45063 \                   -           \ CAP capture/compare mode = compare
45064 \                        -      \ CCIEn
45065 \                             - \ CCIFGn
45066     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
45067 \ ------------------------------\
45068     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
45069 \ ------------------------------\
45070 \ define LPM mode for ACCEPT    \
45071 \ ------------------------------\
45072 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
45073 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
45074 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
45075 \ ------------------------------\
45076 \ activate I/O                  \
45077 \ ------------------------------\
45078 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
45079 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
45080 \ ------------------------------\
45081 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
45082 \ ------------------------------\
45083 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
45084 \ CMP #2,Y                        \ Power_ON event
45085 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
45086 CMP #4,Y                        \
45087 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
45088 \ CMP #6,Y                        \
45089 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
45090 \ CMP #$0A,Y                      \
45091 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
45092 \ CMP #$16,Y                      \
45093 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
45094 \ ------------------------------\
45095 COLON                           \
45096 \ ------------------------------\
45097 \ Init LCD 2x20                 \
45098 \ ------------------------------\
45099     #1000 20_US                 \ 1- wait 20 ms
45100     %011 TOP_LCD                \ 2- send DB5=DB4=1
45101     #205 20_US                  \ 3- wait 4,1 ms
45102     %011 TOP_LCD                \ 4- send again DB5=DB4=1
45103     #5 20_US                    \ 5- wait 0,1 ms
45104     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
45105     #2 20_US                    \    wait 40 us = LCD cycle
45106     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
45107     #2 20_US                    \    wait 40 us = LCD cycle
45108     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
45109     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
45110     LCD_CLEAR                   \ 10- "LCD_Clear"
45111     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
45112     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
45113     LCD_CLEAR                   \ 10- "LCD_Clear"
45114     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
45115     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
45116     CR ." I love you"           \ display message on LCD
45117     ['] CR >BODY IS CR          \ CR executes its default value
45118     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
45119     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
45120     PWR_STATE ABORT             \ init DP and continues with ABORT
45121 ;                               \
45122 \ ------------------------------\
45123
45124 \ ------------------------------\
45125 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
45126 \ ------------------------------\
45127 MOV #SLEEP,X                    \ replace default background process SLEEP
45128 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
45129 MOV #WARM,X                     \ replace default WARM
45130 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
45131 MOV X,PC                        \ then execute new WARM
45132 ENDCODE 
45133 \ ------------------------------\
45134
45135 ECHO
45136             ; downloading RC5toLCD.4th is done
45137 RST_HERE    ; this app is protected against <reset>
45138
45139
45140 RST_STATE
45141
45142 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
45143
45144 [UNDEFINED] MARKER [IF]
45145 \  https://forth-standard.org/standard/core/MARKER
45146 \  MARKER
45147 \ ( "<spaces>name" -- )
45148 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
45149 \ with the execution semantics defined below.
45150
45151 \ name Execution: ( -- )
45152 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
45153 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
45154 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
45155 \ not necessarily provided. No other contextual information such as numeric base is affected
45156 \
45157 : MARKER
45158 CREATE
45159 HI2LO
45160 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
45161 SUB #2,Y            \ 1 Y = LFA
45162 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
45163 ADD #4,&DP          \ 3 add 2 cells
45164 LO2HI
45165 DOES>
45166 HI2LO
45167 MOV @RSP+,IP        \ -- PFA
45168 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
45169 MOV @TOS,&INIDP     \       set DP value for RST_STATE
45170 MOV @PSP+,TOS       \ --
45171 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
45172 ENDCODE
45173 [THEN]
45174
45175 MARKER {RC5TOLCD}
45176
45177 [UNDEFINED] @ [IF]
45178 \ https://forth-standard.org/standard/core/Fetch
45179 \ @     c-addr -- char   fetch char from memory
45180 CODE @
45181 MOV @TOS,TOS
45182 MOV @IP+,PC
45183 ENDCODE
45184 [THEN]
45185
45186 [UNDEFINED] CONSTANT [IF]
45187 \ https://forth-standard.org/standard/core/CONSTANT
45188 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
45189 : CONSTANT 
45190 CREATE
45191 HI2LO
45192 MOV TOS,-2(W)           \   PFA = n
45193 MOV @PSP+,TOS
45194 MOV @RSP+,IP
45195 MOV @IP+,PC
45196 ENDCODE
45197 [THEN]
45198
45199 [UNDEFINED] STATE [IF]
45200 \ https://forth-standard.org/standard/core/STATE
45201 \ STATE   -- a-addr       holds compiler state
45202 STATEADR CONSTANT STATE
45203 [THEN]
45204
45205 [UNDEFINED] = [IF]
45206 \ https://forth-standard.org/standard/core/Equal
45207 \ =      x1 x2 -- flag         test x1=x2
45208 CODE =
45209 SUB @PSP+,TOS   \ 2
45210 0<> IF          \ 2
45211     AND #0,TOS  \ 1
45212     MOV @IP+,PC \ 4
45213 THEN
45214 XOR #-1,TOS     \ 1 flag Z = 1
45215 MOV @IP+,PC     \ 4
45216 ENDCODE
45217 [THEN]
45218
45219 [UNDEFINED] IF [IF]
45220 \ https://forth-standard.org/standard/core/IF
45221 \ IF       -- IFadr    initialize conditional forward branch
45222 CODE IF       \ immediate
45223 SUB #2,PSP              \
45224 MOV TOS,0(PSP)          \
45225 MOV &DP,TOS             \ -- HERE
45226 ADD #4,&DP            \           compile one word, reserve one word
45227 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
45228 ADD #2,TOS              \ -- HERE+2=IFadr
45229 MOV @IP+,PC
45230 ENDCODE IMMEDIATE
45231 [THEN]
45232
45233 [UNDEFINED] THEN [IF]
45234 \ https://forth-standard.org/standard/core/THEN
45235 \ THEN     IFadr --                resolve forward branch
45236 CODE THEN               \ immediate
45237 MOV &DP,0(TOS)          \ -- IFadr
45238 MOV @PSP+,TOS           \ --
45239 MOV @IP+,PC
45240 ENDCODE IMMEDIATE
45241 [THEN]
45242
45243 [UNDEFINED] ELSE [IF]
45244 \ https://forth-standard.org/standard/core/ELSE
45245 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
45246 CODE ELSE     \ immediate
45247 ADD #4,&DP              \ make room to compile two words
45248 MOV &DP,W               \ W=HERE+4
45249 MOV #BRAN,-4(W)
45250 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
45251 SUB #2,W                \ HERE+2
45252 MOV W,TOS               \ -- ELSEadr
45253 MOV @IP+,PC
45254 ENDCODE IMMEDIATE
45255 [THEN]
45256
45257 [UNDEFINED] DEFER [IF]
45258 \ https://forth-standard.org/standard/core/DEFER
45259 \ DEFER "<spaces>name"   --
45260 \ Skip leading space delimiters. Parse name delimited by a space.
45261 \ Create a definition for name with the execution semantics defined below.
45262
45263 \ name Execution:   --
45264 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
45265 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
45266 : DEFER
45267 CREATE
45268 HI2LO
45269 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
45270 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
45271 MOV @RSP+,IP
45272 MOV @IP+,PC
45273 ENDCODE
45274 [THEN]
45275
45276 [UNDEFINED] DEFER! [IF]
45277 \ https://forth-standard.org/standard/core/DEFERStore
45278 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
45279 CODE DEFER!             \ xt2 xt1 --
45280 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
45281 MOV @PSP+,TOS           \ --
45282 MOV @IP+,PC
45283 ENDCODE
45284 [THEN]
45285
45286 [UNDEFINED] IS [IF]
45287 \ https://forth-standard.org/standard/core/IS
45288 \ IS <name>        xt --
45289 \ used as is :
45290 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
45291 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
45292 \ or in a definition : ... ['] U. IS DISPLAY ...
45293 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
45294 \
45295 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
45296 : IS
45297 STATE @
45298 IF  POSTPONE ['] POSTPONE DEFER! 
45299 ELSE ' DEFER! 
45300 THEN
45301 ; IMMEDIATE
45302 [THEN]
45303
45304 [UNDEFINED] >BODY [IF]
45305 \ https://forth-standard.org/standard/core/toBODY
45306 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
45307 CODE >BODY
45308 ADD #4,TOS
45309 MOV @IP+,PC
45310 ENDCODE
45311 [THEN]
45312
45313 \ CODE 20uS           \ n --      8MHz version
45314 \ BEGIN               \ 4 + 16 ~ loop
45315 \     MOV #39,rDOCON   \ 39
45316 \     BEGIN           \ 4 ~ loop
45317 \         NOP
45318 \         SUB #1,rDOCON
45319 \     0=  UNTIL
45320 \     SUB #1,TOS      \ 1
45321 \ 0= UNTIL
45322 \ MOV #XDOCON,rDOCON  \ 2
45323 \ MOV @PSP+,TOS
45324 \ MOV @RSP+,IP        \
45325 \ ENDCODE
45326
45327 CODE 20_US                      \ n --      n * 20 us
45328 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
45329     BEGIN
45330         BIT #1,&LCD_TIM_CTL     \ 3
45331     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
45332     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
45333     SUB #1,TOS                  \ 1
45334 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
45335 MOV @PSP+,TOS                   \ 2
45336 MOV @IP+,PC                     \ 4
45337 ENDCODE
45338
45339 CODE TOP_LCD                    \ LCD Sample
45340 \                               \ if write : %xxxx_WWWW --
45341 \                               \ if read  : -- %0000_RRRR
45342     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
45343     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
45344 0= IF                           \ write LCD bits pattern
45345     AND.B #LCD_DB,TOS           \ 
45346     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
45347     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
45348     MOV @PSP+,TOS               \
45349     MOV @IP+,PC
45350 THEN                            \ read LCD bits pattern
45351     SUB #2,PSP
45352     MOV TOS,0(PSP)
45353     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
45354     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
45355     AND.B #LCD_DB,TOS           \
45356     MOV @IP+,PC
45357 ENDCODE
45358
45359 CODE LCD_WRC                    \ char --         Write Char
45360     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
45361 BW1 SUB #2,PSP                  \
45362     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
45363     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
45364     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
45365     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
45366 COLON                           \ high level word starts here 
45367     TOP_LCD 2 20_US             \ write high nibble first
45368     TOP_LCD 2 20_US 
45369 ;
45370
45371 CODE LCD_WRF                    \ func --         Write Fonction
45372     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
45373     GOTO BW1
45374 ENDCODE
45375
45376 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
45377 : LCD_HOME $02 LCD_WRF 100 20_us ;
45378
45379 \ [UNDEFINED] OR [IF]
45380
45381 \ \ https://forth-standard.org/standard/core/OR
45382 \ \ C OR     x1 x2 -- x3           logical OR
45383 \ CODE OR
45384 \ BIS @PSP+,TOS
45385 \ MOV @IP+,PC
45386 \ ENDCODE
45387
45388 \ [THEN]
45389
45390 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
45391 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
45392 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
45393 \ : LCD_FN_SET        $20 OR LCD_WrF ;
45394 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
45395 \ : LCD_GOTO          $80 OR LCD_WrF ;
45396
45397
45398 \ CODE LCD_RDS                    \ -- status       Read Status
45399 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
45400 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
45401 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
45402 \ COLON                           \ starts a FORTH word
45403 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
45404 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
45405 \ HI2LO                           \ switch from FORTH to assembler
45406 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
45407 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
45408 \     MOV @RSP+,IP                \ restore IP saved by COLON
45409 \     MOV @IP+,PC                 \
45410 \ ENDCODE
45411
45412 \ CODE LCD_RDC                    \ -- char         Read Char
45413 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
45414 \     GOTO BW1
45415 \ ENDCODE
45416
45417
45418 \ ******************************\
45419 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
45420 \ ******************************\
45421 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
45422 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
45423 BIT.B #SW2,&SW2_IN              \ test switch S2
45424 0= IF                           \ case of switch S2 pressed
45425     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
45426     U< IF
45427         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
45428     THEN
45429 ELSE
45430     BIT.B #SW1,&SW1_IN          \ test switch S1 input
45431     0= IF                       \ case of Switch S1 pressed
45432         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
45433         U>= IF                  \
45434            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
45435         THEN                    \
45436     THEN                        \
45437 THEN                            \
45438 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
45439 RET                             \ 5
45440 ENDASM
45441
45442 \ ******************************\
45443 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
45444 \ ******************************\
45445 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
45446 \ ******************************\
45447 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
45448 \                               \       SMclock = 8|16|24 MHz
45449 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
45450 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
45451 \                               \       SR(9)=new Toggle bit memory (ADD on)
45452 \ ******************************\
45453 \ RC5_FirstStartBitHalfCycle:   \
45454 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
45455 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
45456 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
45457 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
45458 \ [THEN]
45459 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
45460     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
45461 [THEN]
45462 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
45463     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
45464 [THEN]
45465 MOV #1778,X                     \ RC5_Period * 1us
45466 MOV #14,W                       \ count of loop
45467 BEGIN                           \
45468 \ ******************************\
45469 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
45470 \ ******************************\                   |
45471 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
45472 \ RC5_Compute_3/4_Period:       \                   |
45473     RRUM    #1,X                \ X=1/2 cycle       |
45474     MOV     X,Y                 \                   ^
45475     RRUM    #1,Y                \ Y=1/4
45476     ADD     X,Y                 \ Y=3/4 cycle
45477     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
45478     U>= UNTIL                   \ 2
45479 \ ******************************\
45480 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
45481 \ ******************************\
45482     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
45483     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
45484     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
45485     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
45486     SUB     #1,W                \ decrement count loop
45487 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
45488 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
45489 0<> WHILE                       \ ----> out of loop ----+
45490     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
45491     BEGIN                       \                       |
45492         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
45493         CMP Y,X                 \ 1                     |   cycle time out of bound ?
45494         U>= IF                  \ 2                 ^   |   yes:
45495         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
45496         GOTO BW1                \                   |   |      quit on truncated RC5 message
45497         THEN                    \                   |   |
45498         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
45499     0<> UNTIL                   \ 2                 |   |
45500 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
45501 \ ******************************\                       |
45502 \ RC5_SampleEndOf:              \ <---------------------+
45503 \ ******************************\
45504 BIC #$30,&RC5_TIM_CTL           \   stop timer
45505 \ ******************************\
45506 \ RC5_ComputeNewRC5word         \
45507 \ ******************************\
45508 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
45509 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
45510 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
45511 \ ******************************\
45512 \ RC5_ComputeC6bit              \
45513 \ ******************************\
45514 BIT     #BIT14,T                \ test /C6 bit in T
45515 0= IF   BIS #BIT6,X             \ set C6 bit in X
45516 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
45517 \ ******************************\
45518 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
45519 \ ******************************\
45520 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
45521 \ ******************************\
45522 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
45523 XOR     @RSP,T                  \ (new XOR old) Toggle bits
45524 BIT     #UF10,T                 \ repeated RC5_command ?
45525 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
45526 XOR #UF10,0(RSP)                \ 5 toggle bit memory
45527 \ ******************************\
45528 \ Display IR_RC5 code           \
45529 \ ******************************\
45530 SUB #8,PSP                      \ TOS -- x x x x TOS
45531 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
45532 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
45533 MOV #$10,&BASEADR               \                                               set hexadecimal base
45534 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
45535 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
45536 LO2HI                           \                                               switch from assembler to FORTH
45537     LCD_CLEAR                   \                                               set LCD cursor at home
45538     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
45539     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
45540     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
45541     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
45542 HI2LO                           \     --                                        switch from FORTH to assembler
45543 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
45544 MOV @PSP+,TOS                   \     -- TOS
45545 RET
45546 ENDASM
45547
45548 \ ******************************\
45549 ASM BACKGROUND                  \
45550 \ ******************************\
45551 BEGIN
45552 \     ...                         \ insert here your background task
45553 \     ...                         \
45554 \     ...                         \
45555     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
45556     BIS &LPM_MODE,SR            \
45557 \ ******************************\
45558 \ here start all interrupts     \
45559 \ ******************************\
45560 \ here return all interrupts    \
45561 \ ******************************\
45562 AGAIN                           \
45563 ENDASM                          \
45564 \ ******************************\
45565
45566 \ ------------------------------\
45567 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
45568 \ ------------------------------\
45569 \     ...                         \ init specific I/O sys as you want
45570 \     ...                         \ before executing default WARM
45571     MOV #WARM,X                 \ ['] WARM 
45572     ADD #4,X                    \ >BODY
45573     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
45574 ENDASM
45575 \ ------------------------------\
45576
45577 \ ------------------------------\
45578 CODE STOP                       \ stops multitasking, must to be used before downloading app
45579 \ ------------------------------\
45580 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
45581     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
45582     MOV X,-2(X)                 \ restore the default background: SLEEP
45583     MOV #WARM,X
45584     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
45585     BIC.B #RC5,&IR_IE           \ clear RC5_Int
45586     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
45587     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
45588     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
45589     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
45590     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
45591 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
45592 ECHO                            \
45593 ." RC5toLCD is removed,"
45594 ."  type START to restart"
45595  WARM                           \ performs reset to reset all interrupt vectors.    
45596 ;
45597 \ ------------------------------\
45598
45599 \ ------------------------------\
45600 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
45601 \ ------------------------------\
45602 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
45603 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
45604 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
45605 \                           --       \ID input divider \ 10 = /4
45606 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
45607 \                                 -  \TBCLR TimerB Clear
45608 \                                  - \TBIE
45609 \                                   -\TBIFG
45610 \ -------------------------------\
45611 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
45612 \                  --                 \CM Capture Mode
45613 \                    --               \CCIS
45614 \                       -             \SCS
45615 \                        --           \CLLD
45616 \                          -          \CAP
45617 \                            ---      \OUTMOD \ 011 = set/reset
45618 \                               -     \CCIE
45619 \                                 -   \CCI
45620 \                                  -  \OUT
45621 \                                   - \COV
45622 \                                    -\CCIFG
45623 \ -------------------------------\
45624 \ LCD_TIM_CCRx                   \
45625 \ -------------------------------\
45626 \ LCD_TIM_EX0                    \ 
45627 \ ------------------------------\
45628 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
45629 \ ------------------------------\
45630 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
45631 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
45632 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
45633     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
45634 [THEN]
45635 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
45636     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
45637 [THEN]
45638     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
45639 \ ------------------------------\
45640 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
45641 \ ------------------------------\
45642 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
45643     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
45644 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
45645 \ ------------------------------\
45646     BIS.B #LCDVo,&LCDVo_DIR     \
45647     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
45648 \ ------------------------------\
45649     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
45650     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
45651 \ ------------------------------\
45652     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
45653     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
45654 \ ******************************\
45655 \ init RC5_Int                  \
45656 \ ******************************\
45657     BIS.B #RC5,&IR_IE           \ enable RC5_Int
45658     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
45659     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
45660 \ ******************************\
45661 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
45662 \ ******************************\
45663 \              %01 0001 0100    \ TAxCTL
45664 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
45665 \                  --           \ ID        divided by 1
45666 \                    --         \ MC        MODE = up to TAxCCRn
45667 \                        -      \ TACLR     clear timer count
45668 \                         -     \ TAIE
45669 \                          -    \ TAIFG
45670 \ ------------------------------\
45671 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
45672 \ ------------------------------\
45673 \                        000    \ TAxEX0
45674 \                        ---    \ TAIDEX    pre divisor
45675 \ ------------------------------\
45676 \          %0000 0000 0000 0101 \ TAxCCR0
45677     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
45678 \ ------------------------------\
45679 \          %0000 0000 0001 0000 \ TAxCCTL0
45680 \                   -           \ CAP capture/compare mode = compare
45681 \                        -      \ CCIEn
45682 \                             - \ CCIFGn
45683     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
45684 \ ------------------------------\
45685     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
45686 \ ------------------------------\
45687 \ define LPM mode for ACCEPT    \
45688 \ ------------------------------\
45689 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
45690 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
45691 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
45692 \ ------------------------------\
45693 \ activate I/O                  \
45694 \ ------------------------------\
45695 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
45696 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
45697 \ ------------------------------\
45698 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
45699 \ ------------------------------\
45700 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
45701 \ CMP #2,Y                        \ Power_ON event
45702 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
45703 CMP #4,Y                        \
45704 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
45705 \ CMP #6,Y                        \
45706 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
45707 \ CMP #$0A,Y                      \
45708 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
45709 \ CMP #$16,Y                      \
45710 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
45711 \ ------------------------------\
45712 COLON                           \
45713 \ ------------------------------\
45714 \ Init LCD 2x20                 \
45715 \ ------------------------------\
45716     #1000 20_US                 \ 1- wait 20 ms
45717     %011 TOP_LCD                \ 2- send DB5=DB4=1
45718     #205 20_US                  \ 3- wait 4,1 ms
45719     %011 TOP_LCD                \ 4- send again DB5=DB4=1
45720     #5 20_US                    \ 5- wait 0,1 ms
45721     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
45722     #2 20_US                    \    wait 40 us = LCD cycle
45723     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
45724     #2 20_US                    \    wait 40 us = LCD cycle
45725     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
45726     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
45727     LCD_CLEAR                   \ 10- "LCD_Clear"
45728     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
45729     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
45730     LCD_CLEAR                   \ 10- "LCD_Clear"
45731     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
45732     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
45733     CR ." I love you"           \ display message on LCD
45734     ['] CR >BODY IS CR          \ CR executes its default value
45735     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
45736     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
45737     PWR_STATE ABORT             \ init DP and continues with ABORT
45738 ;                               \
45739 \ ------------------------------\
45740
45741 \ ------------------------------\
45742 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
45743 \ ------------------------------\
45744 MOV #SLEEP,X                    \ replace default background process SLEEP
45745 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
45746 MOV #WARM,X                     \ replace default WARM
45747 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
45748 MOV X,PC                        \ then execute new WARM
45749 ENDCODE 
45750 \ ------------------------------\
45751
45752 ECHO
45753             ; downloading RC5toLCD.4th is done
45754 RST_HERE    ; this app is protected against <reset>
45755
45756
45757 RST_STATE
45758
45759 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
45760
45761 [UNDEFINED] MARKER [IF]
45762 \  https://forth-standard.org/standard/core/MARKER
45763 \  MARKER
45764 \ ( "<spaces>name" -- )
45765 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
45766 \ with the execution semantics defined below.
45767
45768 \ name Execution: ( -- )
45769 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
45770 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
45771 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
45772 \ not necessarily provided. No other contextual information such as numeric base is affected
45773 \
45774 : MARKER
45775 CREATE
45776 HI2LO
45777 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
45778 SUB #2,Y            \ 1 Y = LFA
45779 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
45780 ADD #4,&DP          \ 3 add 2 cells
45781 LO2HI
45782 DOES>
45783 HI2LO
45784 MOV @RSP+,IP        \ -- PFA
45785 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
45786 MOV @TOS,&INIDP     \       set DP value for RST_STATE
45787 MOV @PSP+,TOS       \ --
45788 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
45789 ENDCODE
45790 [THEN]
45791
45792 MARKER {RC5TOLCD}
45793
45794 [UNDEFINED] @ [IF]
45795 \ https://forth-standard.org/standard/core/Fetch
45796 \ @     c-addr -- char   fetch char from memory
45797 CODE @
45798 MOV @TOS,TOS
45799 MOV @IP+,PC
45800 ENDCODE
45801 [THEN]
45802
45803 [UNDEFINED] CONSTANT [IF]
45804 \ https://forth-standard.org/standard/core/CONSTANT
45805 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
45806 : CONSTANT 
45807 CREATE
45808 HI2LO
45809 MOV TOS,-2(W)           \   PFA = n
45810 MOV @PSP+,TOS
45811 MOV @RSP+,IP
45812 MOV @IP+,PC
45813 ENDCODE
45814 [THEN]
45815
45816 [UNDEFINED] STATE [IF]
45817 \ https://forth-standard.org/standard/core/STATE
45818 \ STATE   -- a-addr       holds compiler state
45819 STATEADR CONSTANT STATE
45820 [THEN]
45821
45822 [UNDEFINED] = [IF]
45823 \ https://forth-standard.org/standard/core/Equal
45824 \ =      x1 x2 -- flag         test x1=x2
45825 CODE =
45826 SUB @PSP+,TOS   \ 2
45827 0<> IF          \ 2
45828     AND #0,TOS  \ 1
45829     MOV @IP+,PC \ 4
45830 THEN
45831 XOR #-1,TOS     \ 1 flag Z = 1
45832 MOV @IP+,PC     \ 4
45833 ENDCODE
45834 [THEN]
45835
45836 [UNDEFINED] IF [IF]
45837 \ https://forth-standard.org/standard/core/IF
45838 \ IF       -- IFadr    initialize conditional forward branch
45839 CODE IF       \ immediate
45840 SUB #2,PSP              \
45841 MOV TOS,0(PSP)          \
45842 MOV &DP,TOS             \ -- HERE
45843 ADD #4,&DP            \           compile one word, reserve one word
45844 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
45845 ADD #2,TOS              \ -- HERE+2=IFadr
45846 MOV @IP+,PC
45847 ENDCODE IMMEDIATE
45848 [THEN]
45849
45850 [UNDEFINED] THEN [IF]
45851 \ https://forth-standard.org/standard/core/THEN
45852 \ THEN     IFadr --                resolve forward branch
45853 CODE THEN               \ immediate
45854 MOV &DP,0(TOS)          \ -- IFadr
45855 MOV @PSP+,TOS           \ --
45856 MOV @IP+,PC
45857 ENDCODE IMMEDIATE
45858 [THEN]
45859
45860 [UNDEFINED] ELSE [IF]
45861 \ https://forth-standard.org/standard/core/ELSE
45862 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
45863 CODE ELSE     \ immediate
45864 ADD #4,&DP              \ make room to compile two words
45865 MOV &DP,W               \ W=HERE+4
45866 MOV #BRAN,-4(W)
45867 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
45868 SUB #2,W                \ HERE+2
45869 MOV W,TOS               \ -- ELSEadr
45870 MOV @IP+,PC
45871 ENDCODE IMMEDIATE
45872 [THEN]
45873
45874 [UNDEFINED] DEFER [IF]
45875 \ https://forth-standard.org/standard/core/DEFER
45876 \ DEFER "<spaces>name"   --
45877 \ Skip leading space delimiters. Parse name delimited by a space.
45878 \ Create a definition for name with the execution semantics defined below.
45879
45880 \ name Execution:   --
45881 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
45882 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
45883 : DEFER
45884 CREATE
45885 HI2LO
45886 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
45887 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
45888 MOV @RSP+,IP
45889 MOV @IP+,PC
45890 ENDCODE
45891 [THEN]
45892
45893 [UNDEFINED] DEFER! [IF]
45894 \ https://forth-standard.org/standard/core/DEFERStore
45895 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
45896 CODE DEFER!             \ xt2 xt1 --
45897 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
45898 MOV @PSP+,TOS           \ --
45899 MOV @IP+,PC
45900 ENDCODE
45901 [THEN]
45902
45903 [UNDEFINED] IS [IF]
45904 \ https://forth-standard.org/standard/core/IS
45905 \ IS <name>        xt --
45906 \ used as is :
45907 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
45908 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
45909 \ or in a definition : ... ['] U. IS DISPLAY ...
45910 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
45911 \
45912 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
45913 : IS
45914 STATE @
45915 IF  POSTPONE ['] POSTPONE DEFER! 
45916 ELSE ' DEFER! 
45917 THEN
45918 ; IMMEDIATE
45919 [THEN]
45920
45921 [UNDEFINED] >BODY [IF]
45922 \ https://forth-standard.org/standard/core/toBODY
45923 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
45924 CODE >BODY
45925 ADD #4,TOS
45926 MOV @IP+,PC
45927 ENDCODE
45928 [THEN]
45929
45930 \ CODE 20uS           \ n --      8MHz version
45931 \ BEGIN               \ 4 + 16 ~ loop
45932 \     MOV #39,rDOCON   \ 39
45933 \     BEGIN           \ 4 ~ loop
45934 \         NOP
45935 \         SUB #1,rDOCON
45936 \     0=  UNTIL
45937 \     SUB #1,TOS      \ 1
45938 \ 0= UNTIL
45939 \ MOV #XDOCON,rDOCON  \ 2
45940 \ MOV @PSP+,TOS
45941 \ MOV @RSP+,IP        \
45942 \ ENDCODE
45943
45944 CODE 20_US                      \ n --      n * 20 us
45945 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
45946     BEGIN
45947         BIT #1,&LCD_TIM_CTL     \ 3
45948     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
45949     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
45950     SUB #1,TOS                  \ 1
45951 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
45952 MOV @PSP+,TOS                   \ 2
45953 MOV @IP+,PC                     \ 4
45954 ENDCODE
45955
45956 CODE TOP_LCD                    \ LCD Sample
45957 \                               \ if write : %xxxx_WWWW --
45958 \                               \ if read  : -- %0000_RRRR
45959     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
45960     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
45961 0= IF                           \ write LCD bits pattern
45962     AND.B #LCD_DB,TOS           \ 
45963     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
45964     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
45965     MOV @PSP+,TOS               \
45966     MOV @IP+,PC
45967 THEN                            \ read LCD bits pattern
45968     SUB #2,PSP
45969     MOV TOS,0(PSP)
45970     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
45971     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
45972     AND.B #LCD_DB,TOS           \
45973     MOV @IP+,PC
45974 ENDCODE
45975
45976 CODE LCD_WRC                    \ char --         Write Char
45977     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
45978 BW1 SUB #2,PSP                  \
45979     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
45980     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
45981     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
45982     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
45983 COLON                           \ high level word starts here 
45984     TOP_LCD 2 20_US             \ write high nibble first
45985     TOP_LCD 2 20_US 
45986 ;
45987
45988 CODE LCD_WRF                    \ func --         Write Fonction
45989     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
45990     GOTO BW1
45991 ENDCODE
45992
45993 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
45994 : LCD_HOME $02 LCD_WRF 100 20_us ;
45995
45996 \ [UNDEFINED] OR [IF]
45997
45998 \ \ https://forth-standard.org/standard/core/OR
45999 \ \ C OR     x1 x2 -- x3           logical OR
46000 \ CODE OR
46001 \ BIS @PSP+,TOS
46002 \ MOV @IP+,PC
46003 \ ENDCODE
46004
46005 \ [THEN]
46006
46007 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
46008 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
46009 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
46010 \ : LCD_FN_SET        $20 OR LCD_WrF ;
46011 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
46012 \ : LCD_GOTO          $80 OR LCD_WrF ;
46013
46014
46015 \ CODE LCD_RDS                    \ -- status       Read Status
46016 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
46017 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
46018 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
46019 \ COLON                           \ starts a FORTH word
46020 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
46021 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
46022 \ HI2LO                           \ switch from FORTH to assembler
46023 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
46024 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
46025 \     MOV @RSP+,IP                \ restore IP saved by COLON
46026 \     MOV @IP+,PC                 \
46027 \ ENDCODE
46028
46029 \ CODE LCD_RDC                    \ -- char         Read Char
46030 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
46031 \     GOTO BW1
46032 \ ENDCODE
46033
46034
46035 \ ******************************\
46036 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
46037 \ ******************************\
46038 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
46039 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
46040 BIT.B #SW2,&SW2_IN              \ test switch S2
46041 0= IF                           \ case of switch S2 pressed
46042     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
46043     U< IF
46044         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
46045     THEN
46046 ELSE
46047     BIT.B #SW1,&SW1_IN          \ test switch S1 input
46048     0= IF                       \ case of Switch S1 pressed
46049         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
46050         U>= IF                  \
46051            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
46052         THEN                    \
46053     THEN                        \
46054 THEN                            \
46055 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
46056 RET                             \ 5
46057 ENDASM
46058
46059 \ ******************************\
46060 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
46061 \ ******************************\
46062 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
46063 \ ******************************\
46064 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
46065 \                               \       SMclock = 8|16|24 MHz
46066 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
46067 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
46068 \                               \       SR(9)=new Toggle bit memory (ADD on)
46069 \ ******************************\
46070 \ RC5_FirstStartBitHalfCycle:   \
46071 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
46072 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
46073 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
46074 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
46075 \ [THEN]
46076 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
46077     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
46078 [THEN]
46079 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
46080     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
46081 [THEN]
46082 MOV #1778,X                     \ RC5_Period * 1us
46083 MOV #14,W                       \ count of loop
46084 BEGIN                           \
46085 \ ******************************\
46086 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
46087 \ ******************************\                   |
46088 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
46089 \ RC5_Compute_3/4_Period:       \                   |
46090     RRUM    #1,X                \ X=1/2 cycle       |
46091     MOV     X,Y                 \                   ^
46092     RRUM    #1,Y                \ Y=1/4
46093     ADD     X,Y                 \ Y=3/4 cycle
46094     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
46095     U>= UNTIL                   \ 2
46096 \ ******************************\
46097 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
46098 \ ******************************\
46099     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
46100     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
46101     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
46102     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
46103     SUB     #1,W                \ decrement count loop
46104 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
46105 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
46106 0<> WHILE                       \ ----> out of loop ----+
46107     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
46108     BEGIN                       \                       |
46109         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
46110         CMP Y,X                 \ 1                     |   cycle time out of bound ?
46111         U>= IF                  \ 2                 ^   |   yes:
46112         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
46113         GOTO BW1                \                   |   |      quit on truncated RC5 message
46114         THEN                    \                   |   |
46115         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
46116     0<> UNTIL                   \ 2                 |   |
46117 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
46118 \ ******************************\                       |
46119 \ RC5_SampleEndOf:              \ <---------------------+
46120 \ ******************************\
46121 BIC #$30,&RC5_TIM_CTL           \   stop timer
46122 \ ******************************\
46123 \ RC5_ComputeNewRC5word         \
46124 \ ******************************\
46125 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
46126 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
46127 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
46128 \ ******************************\
46129 \ RC5_ComputeC6bit              \
46130 \ ******************************\
46131 BIT     #BIT14,T                \ test /C6 bit in T
46132 0= IF   BIS #BIT6,X             \ set C6 bit in X
46133 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
46134 \ ******************************\
46135 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
46136 \ ******************************\
46137 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
46138 \ ******************************\
46139 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
46140 XOR     @RSP,T                  \ (new XOR old) Toggle bits
46141 BIT     #UF10,T                 \ repeated RC5_command ?
46142 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
46143 XOR #UF10,0(RSP)                \ 5 toggle bit memory
46144 \ ******************************\
46145 \ Display IR_RC5 code           \
46146 \ ******************************\
46147 SUB #8,PSP                      \ TOS -- x x x x TOS
46148 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
46149 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
46150 MOV #$10,&BASEADR               \                                               set hexadecimal base
46151 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
46152 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
46153 LO2HI                           \                                               switch from assembler to FORTH
46154     LCD_CLEAR                   \                                               set LCD cursor at home
46155     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
46156     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
46157     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
46158     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
46159 HI2LO                           \     --                                        switch from FORTH to assembler
46160 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
46161 MOV @PSP+,TOS                   \     -- TOS
46162 RET
46163 ENDASM
46164
46165 \ ******************************\
46166 ASM BACKGROUND                  \
46167 \ ******************************\
46168 BEGIN
46169 \     ...                         \ insert here your background task
46170 \     ...                         \
46171 \     ...                         \
46172     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
46173     BIS &LPM_MODE,SR            \
46174 \ ******************************\
46175 \ here start all interrupts     \
46176 \ ******************************\
46177 \ here return all interrupts    \
46178 \ ******************************\
46179 AGAIN                           \
46180 ENDASM                          \
46181 \ ******************************\
46182
46183 \ ------------------------------\
46184 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
46185 \ ------------------------------\
46186 \     ...                         \ init specific I/O sys as you want
46187 \     ...                         \ before executing default WARM
46188     MOV #WARM,X                 \ ['] WARM 
46189     ADD #4,X                    \ >BODY
46190     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
46191 ENDASM
46192 \ ------------------------------\
46193
46194 \ ------------------------------\
46195 CODE STOP                       \ stops multitasking, must to be used before downloading app
46196 \ ------------------------------\
46197 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
46198     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
46199     MOV X,-2(X)                 \ restore the default background: SLEEP
46200     MOV #WARM,X
46201     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
46202     BIC.B #RC5,&IR_IE           \ clear RC5_Int
46203     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
46204     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
46205     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
46206     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
46207     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
46208 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
46209 ECHO                            \
46210 ." RC5toLCD is removed,"
46211 ."  type START to restart"
46212  WARM                           \ performs reset to reset all interrupt vectors.    
46213 ;
46214 \ ------------------------------\
46215
46216 \ ------------------------------\
46217 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
46218 \ ------------------------------\
46219 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
46220 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
46221 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
46222 \                           --       \ID input divider \ 10 = /4
46223 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
46224 \                                 -  \TBCLR TimerB Clear
46225 \                                  - \TBIE
46226 \                                   -\TBIFG
46227 \ -------------------------------\
46228 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
46229 \                  --                 \CM Capture Mode
46230 \                    --               \CCIS
46231 \                       -             \SCS
46232 \                        --           \CLLD
46233 \                          -          \CAP
46234 \                            ---      \OUTMOD \ 011 = set/reset
46235 \                               -     \CCIE
46236 \                                 -   \CCI
46237 \                                  -  \OUT
46238 \                                   - \COV
46239 \                                    -\CCIFG
46240 \ -------------------------------\
46241 \ LCD_TIM_CCRx                   \
46242 \ -------------------------------\
46243 \ LCD_TIM_EX0                    \ 
46244 \ ------------------------------\
46245 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
46246 \ ------------------------------\
46247 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
46248 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
46249 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
46250     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
46251 [THEN]
46252 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
46253     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
46254 [THEN]
46255     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
46256 \ ------------------------------\
46257 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
46258 \ ------------------------------\
46259 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
46260     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
46261 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
46262 \ ------------------------------\
46263     BIS.B #LCDVo,&LCDVo_DIR     \
46264     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
46265 \ ------------------------------\
46266     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
46267     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
46268 \ ------------------------------\
46269     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
46270     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
46271 \ ******************************\
46272 \ init RC5_Int                  \
46273 \ ******************************\
46274     BIS.B #RC5,&IR_IE           \ enable RC5_Int
46275     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
46276     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
46277 \ ******************************\
46278 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
46279 \ ******************************\
46280 \              %01 0001 0100    \ TAxCTL
46281 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
46282 \                  --           \ ID        divided by 1
46283 \                    --         \ MC        MODE = up to TAxCCRn
46284 \                        -      \ TACLR     clear timer count
46285 \                         -     \ TAIE
46286 \                          -    \ TAIFG
46287 \ ------------------------------\
46288 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
46289 \ ------------------------------\
46290 \                        000    \ TAxEX0
46291 \                        ---    \ TAIDEX    pre divisor
46292 \ ------------------------------\
46293 \          %0000 0000 0000 0101 \ TAxCCR0
46294     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
46295 \ ------------------------------\
46296 \          %0000 0000 0001 0000 \ TAxCCTL0
46297 \                   -           \ CAP capture/compare mode = compare
46298 \                        -      \ CCIEn
46299 \                             - \ CCIFGn
46300     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
46301 \ ------------------------------\
46302     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
46303 \ ------------------------------\
46304 \ define LPM mode for ACCEPT    \
46305 \ ------------------------------\
46306 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
46307 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
46308 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
46309 \ ------------------------------\
46310 \ activate I/O                  \
46311 \ ------------------------------\
46312 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
46313 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
46314 \ ------------------------------\
46315 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
46316 \ ------------------------------\
46317 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
46318 \ CMP #2,Y                        \ Power_ON event
46319 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
46320 CMP #4,Y                        \
46321 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
46322 \ CMP #6,Y                        \
46323 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
46324 \ CMP #$0A,Y                      \
46325 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
46326 \ CMP #$16,Y                      \
46327 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
46328 \ ------------------------------\
46329 COLON                           \
46330 \ ------------------------------\
46331 \ Init LCD 2x20                 \
46332 \ ------------------------------\
46333     #1000 20_US                 \ 1- wait 20 ms
46334     %011 TOP_LCD                \ 2- send DB5=DB4=1
46335     #205 20_US                  \ 3- wait 4,1 ms
46336     %011 TOP_LCD                \ 4- send again DB5=DB4=1
46337     #5 20_US                    \ 5- wait 0,1 ms
46338     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
46339     #2 20_US                    \    wait 40 us = LCD cycle
46340     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
46341     #2 20_US                    \    wait 40 us = LCD cycle
46342     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
46343     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
46344     LCD_CLEAR                   \ 10- "LCD_Clear"
46345     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
46346     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
46347     LCD_CLEAR                   \ 10- "LCD_Clear"
46348     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
46349     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
46350     CR ." I love you"           \ display message on LCD
46351     ['] CR >BODY IS CR          \ CR executes its default value
46352     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
46353     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
46354     PWR_STATE ABORT             \ init DP and continues with ABORT
46355 ;                               \
46356 \ ------------------------------\
46357
46358 \ ------------------------------\
46359 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
46360 \ ------------------------------\
46361 MOV #SLEEP,X                    \ replace default background process SLEEP
46362 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
46363 MOV #WARM,X                     \ replace default WARM
46364 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
46365 MOV X,PC                        \ then execute new WARM
46366 ENDCODE 
46367 \ ------------------------------\
46368
46369 ECHO
46370             ; downloading RC5toLCD.4th is done
46371 RST_HERE    ; this app is protected against <reset>
46372
46373
46374 RST_STATE
46375
46376 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
46377
46378 [UNDEFINED] MARKER [IF]
46379 \  https://forth-standard.org/standard/core/MARKER
46380 \  MARKER
46381 \ ( "<spaces>name" -- )
46382 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
46383 \ with the execution semantics defined below.
46384
46385 \ name Execution: ( -- )
46386 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
46387 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
46388 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
46389 \ not necessarily provided. No other contextual information such as numeric base is affected
46390 \
46391 : MARKER
46392 CREATE
46393 HI2LO
46394 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
46395 SUB #2,Y            \ 1 Y = LFA
46396 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
46397 ADD #4,&DP          \ 3 add 2 cells
46398 LO2HI
46399 DOES>
46400 HI2LO
46401 MOV @RSP+,IP        \ -- PFA
46402 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
46403 MOV @TOS,&INIDP     \       set DP value for RST_STATE
46404 MOV @PSP+,TOS       \ --
46405 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
46406 ENDCODE
46407 [THEN]
46408
46409 MARKER {RC5TOLCD}
46410
46411 [UNDEFINED] @ [IF]
46412 \ https://forth-standard.org/standard/core/Fetch
46413 \ @     c-addr -- char   fetch char from memory
46414 CODE @
46415 MOV @TOS,TOS
46416 MOV @IP+,PC
46417 ENDCODE
46418 [THEN]
46419
46420 [UNDEFINED] CONSTANT [IF]
46421 \ https://forth-standard.org/standard/core/CONSTANT
46422 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
46423 : CONSTANT 
46424 CREATE
46425 HI2LO
46426 MOV TOS,-2(W)           \   PFA = n
46427 MOV @PSP+,TOS
46428 MOV @RSP+,IP
46429 MOV @IP+,PC
46430 ENDCODE
46431 [THEN]
46432
46433 [UNDEFINED] STATE [IF]
46434 \ https://forth-standard.org/standard/core/STATE
46435 \ STATE   -- a-addr       holds compiler state
46436 STATEADR CONSTANT STATE
46437 [THEN]
46438
46439 [UNDEFINED] = [IF]
46440 \ https://forth-standard.org/standard/core/Equal
46441 \ =      x1 x2 -- flag         test x1=x2
46442 CODE =
46443 SUB @PSP+,TOS   \ 2
46444 0<> IF          \ 2
46445     AND #0,TOS  \ 1
46446     MOV @IP+,PC \ 4
46447 THEN
46448 XOR #-1,TOS     \ 1 flag Z = 1
46449 MOV @IP+,PC     \ 4
46450 ENDCODE
46451 [THEN]
46452
46453 [UNDEFINED] IF [IF]
46454 \ https://forth-standard.org/standard/core/IF
46455 \ IF       -- IFadr    initialize conditional forward branch
46456 CODE IF       \ immediate
46457 SUB #2,PSP              \
46458 MOV TOS,0(PSP)          \
46459 MOV &DP,TOS             \ -- HERE
46460 ADD #4,&DP            \           compile one word, reserve one word
46461 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
46462 ADD #2,TOS              \ -- HERE+2=IFadr
46463 MOV @IP+,PC
46464 ENDCODE IMMEDIATE
46465 [THEN]
46466
46467 [UNDEFINED] THEN [IF]
46468 \ https://forth-standard.org/standard/core/THEN
46469 \ THEN     IFadr --                resolve forward branch
46470 CODE THEN               \ immediate
46471 MOV &DP,0(TOS)          \ -- IFadr
46472 MOV @PSP+,TOS           \ --
46473 MOV @IP+,PC
46474 ENDCODE IMMEDIATE
46475 [THEN]
46476
46477 [UNDEFINED] ELSE [IF]
46478 \ https://forth-standard.org/standard/core/ELSE
46479 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
46480 CODE ELSE     \ immediate
46481 ADD #4,&DP              \ make room to compile two words
46482 MOV &DP,W               \ W=HERE+4
46483 MOV #BRAN,-4(W)
46484 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
46485 SUB #2,W                \ HERE+2
46486 MOV W,TOS               \ -- ELSEadr
46487 MOV @IP+,PC
46488 ENDCODE IMMEDIATE
46489 [THEN]
46490
46491 [UNDEFINED] DEFER [IF]
46492 \ https://forth-standard.org/standard/core/DEFER
46493 \ DEFER "<spaces>name"   --
46494 \ Skip leading space delimiters. Parse name delimited by a space.
46495 \ Create a definition for name with the execution semantics defined below.
46496
46497 \ name Execution:   --
46498 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
46499 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
46500 : DEFER
46501 CREATE
46502 HI2LO
46503 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
46504 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
46505 MOV @RSP+,IP
46506 MOV @IP+,PC
46507 ENDCODE
46508 [THEN]
46509
46510 [UNDEFINED] DEFER! [IF]
46511 \ https://forth-standard.org/standard/core/DEFERStore
46512 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
46513 CODE DEFER!             \ xt2 xt1 --
46514 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
46515 MOV @PSP+,TOS           \ --
46516 MOV @IP+,PC
46517 ENDCODE
46518 [THEN]
46519
46520 [UNDEFINED] IS [IF]
46521 \ https://forth-standard.org/standard/core/IS
46522 \ IS <name>        xt --
46523 \ used as is :
46524 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
46525 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
46526 \ or in a definition : ... ['] U. IS DISPLAY ...
46527 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
46528 \
46529 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
46530 : IS
46531 STATE @
46532 IF  POSTPONE ['] POSTPONE DEFER! 
46533 ELSE ' DEFER! 
46534 THEN
46535 ; IMMEDIATE
46536 [THEN]
46537
46538 [UNDEFINED] >BODY [IF]
46539 \ https://forth-standard.org/standard/core/toBODY
46540 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
46541 CODE >BODY
46542 ADD #4,TOS
46543 MOV @IP+,PC
46544 ENDCODE
46545 [THEN]
46546
46547 \ CODE 20uS           \ n --      8MHz version
46548 \ BEGIN               \ 4 + 16 ~ loop
46549 \     MOV #39,rDOCON   \ 39
46550 \     BEGIN           \ 4 ~ loop
46551 \         NOP
46552 \         SUB #1,rDOCON
46553 \     0=  UNTIL
46554 \     SUB #1,TOS      \ 1
46555 \ 0= UNTIL
46556 \ MOV #XDOCON,rDOCON  \ 2
46557 \ MOV @PSP+,TOS
46558 \ MOV @RSP+,IP        \
46559 \ ENDCODE
46560
46561 CODE 20_US                      \ n --      n * 20 us
46562 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
46563     BEGIN
46564         BIT #1,&LCD_TIM_CTL     \ 3
46565     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
46566     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
46567     SUB #1,TOS                  \ 1
46568 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
46569 MOV @PSP+,TOS                   \ 2
46570 MOV @IP+,PC                     \ 4
46571 ENDCODE
46572
46573 CODE TOP_LCD                    \ LCD Sample
46574 \                               \ if write : %xxxx_WWWW --
46575 \                               \ if read  : -- %0000_RRRR
46576     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
46577     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
46578 0= IF                           \ write LCD bits pattern
46579     AND.B #LCD_DB,TOS           \ 
46580     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
46581     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
46582     MOV @PSP+,TOS               \
46583     MOV @IP+,PC
46584 THEN                            \ read LCD bits pattern
46585     SUB #2,PSP
46586     MOV TOS,0(PSP)
46587     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
46588     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
46589     AND.B #LCD_DB,TOS           \
46590     MOV @IP+,PC
46591 ENDCODE
46592
46593 CODE LCD_WRC                    \ char --         Write Char
46594     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
46595 BW1 SUB #2,PSP                  \
46596     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
46597     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
46598     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
46599     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
46600 COLON                           \ high level word starts here 
46601     TOP_LCD 2 20_US             \ write high nibble first
46602     TOP_LCD 2 20_US 
46603 ;
46604
46605 CODE LCD_WRF                    \ func --         Write Fonction
46606     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
46607     GOTO BW1
46608 ENDCODE
46609
46610 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
46611 : LCD_HOME $02 LCD_WRF 100 20_us ;
46612
46613 \ [UNDEFINED] OR [IF]
46614
46615 \ \ https://forth-standard.org/standard/core/OR
46616 \ \ C OR     x1 x2 -- x3           logical OR
46617 \ CODE OR
46618 \ BIS @PSP+,TOS
46619 \ MOV @IP+,PC
46620 \ ENDCODE
46621
46622 \ [THEN]
46623
46624 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
46625 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
46626 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
46627 \ : LCD_FN_SET        $20 OR LCD_WrF ;
46628 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
46629 \ : LCD_GOTO          $80 OR LCD_WrF ;
46630
46631
46632 \ CODE LCD_RDS                    \ -- status       Read Status
46633 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
46634 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
46635 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
46636 \ COLON                           \ starts a FORTH word
46637 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
46638 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
46639 \ HI2LO                           \ switch from FORTH to assembler
46640 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
46641 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
46642 \     MOV @RSP+,IP                \ restore IP saved by COLON
46643 \     MOV @IP+,PC                 \
46644 \ ENDCODE
46645
46646 \ CODE LCD_RDC                    \ -- char         Read Char
46647 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
46648 \     GOTO BW1
46649 \ ENDCODE
46650
46651
46652 \ ******************************\
46653 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
46654 \ ******************************\
46655 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
46656 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
46657 BIT.B #SW2,&SW2_IN              \ test switch S2
46658 0= IF                           \ case of switch S2 pressed
46659     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
46660     U< IF
46661         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
46662     THEN
46663 ELSE
46664     BIT.B #SW1,&SW1_IN          \ test switch S1 input
46665     0= IF                       \ case of Switch S1 pressed
46666         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
46667         U>= IF                  \
46668            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
46669         THEN                    \
46670     THEN                        \
46671 THEN                            \
46672 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
46673 RET                             \ 5
46674 ENDASM
46675
46676 \ ******************************\
46677 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
46678 \ ******************************\
46679 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
46680 \ ******************************\
46681 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
46682 \                               \       SMclock = 8|16|24 MHz
46683 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
46684 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
46685 \                               \       SR(9)=new Toggle bit memory (ADD on)
46686 \ ******************************\
46687 \ RC5_FirstStartBitHalfCycle:   \
46688 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
46689 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
46690 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
46691 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
46692 \ [THEN]
46693 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
46694     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
46695 [THEN]
46696 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
46697     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
46698 [THEN]
46699 MOV #1778,X                     \ RC5_Period * 1us
46700 MOV #14,W                       \ count of loop
46701 BEGIN                           \
46702 \ ******************************\
46703 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
46704 \ ******************************\                   |
46705 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
46706 \ RC5_Compute_3/4_Period:       \                   |
46707     RRUM    #1,X                \ X=1/2 cycle       |
46708     MOV     X,Y                 \                   ^
46709     RRUM    #1,Y                \ Y=1/4
46710     ADD     X,Y                 \ Y=3/4 cycle
46711     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
46712     U>= UNTIL                   \ 2
46713 \ ******************************\
46714 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
46715 \ ******************************\
46716     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
46717     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
46718     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
46719     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
46720     SUB     #1,W                \ decrement count loop
46721 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
46722 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
46723 0<> WHILE                       \ ----> out of loop ----+
46724     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
46725     BEGIN                       \                       |
46726         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
46727         CMP Y,X                 \ 1                     |   cycle time out of bound ?
46728         U>= IF                  \ 2                 ^   |   yes:
46729         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
46730         GOTO BW1                \                   |   |      quit on truncated RC5 message
46731         THEN                    \                   |   |
46732         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
46733     0<> UNTIL                   \ 2                 |   |
46734 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
46735 \ ******************************\                       |
46736 \ RC5_SampleEndOf:              \ <---------------------+
46737 \ ******************************\
46738 BIC #$30,&RC5_TIM_CTL           \   stop timer
46739 \ ******************************\
46740 \ RC5_ComputeNewRC5word         \
46741 \ ******************************\
46742 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
46743 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
46744 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
46745 \ ******************************\
46746 \ RC5_ComputeC6bit              \
46747 \ ******************************\
46748 BIT     #BIT14,T                \ test /C6 bit in T
46749 0= IF   BIS #BIT6,X             \ set C6 bit in X
46750 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
46751 \ ******************************\
46752 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
46753 \ ******************************\
46754 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
46755 \ ******************************\
46756 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
46757 XOR     @RSP,T                  \ (new XOR old) Toggle bits
46758 BIT     #UF10,T                 \ repeated RC5_command ?
46759 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
46760 XOR #UF10,0(RSP)                \ 5 toggle bit memory
46761 \ ******************************\
46762 \ Display IR_RC5 code           \
46763 \ ******************************\
46764 SUB #8,PSP                      \ TOS -- x x x x TOS
46765 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
46766 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
46767 MOV #$10,&BASEADR               \                                               set hexadecimal base
46768 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
46769 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
46770 LO2HI                           \                                               switch from assembler to FORTH
46771     LCD_CLEAR                   \                                               set LCD cursor at home
46772     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
46773     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
46774     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
46775     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
46776 HI2LO                           \     --                                        switch from FORTH to assembler
46777 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
46778 MOV @PSP+,TOS                   \     -- TOS
46779 RET
46780 ENDASM
46781
46782 \ ******************************\
46783 ASM BACKGROUND                  \
46784 \ ******************************\
46785 BEGIN
46786 \     ...                         \ insert here your background task
46787 \     ...                         \
46788 \     ...                         \
46789     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
46790     BIS &LPM_MODE,SR            \
46791 \ ******************************\
46792 \ here start all interrupts     \
46793 \ ******************************\
46794 \ here return all interrupts    \
46795 \ ******************************\
46796 AGAIN                           \
46797 ENDASM                          \
46798 \ ******************************\
46799
46800 \ ------------------------------\
46801 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
46802 \ ------------------------------\
46803 \     ...                         \ init specific I/O sys as you want
46804 \     ...                         \ before executing default WARM
46805     MOV #WARM,X                 \ ['] WARM 
46806     ADD #4,X                    \ >BODY
46807     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
46808 ENDASM
46809 \ ------------------------------\
46810
46811 \ ------------------------------\
46812 CODE STOP                       \ stops multitasking, must to be used before downloading app
46813 \ ------------------------------\
46814 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
46815     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
46816     MOV X,-2(X)                 \ restore the default background: SLEEP
46817     MOV #WARM,X
46818     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
46819     BIC.B #RC5,&IR_IE           \ clear RC5_Int
46820     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
46821     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
46822     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
46823     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
46824     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
46825 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
46826 ECHO                            \
46827 ." RC5toLCD is removed,"
46828 ."  type START to restart"
46829  WARM                           \ performs reset to reset all interrupt vectors.    
46830 ;
46831 \ ------------------------------\
46832
46833 \ ------------------------------\
46834 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
46835 \ ------------------------------\
46836 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
46837 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
46838 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
46839 \                           --       \ID input divider \ 10 = /4
46840 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
46841 \                                 -  \TBCLR TimerB Clear
46842 \                                  - \TBIE
46843 \                                   -\TBIFG
46844 \ -------------------------------\
46845 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
46846 \                  --                 \CM Capture Mode
46847 \                    --               \CCIS
46848 \                       -             \SCS
46849 \                        --           \CLLD
46850 \                          -          \CAP
46851 \                            ---      \OUTMOD \ 011 = set/reset
46852 \                               -     \CCIE
46853 \                                 -   \CCI
46854 \                                  -  \OUT
46855 \                                   - \COV
46856 \                                    -\CCIFG
46857 \ -------------------------------\
46858 \ LCD_TIM_CCRx                   \
46859 \ -------------------------------\
46860 \ LCD_TIM_EX0                    \ 
46861 \ ------------------------------\
46862 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
46863 \ ------------------------------\
46864 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
46865 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
46866 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
46867     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
46868 [THEN]
46869 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
46870     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
46871 [THEN]
46872     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
46873 \ ------------------------------\
46874 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
46875 \ ------------------------------\
46876 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
46877     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
46878 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
46879 \ ------------------------------\
46880     BIS.B #LCDVo,&LCDVo_DIR     \
46881     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
46882 \ ------------------------------\
46883     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
46884     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
46885 \ ------------------------------\
46886     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
46887     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
46888 \ ******************************\
46889 \ init RC5_Int                  \
46890 \ ******************************\
46891     BIS.B #RC5,&IR_IE           \ enable RC5_Int
46892     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
46893     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
46894 \ ******************************\
46895 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
46896 \ ******************************\
46897 \              %01 0001 0100    \ TAxCTL
46898 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
46899 \                  --           \ ID        divided by 1
46900 \                    --         \ MC        MODE = up to TAxCCRn
46901 \                        -      \ TACLR     clear timer count
46902 \                         -     \ TAIE
46903 \                          -    \ TAIFG
46904 \ ------------------------------\
46905 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
46906 \ ------------------------------\
46907 \                        000    \ TAxEX0
46908 \                        ---    \ TAIDEX    pre divisor
46909 \ ------------------------------\
46910 \          %0000 0000 0000 0101 \ TAxCCR0
46911     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
46912 \ ------------------------------\
46913 \          %0000 0000 0001 0000 \ TAxCCTL0
46914 \                   -           \ CAP capture/compare mode = compare
46915 \                        -      \ CCIEn
46916 \                             - \ CCIFGn
46917     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
46918 \ ------------------------------\
46919     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
46920 \ ------------------------------\
46921 \ define LPM mode for ACCEPT    \
46922 \ ------------------------------\
46923 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
46924 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
46925 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
46926 \ ------------------------------\
46927 \ activate I/O                  \
46928 \ ------------------------------\
46929 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
46930 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
46931 \ ------------------------------\
46932 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
46933 \ ------------------------------\
46934 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
46935 \ CMP #2,Y                        \ Power_ON event
46936 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
46937 CMP #4,Y                        \
46938 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
46939 \ CMP #6,Y                        \
46940 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
46941 \ CMP #$0A,Y                      \
46942 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
46943 \ CMP #$16,Y                      \
46944 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
46945 \ ------------------------------\
46946 COLON                           \
46947 \ ------------------------------\
46948 \ Init LCD 2x20                 \
46949 \ ------------------------------\
46950     #1000 20_US                 \ 1- wait 20 ms
46951     %011 TOP_LCD                \ 2- send DB5=DB4=1
46952     #205 20_US                  \ 3- wait 4,1 ms
46953     %011 TOP_LCD                \ 4- send again DB5=DB4=1
46954     #5 20_US                    \ 5- wait 0,1 ms
46955     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
46956     #2 20_US                    \    wait 40 us = LCD cycle
46957     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
46958     #2 20_US                    \    wait 40 us = LCD cycle
46959     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
46960     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
46961     LCD_CLEAR                   \ 10- "LCD_Clear"
46962     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
46963     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
46964     LCD_CLEAR                   \ 10- "LCD_Clear"
46965     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
46966     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
46967     CR ." I love you"           \ display message on LCD
46968     ['] CR >BODY IS CR          \ CR executes its default value
46969     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
46970     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
46971     PWR_STATE ABORT             \ init DP and continues with ABORT
46972 ;                               \
46973 \ ------------------------------\
46974
46975 \ ------------------------------\
46976 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
46977 \ ------------------------------\
46978 MOV #SLEEP,X                    \ replace default background process SLEEP
46979 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
46980 MOV #WARM,X                     \ replace default WARM
46981 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
46982 MOV X,PC                        \ then execute new WARM
46983 ENDCODE 
46984 \ ------------------------------\
46985
46986 ECHO
46987             ; downloading RC5toLCD.4th is done
46988 RST_HERE    ; this app is protected against <reset>
46989
46990
46991 RST_STATE
46992
46993 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN]     \ remove application
46994
46995 [UNDEFINED] MARKER [IF]
46996 \  https://forth-standard.org/standard/core/MARKER
46997 \  MARKER
46998 \ ( "<spaces>name" -- )
46999 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
47000 \ with the execution semantics defined below.
47001
47002 \ name Execution: ( -- )
47003 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
47004 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
47005 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
47006 \ not necessarily provided. No other contextual information such as numeric base is affected
47007 \
47008 : MARKER
47009 CREATE
47010 HI2LO
47011 MOV &LASTVOC,0(W)   \ [BODY] = LASTVOC
47012 SUB #2,Y            \ 1 Y = LFA
47013 MOV Y,2(W)          \ 3 [BODY+2] = LFA = DP to be restored
47014 ADD #4,&DP          \ 3 add 2 cells
47015 LO2HI
47016 DOES>
47017 HI2LO
47018 MOV @RSP+,IP        \ -- PFA
47019 MOV @TOS+,&INIVOC   \       set VOC_LINK value for RST_STATE
47020 MOV @TOS,&INIDP     \       set DP value for RST_STATE
47021 MOV @PSP+,TOS       \ --
47022 MOV #RST_STATE,PC   \       execute RST_STATE, PWR_STATE then STATE_DOES
47023 ENDCODE
47024 [THEN]
47025
47026 MARKER {RC5TOLCD}
47027
47028 [UNDEFINED] @ [IF]
47029 \ https://forth-standard.org/standard/core/Fetch
47030 \ @     c-addr -- char   fetch char from memory
47031 CODE @
47032 MOV @TOS,TOS
47033 MOV @IP+,PC
47034 ENDCODE
47035 [THEN]
47036
47037 [UNDEFINED] CONSTANT [IF]
47038 \ https://forth-standard.org/standard/core/CONSTANT
47039 \ CONSTANT <name>     n --                      define a Forth CONSTANT 
47040 : CONSTANT 
47041 CREATE
47042 HI2LO
47043 MOV TOS,-2(W)           \   PFA = n
47044 MOV @PSP+,TOS
47045 MOV @RSP+,IP
47046 MOV @IP+,PC
47047 ENDCODE
47048 [THEN]
47049
47050 [UNDEFINED] STATE [IF]
47051 \ https://forth-standard.org/standard/core/STATE
47052 \ STATE   -- a-addr       holds compiler state
47053 STATEADR CONSTANT STATE
47054 [THEN]
47055
47056 [UNDEFINED] = [IF]
47057 \ https://forth-standard.org/standard/core/Equal
47058 \ =      x1 x2 -- flag         test x1=x2
47059 CODE =
47060 SUB @PSP+,TOS   \ 2
47061 0<> IF          \ 2
47062     AND #0,TOS  \ 1
47063     MOV @IP+,PC \ 4
47064 THEN
47065 XOR #-1,TOS     \ 1 flag Z = 1
47066 MOV @IP+,PC     \ 4
47067 ENDCODE
47068 [THEN]
47069
47070 [UNDEFINED] IF [IF]
47071 \ https://forth-standard.org/standard/core/IF
47072 \ IF       -- IFadr    initialize conditional forward branch
47073 CODE IF       \ immediate
47074 SUB #2,PSP              \
47075 MOV TOS,0(PSP)          \
47076 MOV &DP,TOS             \ -- HERE
47077 ADD #4,&DP            \           compile one word, reserve one word
47078 MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
47079 ADD #2,TOS              \ -- HERE+2=IFadr
47080 MOV @IP+,PC
47081 ENDCODE IMMEDIATE
47082 [THEN]
47083
47084 [UNDEFINED] THEN [IF]
47085 \ https://forth-standard.org/standard/core/THEN
47086 \ THEN     IFadr --                resolve forward branch
47087 CODE THEN               \ immediate
47088 MOV &DP,0(TOS)          \ -- IFadr
47089 MOV @PSP+,TOS           \ --
47090 MOV @IP+,PC
47091 ENDCODE IMMEDIATE
47092 [THEN]
47093
47094 [UNDEFINED] ELSE [IF]
47095 \ https://forth-standard.org/standard/core/ELSE
47096 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
47097 CODE ELSE     \ immediate
47098 ADD #4,&DP              \ make room to compile two words
47099 MOV &DP,W               \ W=HERE+4
47100 MOV #BRAN,-4(W)
47101 MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
47102 SUB #2,W                \ HERE+2
47103 MOV W,TOS               \ -- ELSEadr
47104 MOV @IP+,PC
47105 ENDCODE IMMEDIATE
47106 [THEN]
47107
47108 [UNDEFINED] DEFER [IF]
47109 \ https://forth-standard.org/standard/core/DEFER
47110 \ DEFER "<spaces>name"   --
47111 \ Skip leading space delimiters. Parse name delimited by a space.
47112 \ Create a definition for name with the execution semantics defined below.
47113
47114 \ name Execution:   --
47115 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
47116 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
47117 : DEFER
47118 CREATE
47119 HI2LO
47120 MOV #$4030,-4(W)        \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
47121 MOV #NEXT_ADR,-2(W)     \ PFA = address of MOV @IP+,PC to do nothing.
47122 MOV @RSP+,IP
47123 MOV @IP+,PC
47124 ENDCODE
47125 [THEN]
47126
47127 [UNDEFINED] DEFER! [IF]
47128 \ https://forth-standard.org/standard/core/DEFERStore
47129 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
47130 CODE DEFER!             \ xt2 xt1 --
47131 MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
47132 MOV @PSP+,TOS           \ --
47133 MOV @IP+,PC
47134 ENDCODE
47135 [THEN]
47136
47137 [UNDEFINED] IS [IF]
47138 \ https://forth-standard.org/standard/core/IS
47139 \ IS <name>        xt --
47140 \ used as is :
47141 \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
47142 \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
47143 \ or in a definition : ... ['] U. IS DISPLAY ...
47144 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
47145 \
47146 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
47147 : IS
47148 STATE @
47149 IF  POSTPONE ['] POSTPONE DEFER! 
47150 ELSE ' DEFER! 
47151 THEN
47152 ; IMMEDIATE
47153 [THEN]
47154
47155 [UNDEFINED] >BODY [IF]
47156 \ https://forth-standard.org/standard/core/toBODY
47157 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
47158 CODE >BODY
47159 ADD #4,TOS
47160 MOV @IP+,PC
47161 ENDCODE
47162 [THEN]
47163
47164 \ CODE 20uS           \ n --      8MHz version
47165 \ BEGIN               \ 4 + 16 ~ loop
47166 \     MOV #39,rDOCON   \ 39
47167 \     BEGIN           \ 4 ~ loop
47168 \         NOP
47169 \         SUB #1,rDOCON
47170 \     0=  UNTIL
47171 \     SUB #1,TOS      \ 1
47172 \ 0= UNTIL
47173 \ MOV #XDOCON,rDOCON  \ 2
47174 \ MOV @PSP+,TOS
47175 \ MOV @RSP+,IP        \
47176 \ ENDCODE
47177
47178 CODE 20_US                      \ n --      n * 20 us
47179 BEGIN                           \ here we presume that LCD_TIM_IFG = 1...
47180     BEGIN
47181         BIT #1,&LCD_TIM_CTL     \ 3
47182     0<> UNTIL                   \ 2         loop until LCD_TIM_IFG set
47183     BIC #1,&LCD_TIM_CTL         \ 3         clear LCD_TIM_IFG
47184     SUB #1,TOS                  \ 1
47185 U< UNTIL                        \ 2 ...so add a dummy loop with U< instead of 0=
47186 MOV @PSP+,TOS                   \ 2
47187 MOV @IP+,PC                     \ 4
47188 ENDCODE
47189
47190 CODE TOP_LCD                    \ LCD Sample
47191 \                               \ if write : %xxxx_WWWW --
47192 \                               \ if read  : -- %0000_RRRR
47193     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
47194     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
47195 0= IF                           \ write LCD bits pattern
47196     AND.B #LCD_DB,TOS           \ 
47197     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
47198     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
47199     MOV @PSP+,TOS               \
47200     MOV @IP+,PC
47201 THEN                            \ read LCD bits pattern
47202     SUB #2,PSP
47203     MOV TOS,0(PSP)
47204     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
47205     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
47206     AND.B #LCD_DB,TOS           \
47207     MOV @IP+,PC
47208 ENDCODE
47209
47210 CODE LCD_WRC                    \ char --         Write Char
47211     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
47212 BW1 SUB #2,PSP                  \
47213     MOV TOS,0(PSP)              \ -- %xxxx_LLLL %HHHH_LLLL
47214     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
47215     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
47216     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
47217 COLON                           \ high level word starts here 
47218     TOP_LCD 2 20_US             \ write high nibble first
47219     TOP_LCD 2 20_US 
47220 ;
47221
47222 CODE LCD_WRF                    \ func --         Write Fonction
47223     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
47224     GOTO BW1
47225 ENDCODE
47226
47227 : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
47228 : LCD_HOME $02 LCD_WRF 100 20_us ;
47229
47230 \ [UNDEFINED] OR [IF]
47231
47232 \ \ https://forth-standard.org/standard/core/OR
47233 \ \ C OR     x1 x2 -- x3           logical OR
47234 \ CODE OR
47235 \ BIS @PSP+,TOS
47236 \ MOV @IP+,PC
47237 \ ENDCODE
47238
47239 \ [THEN]
47240
47241 \ : LCD_ENTRY_SET     $04 OR LCD_WrF ;
47242 \ : LCD_DSP_CTRL      $08 OR LCD_WrF ;
47243 \ : LCD_DSP_SHIFT     $10 OR LCD_WrF ;
47244 \ : LCD_FN_SET        $20 OR LCD_WrF ;
47245 \ : LCD_CGRAM_SET     $40 OR LCD_WrF ;
47246 \ : LCD_GOTO          $80 OR LCD_WrF ;
47247
47248
47249 \ CODE LCD_RDS                    \ -- status       Read Status
47250 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
47251 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
47252 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
47253 \ COLON                           \ starts a FORTH word
47254 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
47255 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
47256 \ HI2LO                           \ switch from FORTH to assembler
47257 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
47258 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
47259 \     MOV @RSP+,IP                \ restore IP saved by COLON
47260 \     MOV @IP+,PC                 \
47261 \ ENDCODE
47262
47263 \ CODE LCD_RDC                    \ -- char         Read Char
47264 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
47265 \     GOTO BW1
47266 \ ENDCODE
47267
47268
47269 \ ******************************\
47270 ASM WDT_INT                     \ Watchdog interrupt routine, warning : not FORTH executable !
47271 \ ******************************\
47272 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
47273 \ XOR.B #LED1,&LED1_OUT           \ to visualise WDT
47274 BIT.B #SW2,&SW2_IN              \ test switch S2
47275 0= IF                           \ case of switch S2 pressed
47276     CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
47277     U< IF
47278         ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
47279     THEN
47280 ELSE
47281     BIT.B #SW1,&SW1_IN          \ test switch S1 input
47282     0= IF                       \ case of Switch S1 pressed
47283         CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
47284         U>= IF                  \
47285            SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
47286         THEN                    \
47287     THEN                        \
47288 THEN                            \
47289 BW1                             \ from quit on truncated RC5 message, repeated RC5 command
47290 RET                             \ 5
47291 ENDASM
47292
47293 \ ******************************\
47294 ASM RC5_INT                     \   wake up on Px.RC5 change interrupt
47295 \ ******************************\
47296 \ IR_RC5 driver                 \ IP,S,T,W,X,Y registers are free for use
47297 \ ******************************\
47298 \                               \ in :  SR(9)=old Toggle bit memory (ADD on)
47299 \                               \       SMclock = 8|16|24 MHz
47300 \                               \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
47301 \                               \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
47302 \                               \       SR(9)=new Toggle bit memory (ADD on)
47303 \ ******************************\
47304 \ RC5_FirstStartBitHalfCycle:   \
47305 \ ******************************\                division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
47306 ADD #2,RSP                      \ 1  smart and fast RETI with GIE=0
47307 \ FREQ_KHZ @ 8000 = [IF]        \ 8 MHz ?
47308 \     MOV #0,&RC5_TIM_EX0       \ predivide by 1 in RC5_TIM_EX0 register, reset value
47309 \ [THEN]
47310 FREQ_KHZ @ 16000 = [IF]         \ 16 MHz ?
47311     MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
47312 [THEN]
47313 FREQ_KHZ @ 24000 = [IF]         \ 24 MHz ?
47314     MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
47315 [THEN]
47316 MOV #1778,X                     \ RC5_Period * 1us
47317 MOV #14,W                       \ count of loop
47318 BEGIN                           \
47319 \ ******************************\
47320 \ RC5_HalfCycle                 \ <--- loop back ---+ with readjusted RC5_Period
47321 \ ******************************\                   |
47322 MOV #%1011100100,&RC5_TIM_CTL   \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
47323 \ RC5_Compute_3/4_Period:       \                   |
47324     RRUM    #1,X                \ X=1/2 cycle       |
47325     MOV     X,Y                 \                   ^
47326     RRUM    #1,Y                \ Y=1/4
47327     ADD     X,Y                 \ Y=3/4 cycle
47328     BEGIN   CMP Y,&RC5_TIM_R    \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles 
47329     U>= UNTIL                   \ 2
47330 \ ******************************\
47331 \ RC5_SampleOnFirstQuarter      \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
47332 \ ******************************\
47333     BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
47334     ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
47335     MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
47336     BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
47337     SUB     #1,W                \ decrement count loop
47338 \                               \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
47339 \                               \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1 
47340 0<> WHILE                       \ ----> out of loop ----+
47341     ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
47342     BEGIN                       \                       |
47343         MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
47344         CMP Y,X                 \ 1                     |   cycle time out of bound ?
47345         U>= IF                  \ 2                 ^   |   yes:
47346         BIC #$30,&RC5_TIM_CTL   \                   |   |      stop timer
47347         GOTO BW1                \                   |   |      quit on truncated RC5 message
47348         THEN                    \                   |   |
47349         BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
47350     0<> UNTIL                   \ 2                 |   |
47351 REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
47352 \ ******************************\                       |
47353 \ RC5_SampleEndOf:              \ <---------------------+
47354 \ ******************************\
47355 BIC #$30,&RC5_TIM_CTL           \   stop timer
47356 \ ******************************\
47357 \ RC5_ComputeNewRC5word         \
47358 \ ******************************\
47359 RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
47360 MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
47361 RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
47362 \ ******************************\
47363 \ RC5_ComputeC6bit              \
47364 \ ******************************\
47365 BIT     #BIT14,T                \ test /C6 bit in T
47366 0= IF   BIS #BIT6,X             \ set C6 bit in X
47367 THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
47368 \ ******************************\
47369 \ RC5_CommandByteIsDone         \ -- BASE RC5_code
47370 \ ******************************\
47371 \ Only New_RC5_Command ADD_ON   \ use SR(9) bit as toggle bit
47372 \ ******************************\
47373 RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
47374 XOR     @RSP,T                  \ (new XOR old) Toggle bits
47375 BIT     #UF10,T                 \ repeated RC5_command ?
47376 0= ?GOTO BW1                    \ yes, RETI without UF10 change and without action !
47377 XOR #UF10,0(RSP)                \ 5 toggle bit memory
47378 \ ******************************\
47379 \ Display IR_RC5 code           \
47380 \ ******************************\
47381 SUB #8,PSP                      \ TOS -- x x x x TOS
47382 MOV TOS,6(PSP)                  \     -- Save_TOS x x x TOS
47383 MOV &BASEADR,4(PSP)             \     -- Save_TOS Save_Base x x TOS
47384 MOV #$10,&BASEADR               \                                               set hexadecimal base
47385 MOV X,0(PSP)                    \     -- Save_TOS Save_Base x RC5_code TOS      convert number to ascii low word = RC5 byte
47386 MOV #0,TOS                      \     -- Save_TOS Save_Base x RC5_code 0        convert number to ascii high word = 0
47387 LO2HI                           \                                               switch from assembler to FORTH
47388     LCD_CLEAR                   \                                               set LCD cursor at home
47389     <# # #S #36 HOLD #>         \                                               32 bits conversion as "$xx"
47390     ['] LCD_WRC IS EMIT         \                                               redirect EMIT to LCD
47391     TYPE                        \     -- Save_TOS Save_Base x adr cnt           display "$xx" on LCD
47392     ['] EMIT >BODY IS EMIT      \     -- Save_TOS Save_Base TOS                 restore EMIT
47393 HI2LO                           \     --                                        switch from FORTH to assembler
47394 MOV @PSP+,&BASEADR              \     -- Save_TOS TOS                           restore current BASE
47395 MOV @PSP+,TOS                   \     -- TOS
47396 RET
47397 ENDASM
47398
47399 \ ******************************\
47400 ASM BACKGROUND                  \
47401 \ ******************************\
47402 BEGIN
47403 \     ...                         \ insert here your background task
47404 \     ...                         \
47405 \     ...                         \
47406     CALL &RXON                  \ comment this line to disable TERMINAL_INPUT
47407     BIS &LPM_MODE,SR            \
47408 \ ******************************\
47409 \ here start all interrupts     \
47410 \ ******************************\
47411 \ here return all interrupts    \
47412 \ ******************************\
47413 AGAIN                           \
47414 ENDASM                          \
47415 \ ******************************\
47416
47417 \ ------------------------------\
47418 ASM SYS_OUT                    \ system OUT init, replaces WARM at the request of STOP.
47419 \ ------------------------------\
47420 \     ...                         \ init specific I/O sys as you want
47421 \     ...                         \ before executing default WARM
47422     MOV #WARM,X                 \ ['] WARM 
47423     ADD #4,X                    \ >BODY
47424     MOV X,PC                    \ EXECUTE    (which activates IO and TERMINAL)
47425 ENDASM
47426 \ ------------------------------\
47427
47428 \ ------------------------------\
47429 CODE STOP                       \ stops multitasking, must to be used before downloading app
47430 \ ------------------------------\
47431 BW1 MOV #SLEEP,X                \ the ASM word SLEEP is only visible in mode assembler. 
47432     ADD #4,X                    \ X = BODY of SLEEP, X-2 = PFA of SLEEP
47433     MOV X,-2(X)                 \ restore the default background: SLEEP
47434     MOV #WARM,X
47435     MOV #SYS_OUT,2(X)           \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
47436     BIC.B #RC5,&IR_IE           \ clear RC5_Int
47437     BIC.B #RC5,&IR_IFG          \ clear RC5_Int flag
47438     MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER
47439     MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
47440     MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
47441     CALL #INIT_VECT             \ reset all vectors other than TERMINAL_int
47442 COLON                           \ restore default action of primary DEFERred word WARM (FORTH version)
47443 ECHO                            \
47444 ." RC5toLCD is removed,"
47445 ."  type START to restart"
47446  WARM                           \ performs reset to reset all interrupt vectors.    
47447 ;
47448 \ ------------------------------\
47449
47450 \ ------------------------------\
47451 CODE SYS_INIT                   \ this routine completes the init of system, i.e. FORTH + this app.
47452 \ ------------------------------\
47453 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
47454 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
47455 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
47456 \                           --       \ID input divider \ 10 = /4
47457 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
47458 \                                 -  \TBCLR TimerB Clear
47459 \                                  - \TBIE
47460 \                                   -\TBIFG
47461 \ -------------------------------\
47462 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
47463 \                  --                 \CM Capture Mode
47464 \                    --               \CCIS
47465 \                       -             \SCS
47466 \                        --           \CLLD
47467 \                          -          \CAP
47468 \                            ---      \OUTMOD \ 011 = set/reset
47469 \                               -     \CCIE
47470 \                                 -   \CCI
47471 \                                  -  \OUT
47472 \                                   - \COV
47473 \                                    -\CCIFG
47474 \ -------------------------------\
47475 \ LCD_TIM_CCRx                   \
47476 \ -------------------------------\
47477 \ LCD_TIM_EX0                    \ 
47478 \ ------------------------------\
47479 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
47480 \ ------------------------------\
47481 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
47482 \    MOV #0,&LCD_TIM_EX0        \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
47483 FREQ_KHZ @ 16000 = [IF]         \ if 16 MHz
47484     MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
47485 [THEN]
47486 FREQ_KHZ @ 24000 = [IF]         \ if 24 MHz
47487     MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
47488 [THEN]
47489     MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
47490 \ ------------------------------\
47491 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
47492 \ ------------------------------\
47493 MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
47494     MOV #10,&LCD_TIM_CCRn       \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
47495 \    MOV #12,&LCD_TIM_CCRn        \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
47496 \ ------------------------------\
47497     BIS.B #LCDVo,&LCDVo_DIR     \
47498     BIS.B #LCDVo,&LCDVo_SEL     \ SEL.2
47499 \ ------------------------------\
47500     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
47501     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
47502 \ ------------------------------\
47503     BIS.B #LCD_DB,&LCD_DB_DIR   \ as output, wired to DB(4-7) LCD_Data
47504     BIC.B #LCD_DB,&LCD_DB_REN   \ LCD_Data pullup/down disable
47505 \ ******************************\
47506 \ init RC5_Int                  \
47507 \ ******************************\
47508     BIS.B #RC5,&IR_IE           \ enable RC5_Int
47509     BIC.B #RC5,&IR_IFG          \ reset RC5_Int flag
47510     MOV #RC5_INT,&IR_Vec        \ init interrupt vector
47511 \ ******************************\
47512 \ init WatchDog WDT_TIM_        \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
47513 \ ******************************\
47514 \              %01 0001 0100    \ TAxCTL
47515 \               --              \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
47516 \                  --           \ ID        divided by 1
47517 \                    --         \ MC        MODE = up to TAxCCRn
47518 \                        -      \ TACLR     clear timer count
47519 \                         -     \ TAIE
47520 \                          -    \ TAIFG
47521 \ ------------------------------\
47522 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int, 
47523 \ ------------------------------\
47524 \                        000    \ TAxEX0
47525 \                        ---    \ TAIDEX    pre divisor
47526 \ ------------------------------\
47527 \          %0000 0000 0000 0101 \ TAxCCR0
47528     MOV ##3276,&WDT_TIM_CCR0    \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
47529 \ ------------------------------\
47530 \          %0000 0000 0001 0000 \ TAxCCTL0
47531 \                   -           \ CAP capture/compare mode = compare
47532 \                        -      \ CCIEn
47533 \                             - \ CCIFGn
47534     MOV #%10000,&WDT_TIM_CCTL0  \ enable compare interrupt, clear CCIFG0
47535 \ ------------------------------\
47536     MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
47537 \ ------------------------------\
47538 \ define LPM mode for ACCEPT    \
47539 \ ------------------------------\
47540 \    MOV #LPM4,&LPM_MODE         \ with MSP430FR59xx
47541 \    MOV #LPM2,&LPM_MODE         \ with MSP430FR57xx, terminal input don't work for LPMx > 2
47542 \                               \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
47543 \ ------------------------------\
47544 \ activate I/O                  \
47545 \ ------------------------------\
47546 BIC #1,&PM5CTL0                 \ activate all previous I/O settings; if not activated, nothing works after reset !
47547 BIS.B #TERM_BUS,&TERM_SEL       \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
47548 \ ------------------------------\
47549 \ RESET events handling         \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
47550 \ ------------------------------\
47551 MOV &SAVE_SYSRSTIV,Y            \ Y = SYSRSTIV register memory
47552 \ CMP #2,Y                        \ Power_ON event
47553 \ 0= ?GOTO BW1                    \ uncomment if you want to loose application in this case...
47554 CMP #4,Y                        \
47555 0= ?GOTO BW1                    \ hardware RESET performs STOP. Should be mandatory...
47556 \ CMP #6,Y                        \
47557 \ 0= ?GOTO BW1                    \ COLD event performs STOP... uncomment if it's that you want.
47558 \ CMP #$0A,Y                      \
47559 \ 0= ?GOTO BW1                    \ fault event (violation memory protected areas) performs STOP
47560 \ CMP #$16,Y                      \
47561 \ U>= ?GOTO BW1                   \ all other fault events + Deep Reset perform STOP
47562 \ ------------------------------\
47563 COLON                           \
47564 \ ------------------------------\
47565 \ Init LCD 2x20                 \
47566 \ ------------------------------\
47567     #1000 20_US                 \ 1- wait 20 ms
47568     %011 TOP_LCD                \ 2- send DB5=DB4=1
47569     #205 20_US                  \ 3- wait 4,1 ms
47570     %011 TOP_LCD                \ 4- send again DB5=DB4=1
47571     #5 20_US                    \ 5- wait 0,1 ms
47572     %011 TOP_LCD                \ 6- send again again DB5=DB4=1
47573     #2 20_US                    \    wait 40 us = LCD cycle
47574     %010 TOP_LCD                \ 7- send DB5=1 DB4=0
47575     #2 20_US                    \    wait 40 us = LCD cycle
47576     %00101000 LCD_WRF           \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
47577     %1000 LCD_WRF               \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
47578     LCD_CLEAR                   \ 10- "LCD_Clear"
47579     %0110 LCD_WRF               \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
47580     %1100 LCD_WRF               \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
47581     LCD_CLEAR                   \ 10- "LCD_Clear"
47582     ['] LCD_HOME IS CR          \ ' CR redirected to LCD_HOME
47583     ['] LCD_WRC  IS EMIT        \ ' EMIT redirected to LCD_WrC
47584     CR ." I love you"           \ display message on LCD
47585     ['] CR >BODY IS CR          \ CR executes its default value
47586     ['] EMIT >BODY IS EMIT      \ EMIT executes its defaulte value
47587     ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
47588     PWR_STATE ABORT             \ init DP and continues with ABORT
47589 ;                               \
47590 \ ------------------------------\
47591
47592 \ ------------------------------\
47593 CODE START                      \ this routine replaces WARM and SLEEP default values by these of this application.
47594 \ ------------------------------\
47595 MOV #SLEEP,X                    \ replace default background process SLEEP
47596 MOV #BACKGROUND,2(X)            \ by RC5toLCD BACKGROUND
47597 MOV #WARM,X                     \ replace default WARM
47598 MOV #SYS_INIT,2(X)              \ by RC5toLCD SYS_INIT
47599 MOV X,PC                        \ then execute new WARM
47600 ENDCODE 
47601 \ ------------------------------\
47602
47603 ECHO
47604             ; downloading RC5toLCD.4th is done
47605 RST_HERE    ; this app is protected against <reset>
47606
47607 \ START