OSDN Git Service

V309
[fast-forth/master.git] / MSP430-FORTH / PROG10K.f
1 \ -*- coding: utf-8 -*-
2
3 ; -----------------------------------
4 ; PROG10K.f
5 ; -----------------------------------
6
7 ; load and compile 10kb (9 x RC52LCD)
8
9 \ to see kernel options, download FastForthSpecs.f
10 \ FastForth kernel options: MSP430ASSEMBLER, CONDCOMP, FREQUENCY = 8/16/24 MHz
11 \
12 \ TARGET SELECTION ( = the name of \INC\target.pat file without the extension)
13 \ MSP_EXP430FR5739  MSP_EXP430FR5969    MSP_EXP430FR5994    MSP_EXP430FR6989
14 \ MSP_EXP430FR2355
15 \ LP_MSP430FR2476
16 \
17 \ from scite editor : copy your target selection in (shift+F8) parameter 1:
18 \
19 \ OR
20 \
21 \ drag and drop this file onto SendSourceFileToTarget.bat
22 \ then select your TARGET when asked.
23 \
24 \
25 \ ================================================================================
26 \ REGISTERS USAGE for embedded MSP430 ASSEMBLER
27 \ ================================================================================
28 \ don't use R2, R3, R4
29 \ R5, R6, R7 must be PUSHed/POPed before/after use, OR restored after: MOV #{XDOCOL|XDOCON|R>},{rDODOES|rDOCON|rDOVAR}
30 \ scratch registers Y to S are free,
31 \ under interrupt, IP is free,
32 \ use FORTH rules for reg. TOS, PSP, RSP.
33 \
34 \ PUSHM order : PSP,TOS, IP, S , T , W , X , Y ,rDOVAR,rDOCON,rDODOES,rDOCOL, R3, SR,RSP, PC
35 \ PUSHM order : R15,R14,R13,R12,R11,R10, R9, R8,  R7  ,  R6  ,  R5   ,  R4  , R3, R2, R1, R0
36 \
37 \ example : PUSHM #6,IP pushes IP,S,T,W,X,Y registers to return stack
38 \
39 \ POPM  order :  PC,RSP, SR, R3, rDODOES,rDOCON,rDOVAR,rEXIT,  Y,  X,  W,  T,  S, IP,TOS,PSP
40 \ POPM  order :  R0, R1, R2, R3,   R4   ,  R5  ,  R6  ,  R7 , R8, R9,R10,R11,R12,R13,R14,R15
41 \
42 \ example : POPM #6,IP   pop Y,X,W,T,S,IP registers from return stack
43 \
44 \ ASSEMBLER conditionnal usage after IF UNTIL WHILE : S< S>= U< U>= 0= 0<> 0>=
45 \ ASSEMBLER conditionnal usage before      ?GOTO    : S< S>= U< U>= 0= 0<> 0<
46 \
47 \
48 \ display on a LCD 2x20 CHAR the code sent by an IR remote under philips RC5 protocol
49 \ target : any TI MSP-EXP430FRxxxx launchpad (FRAM)
50 \ LPM_MODE = LPM0 because use SMCLK for LCDVo
51 \
52 \ DEMO : driver for IR remote compatible with the PHILIPS RC5 protocol
53 \ plus : driver for 5V LCD 2x20 characters display with 4 bits data interface
54 \        without usage of an auxiliary 5V to feed the LCD_Vo
55 \        and without potentiometer to adjust the LCD contrast :
56 \        to adjust LCD contrast, just press S1 (-) or S2 (+)
57 \        LCDVo current consumption ~ 500 uA.
58 \
59 \ ===================================================================================
60 \ notice : adjust WDT_TIM_EX0,LCD_TIM_CTL,LCD_TIM_EX0 and 20_us to the target frequency if <> 8MHz !
61 \ ===================================================================================
62 \
63 \
64 \ layout : I/O are defined in the launchpad.pat file (don't work with ChipStick_FR2433)
65 \
66 \  GND  <-------o---0V0---------->  1 LCD_Vss
67 \  VCC  >-------|---3V6-----o---->  2 LCD_Vdd
68 \               |           |
69 \              ___    470n ---
70 \               ^          ---
71 \              / \ 1N4148   |
72 \              ---          |
73 \          100n |    2k2    |
74 \ TB0.2 >---||--o--^/\/\/v--o---->  3 LCD_Vo (= 0V6 without modulation)
75 \       ------------------------->  4 LCD_RW
76 \       ------------------------->  5 LCD_RW
77 \       ------------------------->  6 LCD_EN
78 \       <------------------------> 11 LCD_DB4
79 \       <------------------------> 12 LCD_DB5
80 \       <------------------------> 13 LCD_DB5
81 \       <------------------------> 14 LCD_DB7
82 \
83 \       <----- LCD contrast + <---    Sw1   <--- (finger) :-)
84 \       <----- LCD contrast - <---    Sw2   <--- (finger) :-)
85 \
86 \ rc5   <--- OUT IR_Receiver (1 TSOP32236)
87
88
89 \ first, we test for downloading driver only if UART TERMINAL target
90     CODE ABORT_RC5TOLCD
91     SUB #2,PSP
92     MOV TOS,0(PSP)
93     MOV &VERSION,TOS
94     SUB #309,TOS        \                   FastForth V3.9
95     COLON
96     'CR' EMIT            \ return to column 1 without 'LF'
97     ABORT" FastForth V3.9 please!"
98     RST_RET              \ remove ABORT_UARTI2CS definition before resuming
99     ;
100
101     ABORT_RC5TOLCD
102
103     MARKER {RC5TOLCD}   \ restore the state before MARKER definition
104 \                       \ {UARTI2CS}-2 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
105     8 ALLOT             \ {UARTI2CS}    make room to save previous INI_APP address
106                         \ {RC5TOLCD}+2  make room to save previous WDT_TIM_0_VEC
107                         \ {RC5TOLCD}+4  make room to save previous IR_VEC
108                         \ {RC5TOLCD}+6  make room for 20 us count loop.
109
110     [UNDEFINED] TSTBIT
111     [IF]
112     CODE TSTBIT     \ addr bit_mask -- true/flase flag
113     MOV @PSP+,X
114     AND @X,TOS
115     MOV @IP+,PC
116     ENDCODE
117     [THEN]
118
119 \ https://forth-standard.org/standard/core/Equal
120 \ =      x1 x2 -- flag         test x1=x2
121     [UNDEFINED] =
122     [IF]
123     CODE =
124     SUB @PSP+,TOS   \ 2
125     0<> IF          \ 2
126         AND #0,TOS  \ 1
127         MOV @IP+,PC \ 4
128     THEN
129     XOR #-1,TOS     \ 1 flag Z = 1
130     MOV @IP+,PC     \ 4
131     ENDCODE
132     [THEN]
133
134     [UNDEFINED] IF
135     [IF]     \ define IF and THEN
136 \ https://forth-standard.org/standard/core/IF
137 \ IF       -- IFadr    initialize conditional forward branch
138     CODE IF       \ immediate
139     SUB #2,PSP              \
140     MOV TOS,0(PSP)          \
141     MOV &DP,TOS             \ -- HERE
142     ADD #4,&DP              \           compile one word, reserve one word
143     MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
144     ADD #2,TOS              \ -- HERE+2=IFadr
145     MOV @IP+,PC
146     ENDCODE IMMEDIATE
147
148 \ https://forth-standard.org/standard/core/THEN
149 \ THEN     IFadr --                resolve forward branch
150     CODE THEN               \ immediate
151     MOV &DP,0(TOS)          \ -- IFadr
152     MOV @PSP+,TOS           \ --
153     MOV @IP+,PC
154     ENDCODE IMMEDIATE
155     [THEN]
156
157 \ https://forth-standard.org/standard/core/ELSE
158 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
159     [UNDEFINED] ELSE
160     [IF]
161     CODE ELSE     \ immediate
162     ADD #4,&DP              \ make room to compile two words
163     MOV &DP,W               \ W=HERE+4
164     MOV #BRAN,-4(W)
165     MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
166     SUB #2,W                \ HERE+2
167     MOV W,TOS               \ -- ELSEadr
168     MOV @IP+,PC
169     ENDCODE IMMEDIATE
170     [THEN]
171
172 \ \ https://forth-standard.org/standard/core/DEFERStore
173 \ \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
174 \     [UNDEFINED] IS
175 \     [IF]     \ define DEFER! and IS
176 \     CODE DEFER!             \ xt2 xt1 --
177 \     MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
178 \     MOV @PSP+,TOS           \ --
179 \     MOV @IP+,PC
180 \     ENDCODE
181 \
182 \ \ https://forth-standard.org/standard/core/IS
183 \ \ IS <name>        xt --
184 \ \ used as is :
185 \ \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
186 \ \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
187 \ \ or in a definition : ... ['] U. IS DISPLAY ...
188 \ \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
189 \ \
190 \ \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
191 \
192 \     : IS
193 \     STATEADR @
194 \     IF  POSTPONE ['] POSTPONE DEFER!
195 \     ELSE ' DEFER!
196 \     THEN
197 \     ; IMMEDIATE
198 \     [THEN]
199
200 \ https://forth-standard.org/standard/core/CR
201 \ CR      --               send CR+LF to the output device
202     [UNDEFINED] CR
203     [IF]
204 \ create a primary defered word, i.e. with its default runtime beginning at the >BODY of the definition
205     CODE CR     \ part I : DEFERed definition of CR
206     MOV #NEXT_ADR,PC                \ [PFA] = NEXT_ADR
207     ENDCODE
208
209     :NONAME
210     'CR' EMIT 'LF' EMIT
211     ; IS CR
212     [THEN]
213
214 \ https://forth-standard.org/standard/core/toBODY
215 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
216     [UNDEFINED] >BODY
217     [IF]
218     CODE >BODY
219     ADD #4,TOS
220     MOV @IP+,PC
221     ENDCODE
222     [THEN]
223
224     CODE 20_US                      \ n --
225     BEGIN                           \          J_loop           8000    16000  24000  kHz
226         MOV &{RC5TOLCD}+6,X         \            3          X = {40      80     120}
227         SUB #2,X                    \           +1          X = {38      78     118} I_loops + 2 J_loops = {40 80 120} * 4 cycles
228         BEGIN                       \  I_loop
229             NOP                     \    1
230             SUB #1,X                \   +1
231         0=  UNTIL                   \   +2
232         NOP                         \           +1
233         SUB #1,TOS                  \           +1
234     0= UNTIL                        \           +2
235     MOV @PSP+,TOS                   \
236     MOV @RSP+,IP                    \
237     ENDCODE
238
239 \                                   \ if write : %xxxx_WWWW --
240 \                                   \ if read  : -- %0000_RRRR
241     CODE TOP_LCD                    \ LCD Sample
242     BIS.B #LCD_EN,&LCD_CMD_OUT      \ lcd_en 0-->1
243     BIT.B #LCD_RW,&LCD_CMD_IN       \ lcd_rw test
244     0= IF                           \ write LCD bits pattern
245         AND.B #LCD_DB,TOS           \
246         MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
247         BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
248         MOV @PSP+,TOS               \
249         MOV @IP+,PC
250     THEN                            \ read LCD bits pattern
251     SUB #2,PSP
252     MOV TOS,0(PSP)
253     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
254     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
255     AND.B #LCD_DB,TOS           \
256     MOV @IP+,PC
257     ENDCODE
258
259     CODE LCD_WRC                \ char --         Write Char
260     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
261 BW1 SUB #2,PSP                  \
262     MOV TOS,0(PSP)              \ -- %HHHH_LLLL %HHHH_LLLL
263     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
264     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
265     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
266     COLON                       \ high level word starts here
267     TOP_LCD 2 20_US             \ write high nibble first
268     TOP_LCD 2 20_US
269     ;
270
271     CODE LCD_WRF                \ func --         Write Fonction
272     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
273     GOTO BW1
274     ENDCODE
275
276     : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
277     : LCD_HOME $02 LCD_WRF 100 20_us ;
278
279 \     CODE LCD_ENTRY_SET
280 \     BIS #$04,TOS
281 \ BW1 COLON
282 \     LCD_WrF
283 \     ;
284 \
285 \     CODE LCD_DSP_CTRL
286 \     BIS#$08,TOS
287 \     GOTO BW1
288 \     ENDCODE
289 \
290 \     CODE LCD_DSP_SHIFT
291 \     BIS#$10,TOS
292 \     GOTO BW1
293 \     ENDCODE
294 \
295 \     CODE LCD_FN_SET
296 \     BIS#$20,TOS
297 \     GOTO BW1
298 \     ENDCODE
299 \
300 \     CODE LCD_CGRAM_SET
301 \     BIS #$40,TOS
302 \     GOTO BW1
303 \     ENDCODE
304 \
305 \     CODE LCD_GOTO
306 \     BIS #$80,TOS
307 \     GOTO BW1
308 \     ENDCODE
309 \
310 \ CODE LCD_RDS                    \ -- status       Read Status
311 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
312 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
313 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
314 \ COLON                           \ starts a FORTH word
315 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
316 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
317 \ HI2LO                           \ switch from FORTH to assembler
318 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
319 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
320 \     MOV @RSP+,IP                \ restore IP saved by COLON
321 \     MOV @IP+,PC                 \
322 \ ENDCODE
323 \
324 \ CODE LCD_RDC                    \ -- char         Read Char
325 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
326 \     GOTO BW1
327 \ ENDCODE
328 \
329 \
330 \   ********************************\
331     HDNCODE WDT_INT                 \ Watchdog interrupt routine, warning : not FORTH executable !
332 \   ********************************\
333 \    XOR.B #LED1,&LED1_OUT           \ to visualise WDT
334     BIT.B #SW2,&SW2_IN              \ test switch S2
335     0= IF                           \ case of switch S2 pressed
336         CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
337         U< IF
338             ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
339         THEN
340     ELSE
341         BIT.B #SW1,&SW1_IN          \ test switch S1 input
342         0= IF                       \ case of Switch S1 pressed
343             CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
344             U>= IF                  \
345             SUB #1,&LCD_TIM_CCRn    \ action for switch S1 (P2.6) : -150 mV / decrement
346             THEN                    \
347         THEN                        \
348     THEN                            \
349     RETI                            \ 5
350     ENDCODE                         \
351 \   ********************************\
352
353 \   ********************************\
354     HDNCODE RC5_INT                 \   wake up on Px.RC5 change interrupt
355 \   ********************************\
356 \   IR_RC5 driver                   \ IP,S,T,W,X,Y registers are free for use
357 \   ********************************\
358 \                                   \ in :  SR(9)=old Toggle bit memory (ADD on)
359 \                                   \       SMclock = 8|16|24 MHz
360 \                                   \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
361 \                                   \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
362 \                                   \       SR(9)=new Toggle bit memory (ADD on)
363 \   ********************************\
364 \   RC5_FirstStartBitHalfCycle:     \
365 \   ********************************\
366     MOV #1778,X                     \ RC5_Period in us
367     MOV #14,W                       \ count of loop
368     BEGIN                           \
369 \       ****************************\
370 \       RC5_HalfCycle               \ <--- loop back ---+ with readjusted RC5_Period
371 \       ****************************\                   |
372       MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
373 \       RC5_Compute_3/4_Period:     \                   |
374         RRUM    #1,X                \ X=1/2 cycle       |
375         MOV     X,Y                 \                   ^
376         RRUM    #1,Y                \ Y=1/4
377         ADD     X,Y                 \ Y=3/4 cycle
378         BEGIN                       \
379             CMP Y,&RC5_TIM_R        \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
380         U>= UNTIL                   \ 2
381 \       ****************************\
382 \       RC5_SampleOnFirstQuarter    \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
383 \       ****************************\
384         BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
385         ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
386         MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
387         BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
388         SUB     #1,W                \ decrement count loop
389 \                                   \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
390 \                                   \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1
391     0<> WHILE                       \ ----> out of loop ----+
392         ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
393         BEGIN                       \                       |
394             MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
395             CMP Y,X                 \ 1                 ^   |   cycle time out of bound ?
396             U>= ?GOTO FW1           \                   |   |   quit on truncated RC5 message
397             BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
398         0<> UNTIL                   \ 2                 |   |
399     REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
400 \   ********************************\                       |
401 \   RC5_SampleEndOf:                \ <---------------------+
402 \   ********************************\
403     BIC #$30,&RC5_TIM_CTL           \   stop timer
404 \   ********************************\
405 \   RC5_ComputeNewRC5word           \
406 \   ********************************\
407     RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
408     MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
409     RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
410 \   ********************************\
411 \   RC5_ComputeC6bit                \
412 \   ********************************\
413     BIT     #BIT14,T                \ test /C6 bit in T
414     0= IF   BIS #BIT6,X             \ set C6 bit in X
415     THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
416 \   ********************************\
417 \   RC5_CommandByteIsDone           \
418 \   ********************************\
419 \   Only New_RC5_Command ADD_ON     \ use SR(10) bit as toggle bit
420 \   ********************************\
421     RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
422     XOR     @RSP,T                  \ (new XOR old) Toggle bits
423     BIT     #UF10,T                 \ repeated RC5_command ?
424     0= ?GOTO FW2                    \ yes, RETI without UF10 change and without action !
425     XOR #UF10,0(RSP)                \ 5 toggle bit memory
426 \   ********************************\
427 \   Display IR_RC5 code             \
428 \   ********************************\
429     SUB #6,PSP                      \   -- x x x TOS
430     MOV TOS,4(PSP)                  \   -- TOS x x TOS
431     MOV &BASEADR,2(PSP)             \   -- TOS Base x TOS
432     MOV #$10,&BASEADR               \                               set hexadecimal base
433     MOV X,0(PSP)                    \   -- TOS Base RC5_code TOS    convert number to ascii low word = RC5 byte
434     MOV #0,TOS                      \   -- TOS Base RC5_code 0      convert double number to ascii
435     LO2HI                           \                               switch from assembler to FORTH
436     LCD_CLEAR                       \                               set LCD cursor at home
437     <# # #S #36 HOLD #>             \   -- TOS Base adr cnt         32 bits conversion as "$xx"
438     ['] LCD_WRC IS EMIT             \                               redirect EMIT to LCD
439     TYPE                            \   -- TOS Base                 display "$xx" on LCD
440     ['] EMIT >BODY IS EMIT          \                               restore EMIT
441     HI2LO                           \                               switch from FORTH to assembler
442     MOV @PSP+,&BASEADR              \   -- TOS                      restore current BASE
443     MOV @PSP+,TOS                   \   --
444 FW1 BIC #$30,&RC5_TIM_CTL           \ stop timer (case of truncated RC5 message)
445 FW2 BIC #%1111_1000,0(RSP)          \ force CPU Active Mode and disable GIE in saved SR
446     RETI                            \
447     ENDCODE                         \
448 \   ********************************\
449
450 \ define our STOP_APP
451 \ ----------------------------------\
452     HDNCODE STOP_R2L                \ called by STOP|INIT_R2L|{RC5TOLCD}
453 \ ----------------------------------\
454     CMP #WDT_INT,&WDT_TIM_0_VEC     \ value set by START
455     0= IF                           \ only if START is done
456         BIC.B #RC5,&IR_IE           \ clear I/O RC5_Int
457         BIC.B #RC5,&IR_IFG          \ clear I/O RC5_Int flag
458         MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER, clear LCD_TIMER IFG
459         MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
460         MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
461         MOV #{RC5TOLCD},W           \
462         MOV #RET_ADR,-2(W)          \ clear MARKER_DOES call
463         KERNEL_ADDON $3C00 TSTBIT   \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
464         [IF]
465         MOV @W+,&UART_WARM+2        \ restore previous ini_APP
466         [ELSE]
467         MOV @W+,&I2C_WARM+2         \ restore previous ini_APP
468         [THEN]
469         MOV @W+,&WDT_TIM_0_VEC      \ restore Vector previous value
470         MOV @W+,&IR_VEC             \ restore Vector previous value
471     THEN
472     MOV @RSP+,PC                    \ RET to STOP|WARM+4|{RC5TOLCD}
473     ENDCODE
474 \ ----------------------------------\
475
476 \ ----------------------------------\
477     CODE STOP                       \ also called by INIT_R2L for some events
478 \ ----------------------------------\
479 BW1 CALL #STOP_R2L
480     COLON                           \
481     ECHO                            \
482     ." type START to start RC5toLCD"
483     ;
484 \ ----------------------------------\
485
486 \ this routine completes the INIT_HARD of FORTH, with INIT_HARD for this app.
487 \ ----------------------------------\
488     HDNCODE INIT_R2L                \ called by START|SYS
489 \ ----------------------------------\
490 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
491 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
492 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
493 \                           --       \ID input divider \ 10 = /4
494 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
495 \                                 -  \TBCLR TimerB Clear
496 \                                  - \TBIE
497 \                                   -\TBIFG
498 \ ----------------------------------\
499 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
500 \                  --                 \CM Capture Mode
501 \                    --               \CCIS
502 \                       -             \SCS
503 \                        --           \CLLD
504 \                          -          \CAP
505 \                            ---      \OUTMOD \ 011 = set/reset
506 \                               -     \CCIE
507 \                                 -   \CCI
508 \                                  -  \OUT
509 \                                   - \COV
510 \                                    -\CCIFG
511 \ ----------------------------------\
512 \ LCD_TIM_CCRx                      \
513 \ ----------------------------------\
514 \ LCD_TIM_EX0                       \
515 \ ----------------------------------\
516 \ set LCD_TIM_ to make 50kHz PWM    \ for LCD_Vo; works without interrupt
517 \ ----------------------------------\
518     MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int, set IFG
519 \    MOV #0,&RC5_TIM_EX0             \ predivide by 1 in RC5_TIM_EX0 register, reset value
520 \    MOV #0,&LCD_TIM_EX0             \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
521     FREQ_KHZ @ 16000 =
522     [IF]                            \ if 16 MHz
523         MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
524         MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
525     [THEN]
526     FREQ_KHZ @ 24000 =
527     [IF]                            \ if 24 MHz
528         MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
529         MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
530     [THEN]
531         MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
532 \ ----------------------------------\
533 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
534 \ ----------------------------------\
535     MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
536     MOV #10,&LCD_TIM_CCRn           \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
537 \    MOV #12,&LCD_TIM_CCRn           \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
538 \ ----------------------------------\
539     BIS.B #LCDVo,&LCDVo_DIR         \
540     BIS.B #LCDVo,&LCDVo_SEL         \ SEL.2
541 \ ----------------------------------\
542     BIS.B #LCD_CMD,&LCD_CMD_DIR     \ lcd_cmd as outputs
543     BIC.B #LCD_CMD,&LCD_CMD_REN     \ lcd_cmd pullup/down disable
544 \ ----------------------------------\
545     BIS.B #LCD_DB,&LCD_DB_DIR       \ as output, wired to DB(4-7) LCD_Data
546     BIC.B #LCD_DB,&LCD_DB_REN       \ LCD_Data pullup/down disable
547 \ ----------------------------------\
548 \ init RC5_Int                      \
549 \ ----------------------------------\
550     BIS.B #RC5,&IR_IE               \ enable RC5_Int
551     BIC.B #RC5,&IR_IFG              \ reset RC5_Int flag
552 \ ----------------------------------\
553 \ init WatchDog WDT_TIM_            \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
554 \ ----------------------------------\
555 \              %01 0001 0100        \ TAxCTL
556 \               --                  \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
557 \                  --               \ ID        divided by 1
558 \                    --             \ MC        MODE = up to TAxCCRn
559 \                        -          \ TACLR     clear timer count
560 \                         -         \ TAIE
561 \                          -        \ TAIFG
562 \ ----------------------------------\
563     MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
564 \ ----------------------------------\
565 \                        000        \ TAxEX0
566 \                        ---        \ TAIDEX    pre divisor
567 \ ----------------------------------\
568 \          %0000 0000 0000 0101     \ TAxCCR0
569     MOV ##3276,&WDT_TIM_CCR0        \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
570 \ ----------------------------------\
571 \          %0000 0000 0001 0000     \ TAxCCTL0
572 \                   -               \ CAP capture/compare mode = compare
573 \                        -          \ CCIEn
574 \                             -     \ CCIFGn
575     MOV #%10000,&WDT_TIM_CCTL0      \ enable compare interrupt, clear CCIFG0
576 \ ----------------------------------\
577 \ activate I/O                      \
578 \ ----------------------------------\
579     CALL &{RC5TOLCD}                \ run previous INIT_HARD_APP
580 \ ----------------------------------\
581 \ RESET events handling             \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
582 \ ----------------------------------\
583     CMP #$0E,TOS                    \ SYSRSTIV = SVSHIFG SVSH event ?
584     0<> IF                          \ if not
585         CMP #$0A,TOS                \   SYSRSTIV >= violation memory protected areas | USERSYS <0 = DEEP_RESET request ?
586         U>= ?GOTO BW1               \   if yes execute STOP_R2L then RET to BODY of WARM
587     THEN                            \
588 \    CMP #2,TOS                      \   Power_ON event
589 \    0= ?GOTO BW1                    \   uncomment if you want to loose application in this case...
590     CMP #4,TOS                      \   SYSRSTIV|USERSYS RST ?
591     0= ?GOTO BW1                    \   if yes run STOP.
592 \    CMP #$0E,TOS                    \   SYSRSTIV = SVSHIFG SVSH event ?
593 \    0= ?GOTO BW1                    \   SVSHIFG SVSH event performs STOP
594 \ ----------------------------------\
595     LO2HI                           \
596 \ ----------------------------------\
597 \   Init LCD 2x20                   \
598 \ ----------------------------------\
599     #1000 20_US                     \ 1- wait 20 ms
600     %011 TOP_LCD                    \ 2- send DB5=DB4=1
601     #205 20_US                      \ 3- wait 4,1 ms
602     %011 TOP_LCD                    \ 4- send again DB5=DB4=1
603     #5 20_US                        \ 5- wait 0,1 ms
604     %011 TOP_LCD                    \ 6- send again again DB5=DB4=1
605     #2 20_US                        \    wait 40 us = LCD cycle
606     %010 TOP_LCD                    \ 7- send DB5=1 DB4=0
607     #2 20_US                        \    wait 40 us = LCD cycle
608     %00101000 LCD_WRF               \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
609     %1000 LCD_WRF                   \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off.
610     LCD_CLEAR                       \ 10- "LCD_Clear"
611     %0110 LCD_WRF                   \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
612     %1100 LCD_WRF                   \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
613     LCD_CLEAR                       \ 10- "LCD_Clear"
614     HI2LO                           \
615     MOV @RSP+,PC                    \ RET to WARM|START
616     ENDCODE
617 \ ----------------------------------\
618
619 \ ----------------------------------\
620     CODE START                      \ this routine replaces INT_HARD_APP default values by these of this application.
621 \ ----------------------------------\
622     CMP #WDT_INT,&WDT_TIM_0_VEC     \ value set by START
623     0= IF                           \
624         MOV @IP+,PC                 \ does nothing if already initialised
625     THEN
626     MOV #STOP_R2L,&{RC5TOLCD}-2     \ execution of {RC5TOLCD} will perform STOP_R2L.
627     KERNEL_ADDON $3C00 TSTBIT       \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
628     [IF]
629        MOV &UART_WARM+2,&{RC5TOLCD} \ save previous INI_APP subroutine
630        MOV #INIT_R2L,&UART_WARM+2   \ replace it by RC5toLCD INI_APP
631     [ELSE]
632        MOV &I2C_WARM+2,&{RC5TOLCD}  \ save previous INI_APP subroutine
633        MOV #INIT_R2L,&I2C_WARM+2    \ replace it by RC5toLCD INI_APP
634     [THEN]
635     MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+2 \ save Vector previous value
636     MOV #WDT_INT,&WDT_TIM_0_VEC     \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
637     MOV &IR_VEC,&{RC5TOLCD}+4       \ save Vector previous value
638     MOV #RC5_INT,&IR_VEC            \ init interrupt vector
639 \ ----------------------------------\
640 \   init 20 us count loop           \ see 20_US
641 \ ----------------------------------\ -- TOS
642     SUB #6,PSP                      \ -- x x x TOS
643     MOV TOS,4(PSP)                  \ -- TOS x x TOS
644     MOV &FREQ_KHZ,2(PSP)            \ -- TOS DVDlo x TOS
645     MOV #0,0(PSP)                   \ -- TOS DVDlo DVDhi TOS
646     MOV #200,TOS                    \ -- TOS DVDlo DVDhi DIVlo
647     CALL #MUSMOD                    \ -- TOS REMlo QUOTlo QUOThi
648     MOV @PSP,&{RC5TOLCD}+6          \                       set count+2 for 20_US
649     ADD #4,PSP                      \ -- TOS QUOThi
650     MOV @PSP+,TOS                   \ -- TOS
651 \ ----------------------------------\
652     CALL #INIT_R2L                  \ run new INIT_HARD_APP
653     LO2HI
654 \    ['] LCD_HOME IS CR              \ ' CR redirected to LCD_HOME
655 \    ['] LCD_WRC  IS EMIT            \ ' EMIT redirected to LCD_WrC
656 \    CR ." I love you"               \ display message on LCD
657 \    ['] CR >BODY IS CR              \ CR executes its default value
658 \    ['] EMIT >BODY IS EMIT          \ EMIT executes its defaulte value
659     ." RC5toLCD is running,"        \
660     ."  Type STOP to quit."         \ display message on FastForth Terminal
661     HI2LO
662     MOV #ABORT,PC                   \ goto FORTH interpreter without WARM message.
663     ENDCODE                         \
664 \ ----------------------------------\
665
666 RST_SET
667 ECHO
668
669
670     MARKER {RC5TOLCD}   \ restore the state before MARKER definition
671 \                       \ {UARTI2CS}-2 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
672     8 ALLOT             \ {UARTI2CS}    make room to save previous INI_APP address
673                         \ {RC5TOLCD}+2  make room to save previous WDT_TIM_0_VEC
674                         \ {RC5TOLCD}+4  make room to save previous IR_VEC
675                         \ {RC5TOLCD}+6  make room for 20 us count loop.
676
677     [UNDEFINED] TSTBIT
678     [IF]
679     CODE TSTBIT     \ addr bit_mask -- true/flase flag
680     MOV @PSP+,X
681     AND @X,TOS
682     MOV @IP+,PC
683     ENDCODE
684     [THEN]
685
686 \ https://forth-standard.org/standard/core/Equal
687 \ =      x1 x2 -- flag         test x1=x2
688     [UNDEFINED] =
689     [IF]
690     CODE =
691     SUB @PSP+,TOS   \ 2
692     0<> IF          \ 2
693         AND #0,TOS  \ 1
694         MOV @IP+,PC \ 4
695     THEN
696     XOR #-1,TOS     \ 1 flag Z = 1
697     MOV @IP+,PC     \ 4
698     ENDCODE
699     [THEN]
700
701     [UNDEFINED] IF
702     [IF]     \ define IF and THEN
703 \ https://forth-standard.org/standard/core/IF
704 \ IF       -- IFadr    initialize conditional forward branch
705     CODE IF       \ immediate
706     SUB #2,PSP              \
707     MOV TOS,0(PSP)          \
708     MOV &DP,TOS             \ -- HERE
709     ADD #4,&DP              \           compile one word, reserve one word
710     MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
711     ADD #2,TOS              \ -- HERE+2=IFadr
712     MOV @IP+,PC
713     ENDCODE IMMEDIATE
714
715 \ https://forth-standard.org/standard/core/THEN
716 \ THEN     IFadr --                resolve forward branch
717     CODE THEN               \ immediate
718     MOV &DP,0(TOS)          \ -- IFadr
719     MOV @PSP+,TOS           \ --
720     MOV @IP+,PC
721     ENDCODE IMMEDIATE
722     [THEN]
723
724 \ https://forth-standard.org/standard/core/ELSE
725 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
726     [UNDEFINED] ELSE
727     [IF]
728     CODE ELSE     \ immediate
729     ADD #4,&DP              \ make room to compile two words
730     MOV &DP,W               \ W=HERE+4
731     MOV #BRAN,-4(W)
732     MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
733     SUB #2,W                \ HERE+2
734     MOV W,TOS               \ -- ELSEadr
735     MOV @IP+,PC
736     ENDCODE IMMEDIATE
737     [THEN]
738
739 \ \ https://forth-standard.org/standard/core/DEFERStore
740 \ \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
741 \     [UNDEFINED] IS
742 \     [IF]     \ define DEFER! and IS
743 \     CODE DEFER!             \ xt2 xt1 --
744 \     MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
745 \     MOV @PSP+,TOS           \ --
746 \     MOV @IP+,PC
747 \     ENDCODE
748 \
749 \ \ https://forth-standard.org/standard/core/IS
750 \ \ IS <name>        xt --
751 \ \ used as is :
752 \ \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
753 \ \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
754 \ \ or in a definition : ... ['] U. IS DISPLAY ...
755 \ \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
756 \ \
757 \ \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
758 \
759 \     : IS
760 \     STATEADR @
761 \     IF  POSTPONE ['] POSTPONE DEFER!
762 \     ELSE ' DEFER!
763 \     THEN
764 \     ; IMMEDIATE
765 \     [THEN]
766
767 \ https://forth-standard.org/standard/core/CR
768 \ CR      --               send CR+LF to the output device
769     [UNDEFINED] CR
770     [IF]
771 \ create a primary defered word, i.e. with its default runtime beginning at the >BODY of the definition
772     CODE CR     \ part I : DEFERed definition of CR
773     MOV #NEXT_ADR,PC                \ [PFA] = NEXT_ADR
774     ENDCODE
775
776     :NONAME
777     'CR' EMIT 'LF' EMIT
778     ; IS CR
779     [THEN]
780
781 \ https://forth-standard.org/standard/core/toBODY
782 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
783     [UNDEFINED] >BODY
784     [IF]
785     CODE >BODY
786     ADD #4,TOS
787     MOV @IP+,PC
788     ENDCODE
789     [THEN]
790
791     CODE 20_US                      \ n --
792     BEGIN                           \          J_loop           8000    16000  24000  kHz
793         MOV &{RC5TOLCD}+6,X         \            3          X = {40      80     120}
794         SUB #2,X                    \           +1          X = {38      78     118} I_loops + 2 J_loops = {40 80 120} * 4 cycles
795         BEGIN                       \  I_loop
796             NOP                     \    1
797             SUB #1,X                \   +1
798         0=  UNTIL                   \   +2
799         NOP                         \           +1
800         SUB #1,TOS                  \           +1
801     0= UNTIL                        \           +2
802     MOV @PSP+,TOS                   \
803     MOV @RSP+,IP                    \
804     ENDCODE
805
806 \                                   \ if write : %xxxx_WWWW --
807 \                                   \ if read  : -- %0000_RRRR
808     CODE TOP_LCD                    \ LCD Sample
809     BIS.B #LCD_EN,&LCD_CMD_OUT      \ lcd_en 0-->1
810     BIT.B #LCD_RW,&LCD_CMD_IN       \ lcd_rw test
811     0= IF                           \ write LCD bits pattern
812         AND.B #LCD_DB,TOS           \
813         MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
814         BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
815         MOV @PSP+,TOS               \
816         MOV @IP+,PC
817     THEN                            \ read LCD bits pattern
818     SUB #2,PSP
819     MOV TOS,0(PSP)
820     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
821     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
822     AND.B #LCD_DB,TOS           \
823     MOV @IP+,PC
824     ENDCODE
825
826     CODE LCD_WRC                \ char --         Write Char
827     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
828 BW1 SUB #2,PSP                  \
829     MOV TOS,0(PSP)              \ -- %HHHH_LLLL %HHHH_LLLL
830     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
831     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
832     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
833     COLON                       \ high level word starts here
834     TOP_LCD 2 20_US             \ write high nibble first
835     TOP_LCD 2 20_US
836     ;
837
838     CODE LCD_WRF                \ func --         Write Fonction
839     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
840     GOTO BW1
841     ENDCODE
842
843     : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
844     : LCD_HOME $02 LCD_WRF 100 20_us ;
845
846 \     CODE LCD_ENTRY_SET
847 \     BIS #$04,TOS
848 \ BW1 COLON
849 \     LCD_WrF
850 \     ;
851 \
852 \     CODE LCD_DSP_CTRL
853 \     BIS#$08,TOS
854 \     GOTO BW1
855 \     ENDCODE
856 \
857 \     CODE LCD_DSP_SHIFT
858 \     BIS#$10,TOS
859 \     GOTO BW1
860 \     ENDCODE
861 \
862 \     CODE LCD_FN_SET
863 \     BIS#$20,TOS
864 \     GOTO BW1
865 \     ENDCODE
866 \
867 \     CODE LCD_CGRAM_SET
868 \     BIS #$40,TOS
869 \     GOTO BW1
870 \     ENDCODE
871 \
872 \     CODE LCD_GOTO
873 \     BIS #$80,TOS
874 \     GOTO BW1
875 \     ENDCODE
876 \
877 \ CODE LCD_RDS                    \ -- status       Read Status
878 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
879 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
880 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
881 \ COLON                           \ starts a FORTH word
882 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
883 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
884 \ HI2LO                           \ switch from FORTH to assembler
885 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
886 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
887 \     MOV @RSP+,IP                \ restore IP saved by COLON
888 \     MOV @IP+,PC                 \
889 \ ENDCODE
890 \
891 \ CODE LCD_RDC                    \ -- char         Read Char
892 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
893 \     GOTO BW1
894 \ ENDCODE
895 \
896 \
897 \   ********************************\
898     HDNCODE WDT_INT                 \ Watchdog interrupt routine, warning : not FORTH executable !
899 \   ********************************\
900 \    XOR.B #LED1,&LED1_OUT           \ to visualise WDT
901     BIT.B #SW2,&SW2_IN              \ test switch S2
902     0= IF                           \ case of switch S2 pressed
903         CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
904         U< IF
905             ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
906         THEN
907     ELSE
908         BIT.B #SW1,&SW1_IN          \ test switch S1 input
909         0= IF                       \ case of Switch S1 pressed
910             CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
911             U>= IF                  \
912             SUB #1,&LCD_TIM_CCRn    \ action for switch S1 (P2.6) : -150 mV / decrement
913             THEN                    \
914         THEN                        \
915     THEN                            \
916     RETI                            \ 5
917     ENDCODE                         \
918 \   ********************************\
919
920 \   ********************************\
921     HDNCODE RC5_INT                 \   wake up on Px.RC5 change interrupt
922 \   ********************************\
923 \   IR_RC5 driver                   \ IP,S,T,W,X,Y registers are free for use
924 \   ********************************\
925 \                                   \ in :  SR(9)=old Toggle bit memory (ADD on)
926 \                                   \       SMclock = 8|16|24 MHz
927 \                                   \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
928 \                                   \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
929 \                                   \       SR(9)=new Toggle bit memory (ADD on)
930 \   ********************************\
931 \   RC5_FirstStartBitHalfCycle:     \
932 \   ********************************\
933     MOV #1778,X                     \ RC5_Period in us
934     MOV #14,W                       \ count of loop
935     BEGIN                           \
936 \       ****************************\
937 \       RC5_HalfCycle               \ <--- loop back ---+ with readjusted RC5_Period
938 \       ****************************\                   |
939       MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
940 \       RC5_Compute_3/4_Period:     \                   |
941         RRUM    #1,X                \ X=1/2 cycle       |
942         MOV     X,Y                 \                   ^
943         RRUM    #1,Y                \ Y=1/4
944         ADD     X,Y                 \ Y=3/4 cycle
945         BEGIN                       \
946             CMP Y,&RC5_TIM_R        \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
947         U>= UNTIL                   \ 2
948 \       ****************************\
949 \       RC5_SampleOnFirstQuarter    \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
950 \       ****************************\
951         BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
952         ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
953         MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
954         BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
955         SUB     #1,W                \ decrement count loop
956 \                                   \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
957 \                                   \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1
958     0<> WHILE                       \ ----> out of loop ----+
959         ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
960         BEGIN                       \                       |
961             MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
962             CMP Y,X                 \ 1                 ^   |   cycle time out of bound ?
963             U>= ?GOTO FW1           \                   |   |   quit on truncated RC5 message
964             BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
965         0<> UNTIL                   \ 2                 |   |
966     REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
967 \   ********************************\                       |
968 \   RC5_SampleEndOf:                \ <---------------------+
969 \   ********************************\
970     BIC #$30,&RC5_TIM_CTL           \   stop timer
971 \   ********************************\
972 \   RC5_ComputeNewRC5word           \
973 \   ********************************\
974     RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
975     MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
976     RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
977 \   ********************************\
978 \   RC5_ComputeC6bit                \
979 \   ********************************\
980     BIT     #BIT14,T                \ test /C6 bit in T
981     0= IF   BIS #BIT6,X             \ set C6 bit in X
982     THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
983 \   ********************************\
984 \   RC5_CommandByteIsDone           \
985 \   ********************************\
986 \   Only New_RC5_Command ADD_ON     \ use SR(10) bit as toggle bit
987 \   ********************************\
988     RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
989     XOR     @RSP,T                  \ (new XOR old) Toggle bits
990     BIT     #UF10,T                 \ repeated RC5_command ?
991     0= ?GOTO FW2                    \ yes, RETI without UF10 change and without action !
992     XOR #UF10,0(RSP)                \ 5 toggle bit memory
993 \   ********************************\
994 \   Display IR_RC5 code             \
995 \   ********************************\
996     SUB #6,PSP                      \   -- x x x TOS
997     MOV TOS,4(PSP)                  \   -- TOS x x TOS
998     MOV &BASEADR,2(PSP)             \   -- TOS Base x TOS
999     MOV #$10,&BASEADR               \                               set hexadecimal base
1000     MOV X,0(PSP)                    \   -- TOS Base RC5_code TOS    convert number to ascii low word = RC5 byte
1001     MOV #0,TOS                      \   -- TOS Base RC5_code 0      convert double number to ascii
1002     LO2HI                           \                               switch from assembler to FORTH
1003     LCD_CLEAR                       \                               set LCD cursor at home
1004     <# # #S #36 HOLD #>             \   -- TOS Base adr cnt         32 bits conversion as "$xx"
1005     ['] LCD_WRC IS EMIT             \                               redirect EMIT to LCD
1006     TYPE                            \   -- TOS Base                 display "$xx" on LCD
1007     ['] EMIT >BODY IS EMIT          \                               restore EMIT
1008     HI2LO                           \                               switch from FORTH to assembler
1009     MOV @PSP+,&BASEADR              \   -- TOS                      restore current BASE
1010     MOV @PSP+,TOS                   \   --
1011 FW1 BIC #$30,&RC5_TIM_CTL           \ stop timer (case of truncated RC5 message)
1012 FW2 BIC #%1111_1000,0(RSP)          \ force CPU Active Mode and disable GIE in saved SR
1013     RETI                            \
1014     ENDCODE                         \
1015 \   ********************************\
1016
1017 \ define our STOP_APP
1018 \ ----------------------------------\
1019     HDNCODE STOP_R2L                \ called by STOP|INIT_R2L|{RC5TOLCD}
1020 \ ----------------------------------\
1021     CMP #WDT_INT,&WDT_TIM_0_VEC     \ value set by START
1022     0= IF                           \ only if START is done
1023         BIC.B #RC5,&IR_IE           \ clear I/O RC5_Int
1024         BIC.B #RC5,&IR_IFG          \ clear I/O RC5_Int flag
1025         MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER, clear LCD_TIMER IFG
1026         MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
1027         MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
1028         MOV #{RC5TOLCD},W           \
1029         MOV #RET_ADR,-2(W)          \ clear MARKER_DOES call
1030         KERNEL_ADDON $3C00 TSTBIT   \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
1031         [IF]
1032         MOV @W+,&UART_WARM+2        \ restore previous ini_APP
1033         [ELSE]
1034         MOV @W+,&I2C_WARM+2         \ restore previous ini_APP
1035         [THEN]
1036         MOV @W+,&WDT_TIM_0_VEC      \ restore Vector previous value
1037         MOV @W+,&IR_VEC             \ restore Vector previous value
1038     THEN
1039     MOV @RSP+,PC                    \ RET to STOP|WARM+4|{RC5TOLCD}
1040     ENDCODE
1041 \ ----------------------------------\
1042
1043 \ ----------------------------------\
1044     CODE STOP                       \ also called by INIT_R2L for some events
1045 \ ----------------------------------\
1046 BW1 CALL #STOP_R2L
1047     COLON                           \
1048     ECHO                            \
1049     ." type START to start RC5toLCD"
1050     ;
1051 \ ----------------------------------\
1052
1053 \ this routine completes the INIT_HARD of FORTH, with INIT_HARD for this app.
1054 \ ----------------------------------\
1055     HDNCODE INIT_R2L                \ called by START|SYS
1056 \ ----------------------------------\
1057 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
1058 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
1059 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
1060 \                           --       \ID input divider \ 10 = /4
1061 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
1062 \                                 -  \TBCLR TimerB Clear
1063 \                                  - \TBIE
1064 \                                   -\TBIFG
1065 \ ----------------------------------\
1066 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
1067 \                  --                 \CM Capture Mode
1068 \                    --               \CCIS
1069 \                       -             \SCS
1070 \                        --           \CLLD
1071 \                          -          \CAP
1072 \                            ---      \OUTMOD \ 011 = set/reset
1073 \                               -     \CCIE
1074 \                                 -   \CCI
1075 \                                  -  \OUT
1076 \                                   - \COV
1077 \                                    -\CCIFG
1078 \ ----------------------------------\
1079 \ LCD_TIM_CCRx                      \
1080 \ ----------------------------------\
1081 \ LCD_TIM_EX0                       \
1082 \ ----------------------------------\
1083 \ set LCD_TIM_ to make 50kHz PWM    \ for LCD_Vo; works without interrupt
1084 \ ----------------------------------\
1085     MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int, set IFG
1086 \    MOV #0,&RC5_TIM_EX0             \ predivide by 1 in RC5_TIM_EX0 register, reset value
1087 \    MOV #0,&LCD_TIM_EX0             \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
1088     FREQ_KHZ @ 16000 =
1089     [IF]                            \ if 16 MHz
1090         MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
1091         MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
1092     [THEN]
1093     FREQ_KHZ @ 24000 =
1094     [IF]                            \ if 24 MHz
1095         MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
1096         MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
1097     [THEN]
1098         MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
1099 \ ----------------------------------\
1100 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
1101 \ ----------------------------------\
1102     MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
1103     MOV #10,&LCD_TIM_CCRn           \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
1104 \    MOV #12,&LCD_TIM_CCRn           \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
1105 \ ----------------------------------\
1106     BIS.B #LCDVo,&LCDVo_DIR         \
1107     BIS.B #LCDVo,&LCDVo_SEL         \ SEL.2
1108 \ ----------------------------------\
1109     BIS.B #LCD_CMD,&LCD_CMD_DIR     \ lcd_cmd as outputs
1110     BIC.B #LCD_CMD,&LCD_CMD_REN     \ lcd_cmd pullup/down disable
1111 \ ----------------------------------\
1112     BIS.B #LCD_DB,&LCD_DB_DIR       \ as output, wired to DB(4-7) LCD_Data
1113     BIC.B #LCD_DB,&LCD_DB_REN       \ LCD_Data pullup/down disable
1114 \ ----------------------------------\
1115 \ init RC5_Int                      \
1116 \ ----------------------------------\
1117     BIS.B #RC5,&IR_IE               \ enable RC5_Int
1118     BIC.B #RC5,&IR_IFG              \ reset RC5_Int flag
1119 \ ----------------------------------\
1120 \ init WatchDog WDT_TIM_            \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
1121 \ ----------------------------------\
1122 \              %01 0001 0100        \ TAxCTL
1123 \               --                  \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
1124 \                  --               \ ID        divided by 1
1125 \                    --             \ MC        MODE = up to TAxCCRn
1126 \                        -          \ TACLR     clear timer count
1127 \                         -         \ TAIE
1128 \                          -        \ TAIFG
1129 \ ----------------------------------\
1130     MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
1131 \ ----------------------------------\
1132 \                        000        \ TAxEX0
1133 \                        ---        \ TAIDEX    pre divisor
1134 \ ----------------------------------\
1135 \          %0000 0000 0000 0101     \ TAxCCR0
1136     MOV ##3276,&WDT_TIM_CCR0        \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
1137 \ ----------------------------------\
1138 \          %0000 0000 0001 0000     \ TAxCCTL0
1139 \                   -               \ CAP capture/compare mode = compare
1140 \                        -          \ CCIEn
1141 \                             -     \ CCIFGn
1142     MOV #%10000,&WDT_TIM_CCTL0      \ enable compare interrupt, clear CCIFG0
1143 \ ----------------------------------\
1144 \ activate I/O                      \
1145 \ ----------------------------------\
1146     CALL &{RC5TOLCD}                \ run previous INIT_HARD_APP
1147 \ ----------------------------------\
1148 \ RESET events handling             \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
1149 \ ----------------------------------\
1150     CMP #$0E,TOS                    \ SYSRSTIV = SVSHIFG SVSH event ?
1151     0<> IF                          \ if not
1152         CMP #$0A,TOS                \   SYSRSTIV >= violation memory protected areas | USERSYS <0 = DEEP_RESET request ?
1153         U>= ?GOTO BW1               \   if yes execute STOP_R2L then RET to BODY of WARM
1154     THEN                            \
1155 \    CMP #2,TOS                      \   Power_ON event
1156 \    0= ?GOTO BW1                    \   uncomment if you want to loose application in this case...
1157     CMP #4,TOS                      \   SYSRSTIV|USERSYS RST ?
1158     0= ?GOTO BW1                    \   if yes run STOP.
1159 \    CMP #$0E,TOS                    \   SYSRSTIV = SVSHIFG SVSH event ?
1160 \    0= ?GOTO BW1                    \   SVSHIFG SVSH event performs STOP
1161 \ ----------------------------------\
1162     LO2HI                           \
1163 \ ----------------------------------\
1164 \   Init LCD 2x20                   \
1165 \ ----------------------------------\
1166     #1000 20_US                     \ 1- wait 20 ms
1167     %011 TOP_LCD                    \ 2- send DB5=DB4=1
1168     #205 20_US                      \ 3- wait 4,1 ms
1169     %011 TOP_LCD                    \ 4- send again DB5=DB4=1
1170     #5 20_US                        \ 5- wait 0,1 ms
1171     %011 TOP_LCD                    \ 6- send again again DB5=DB4=1
1172     #2 20_US                        \    wait 40 us = LCD cycle
1173     %010 TOP_LCD                    \ 7- send DB5=1 DB4=0
1174     #2 20_US                        \    wait 40 us = LCD cycle
1175     %00101000 LCD_WRF               \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
1176     %1000 LCD_WRF                   \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off.
1177     LCD_CLEAR                       \ 10- "LCD_Clear"
1178     %0110 LCD_WRF                   \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
1179     %1100 LCD_WRF                   \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
1180     LCD_CLEAR                       \ 10- "LCD_Clear"
1181     HI2LO                           \
1182     MOV @RSP+,PC                    \ RET to WARM|START
1183     ENDCODE
1184 \ ----------------------------------\
1185
1186 \ ----------------------------------\
1187     CODE START                      \ this routine replaces INT_HARD_APP default values by these of this application.
1188 \ ----------------------------------\
1189     CMP #WDT_INT,&WDT_TIM_0_VEC     \ value set by START
1190     0= IF                           \
1191         MOV @IP+,PC                 \ does nothing if already initialised
1192     THEN
1193     MOV #STOP_R2L,&{RC5TOLCD}-2     \ execution of {RC5TOLCD} will perform STOP_R2L.
1194     KERNEL_ADDON $3C00 TSTBIT       \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
1195     [IF]
1196        MOV &UART_WARM+2,&{RC5TOLCD} \ save previous INI_APP subroutine
1197        MOV #INIT_R2L,&UART_WARM+2   \ replace it by RC5toLCD INI_APP
1198     [ELSE]
1199        MOV &I2C_WARM+2,&{RC5TOLCD}  \ save previous INI_APP subroutine
1200        MOV #INIT_R2L,&I2C_WARM+2    \ replace it by RC5toLCD INI_APP
1201     [THEN]
1202     MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+2 \ save Vector previous value
1203     MOV #WDT_INT,&WDT_TIM_0_VEC     \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
1204     MOV &IR_VEC,&{RC5TOLCD}+4       \ save Vector previous value
1205     MOV #RC5_INT,&IR_VEC            \ init interrupt vector
1206 \ ----------------------------------\
1207 \   init 20 us count loop           \ see 20_US
1208 \ ----------------------------------\ -- TOS
1209     SUB #6,PSP                      \ -- x x x TOS
1210     MOV TOS,4(PSP)                  \ -- TOS x x TOS
1211     MOV &FREQ_KHZ,2(PSP)            \ -- TOS DVDlo x TOS
1212     MOV #0,0(PSP)                   \ -- TOS DVDlo DVDhi TOS
1213     MOV #200,TOS                    \ -- TOS DVDlo DVDhi DIVlo
1214     CALL #MUSMOD                    \ -- TOS REMlo QUOTlo QUOThi
1215     MOV @PSP,&{RC5TOLCD}+6          \                       set count+2 for 20_US
1216     ADD #4,PSP                      \ -- TOS QUOThi
1217     MOV @PSP+,TOS                   \ -- TOS
1218 \ ----------------------------------\
1219     CALL #INIT_R2L                  \ run new INIT_HARD_APP
1220     LO2HI
1221 \    ['] LCD_HOME IS CR              \ ' CR redirected to LCD_HOME
1222 \    ['] LCD_WRC  IS EMIT            \ ' EMIT redirected to LCD_WrC
1223 \    CR ." I love you"               \ display message on LCD
1224 \    ['] CR >BODY IS CR              \ CR executes its default value
1225 \    ['] EMIT >BODY IS EMIT          \ EMIT executes its defaulte value
1226     ." RC5toLCD is running,"        \
1227     ."  Type STOP to quit."         \ display message on FastForth Terminal
1228     HI2LO
1229     MOV #ABORT,PC                   \ goto FORTH interpreter without WARM message.
1230     ENDCODE                         \
1231 \ ----------------------------------\
1232
1233 RST_SET
1234
1235     MARKER {RC5TOLCD}   \ restore the state before MARKER definition
1236 \                       \ {UARTI2CS}-2 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
1237     8 ALLOT             \ {UARTI2CS}    make room to save previous INI_APP address
1238                         \ {RC5TOLCD}+2  make room to save previous WDT_TIM_0_VEC
1239                         \ {RC5TOLCD}+4  make room to save previous IR_VEC
1240                         \ {RC5TOLCD}+6  make room for 20 us count loop.
1241
1242     [UNDEFINED] TSTBIT
1243     [IF]
1244     CODE TSTBIT     \ addr bit_mask -- true/flase flag
1245     MOV @PSP+,X
1246     AND @X,TOS
1247     MOV @IP+,PC
1248     ENDCODE
1249     [THEN]
1250
1251 \ https://forth-standard.org/standard/core/Equal
1252 \ =      x1 x2 -- flag         test x1=x2
1253     [UNDEFINED] =
1254     [IF]
1255     CODE =
1256     SUB @PSP+,TOS   \ 2
1257     0<> IF          \ 2
1258         AND #0,TOS  \ 1
1259         MOV @IP+,PC \ 4
1260     THEN
1261     XOR #-1,TOS     \ 1 flag Z = 1
1262     MOV @IP+,PC     \ 4
1263     ENDCODE
1264     [THEN]
1265
1266     [UNDEFINED] IF
1267     [IF]     \ define IF and THEN
1268 \ https://forth-standard.org/standard/core/IF
1269 \ IF       -- IFadr    initialize conditional forward branch
1270     CODE IF       \ immediate
1271     SUB #2,PSP              \
1272     MOV TOS,0(PSP)          \
1273     MOV &DP,TOS             \ -- HERE
1274     ADD #4,&DP              \           compile one word, reserve one word
1275     MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
1276     ADD #2,TOS              \ -- HERE+2=IFadr
1277     MOV @IP+,PC
1278     ENDCODE IMMEDIATE
1279
1280 \ https://forth-standard.org/standard/core/THEN
1281 \ THEN     IFadr --                resolve forward branch
1282     CODE THEN               \ immediate
1283     MOV &DP,0(TOS)          \ -- IFadr
1284     MOV @PSP+,TOS           \ --
1285     MOV @IP+,PC
1286     ENDCODE IMMEDIATE
1287     [THEN]
1288
1289 \ https://forth-standard.org/standard/core/ELSE
1290 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
1291     [UNDEFINED] ELSE
1292     [IF]
1293     CODE ELSE     \ immediate
1294     ADD #4,&DP              \ make room to compile two words
1295     MOV &DP,W               \ W=HERE+4
1296     MOV #BRAN,-4(W)
1297     MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
1298     SUB #2,W                \ HERE+2
1299     MOV W,TOS               \ -- ELSEadr
1300     MOV @IP+,PC
1301     ENDCODE IMMEDIATE
1302     [THEN]
1303
1304 \ \ https://forth-standard.org/standard/core/DEFERStore
1305 \ \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
1306 \     [UNDEFINED] IS
1307 \     [IF]     \ define DEFER! and IS
1308 \     CODE DEFER!             \ xt2 xt1 --
1309 \     MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
1310 \     MOV @PSP+,TOS           \ --
1311 \     MOV @IP+,PC
1312 \     ENDCODE
1313 \
1314 \ \ https://forth-standard.org/standard/core/IS
1315 \ \ IS <name>        xt --
1316 \ \ used as is :
1317 \ \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
1318 \ \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
1319 \ \ or in a definition : ... ['] U. IS DISPLAY ...
1320 \ \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
1321 \ \
1322 \ \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
1323 \
1324 \     : IS
1325 \     STATEADR @
1326 \     IF  POSTPONE ['] POSTPONE DEFER!
1327 \     ELSE ' DEFER!
1328 \     THEN
1329 \     ; IMMEDIATE
1330 \     [THEN]
1331
1332 \ https://forth-standard.org/standard/core/CR
1333 \ CR      --               send CR+LF to the output device
1334     [UNDEFINED] CR
1335     [IF]
1336 \ create a primary defered word, i.e. with its default runtime beginning at the >BODY of the definition
1337     CODE CR     \ part I : DEFERed definition of CR
1338     MOV #NEXT_ADR,PC                \ [PFA] = NEXT_ADR
1339     ENDCODE
1340
1341     :NONAME
1342     'CR' EMIT 'LF' EMIT
1343     ; IS CR
1344     [THEN]
1345
1346 \ https://forth-standard.org/standard/core/toBODY
1347 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
1348     [UNDEFINED] >BODY
1349     [IF]
1350     CODE >BODY
1351     ADD #4,TOS
1352     MOV @IP+,PC
1353     ENDCODE
1354     [THEN]
1355
1356     CODE 20_US                      \ n --
1357     BEGIN                           \          J_loop           8000    16000  24000  kHz
1358         MOV &{RC5TOLCD}+6,X         \            3          X = {40      80     120}
1359         SUB #2,X                    \           +1          X = {38      78     118} I_loops + 2 J_loops = {40 80 120} * 4 cycles
1360         BEGIN                       \  I_loop
1361             NOP                     \    1
1362             SUB #1,X                \   +1
1363         0=  UNTIL                   \   +2
1364         NOP                         \           +1
1365         SUB #1,TOS                  \           +1
1366     0= UNTIL                        \           +2
1367     MOV @PSP+,TOS                   \
1368     MOV @RSP+,IP                    \
1369     ENDCODE
1370
1371 \                                   \ if write : %xxxx_WWWW --
1372 \                                   \ if read  : -- %0000_RRRR
1373     CODE TOP_LCD                    \ LCD Sample
1374     BIS.B #LCD_EN,&LCD_CMD_OUT      \ lcd_en 0-->1
1375     BIT.B #LCD_RW,&LCD_CMD_IN       \ lcd_rw test
1376     0= IF                           \ write LCD bits pattern
1377         AND.B #LCD_DB,TOS           \
1378         MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
1379         BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
1380         MOV @PSP+,TOS               \
1381         MOV @IP+,PC
1382     THEN                            \ read LCD bits pattern
1383     SUB #2,PSP
1384     MOV TOS,0(PSP)
1385     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
1386     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
1387     AND.B #LCD_DB,TOS           \
1388     MOV @IP+,PC
1389     ENDCODE
1390
1391     CODE LCD_WRC                \ char --         Write Char
1392     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
1393 BW1 SUB #2,PSP                  \
1394     MOV TOS,0(PSP)              \ -- %HHHH_LLLL %HHHH_LLLL
1395     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
1396     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
1397     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
1398     COLON                       \ high level word starts here
1399     TOP_LCD 2 20_US             \ write high nibble first
1400     TOP_LCD 2 20_US
1401     ;
1402
1403     CODE LCD_WRF                \ func --         Write Fonction
1404     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
1405     GOTO BW1
1406     ENDCODE
1407
1408     : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
1409     : LCD_HOME $02 LCD_WRF 100 20_us ;
1410
1411 \     CODE LCD_ENTRY_SET
1412 \     BIS #$04,TOS
1413 \ BW1 COLON
1414 \     LCD_WrF
1415 \     ;
1416 \
1417 \     CODE LCD_DSP_CTRL
1418 \     BIS#$08,TOS
1419 \     GOTO BW1
1420 \     ENDCODE
1421 \
1422 \     CODE LCD_DSP_SHIFT
1423 \     BIS#$10,TOS
1424 \     GOTO BW1
1425 \     ENDCODE
1426 \
1427 \     CODE LCD_FN_SET
1428 \     BIS#$20,TOS
1429 \     GOTO BW1
1430 \     ENDCODE
1431 \
1432 \     CODE LCD_CGRAM_SET
1433 \     BIS #$40,TOS
1434 \     GOTO BW1
1435 \     ENDCODE
1436 \
1437 \     CODE LCD_GOTO
1438 \     BIS #$80,TOS
1439 \     GOTO BW1
1440 \     ENDCODE
1441 \
1442 \ CODE LCD_RDS                    \ -- status       Read Status
1443 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
1444 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
1445 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
1446 \ COLON                           \ starts a FORTH word
1447 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
1448 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
1449 \ HI2LO                           \ switch from FORTH to assembler
1450 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
1451 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
1452 \     MOV @RSP+,IP                \ restore IP saved by COLON
1453 \     MOV @IP+,PC                 \
1454 \ ENDCODE
1455 \
1456 \ CODE LCD_RDC                    \ -- char         Read Char
1457 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
1458 \     GOTO BW1
1459 \ ENDCODE
1460 \
1461 \
1462 \   ********************************\
1463     HDNCODE WDT_INT                 \ Watchdog interrupt routine, warning : not FORTH executable !
1464 \   ********************************\
1465 \    XOR.B #LED1,&LED1_OUT           \ to visualise WDT
1466     BIT.B #SW2,&SW2_IN              \ test switch S2
1467     0= IF                           \ case of switch S2 pressed
1468         CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
1469         U< IF
1470             ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
1471         THEN
1472     ELSE
1473         BIT.B #SW1,&SW1_IN          \ test switch S1 input
1474         0= IF                       \ case of Switch S1 pressed
1475             CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
1476             U>= IF                  \
1477             SUB #1,&LCD_TIM_CCRn    \ action for switch S1 (P2.6) : -150 mV / decrement
1478             THEN                    \
1479         THEN                        \
1480     THEN                            \
1481     RETI                            \ 5
1482     ENDCODE                         \
1483 \   ********************************\
1484
1485 \   ********************************\
1486     HDNCODE RC5_INT                 \   wake up on Px.RC5 change interrupt
1487 \   ********************************\
1488 \   IR_RC5 driver                   \ IP,S,T,W,X,Y registers are free for use
1489 \   ********************************\
1490 \                                   \ in :  SR(9)=old Toggle bit memory (ADD on)
1491 \                                   \       SMclock = 8|16|24 MHz
1492 \                                   \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
1493 \                                   \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
1494 \                                   \       SR(9)=new Toggle bit memory (ADD on)
1495 \   ********************************\
1496 \   RC5_FirstStartBitHalfCycle:     \
1497 \   ********************************\
1498     MOV #1778,X                     \ RC5_Period in us
1499     MOV #14,W                       \ count of loop
1500     BEGIN                           \
1501 \       ****************************\
1502 \       RC5_HalfCycle               \ <--- loop back ---+ with readjusted RC5_Period
1503 \       ****************************\                   |
1504       MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
1505 \       RC5_Compute_3/4_Period:     \                   |
1506         RRUM    #1,X                \ X=1/2 cycle       |
1507         MOV     X,Y                 \                   ^
1508         RRUM    #1,Y                \ Y=1/4
1509         ADD     X,Y                 \ Y=3/4 cycle
1510         BEGIN                       \
1511             CMP Y,&RC5_TIM_R        \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
1512         U>= UNTIL                   \ 2
1513 \       ****************************\
1514 \       RC5_SampleOnFirstQuarter    \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
1515 \       ****************************\
1516         BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
1517         ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
1518         MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
1519         BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
1520         SUB     #1,W                \ decrement count loop
1521 \                                   \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
1522 \                                   \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1
1523     0<> WHILE                       \ ----> out of loop ----+
1524         ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
1525         BEGIN                       \                       |
1526             MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
1527             CMP Y,X                 \ 1                 ^   |   cycle time out of bound ?
1528             U>= ?GOTO FW1           \                   |   |   quit on truncated RC5 message
1529             BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
1530         0<> UNTIL                   \ 2                 |   |
1531     REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
1532 \   ********************************\                       |
1533 \   RC5_SampleEndOf:                \ <---------------------+
1534 \   ********************************\
1535     BIC #$30,&RC5_TIM_CTL           \   stop timer
1536 \   ********************************\
1537 \   RC5_ComputeNewRC5word           \
1538 \   ********************************\
1539     RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
1540     MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
1541     RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
1542 \   ********************************\
1543 \   RC5_ComputeC6bit                \
1544 \   ********************************\
1545     BIT     #BIT14,T                \ test /C6 bit in T
1546     0= IF   BIS #BIT6,X             \ set C6 bit in X
1547     THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
1548 \   ********************************\
1549 \   RC5_CommandByteIsDone           \
1550 \   ********************************\
1551 \   Only New_RC5_Command ADD_ON     \ use SR(10) bit as toggle bit
1552 \   ********************************\
1553     RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
1554     XOR     @RSP,T                  \ (new XOR old) Toggle bits
1555     BIT     #UF10,T                 \ repeated RC5_command ?
1556     0= ?GOTO FW2                    \ yes, RETI without UF10 change and without action !
1557     XOR #UF10,0(RSP)                \ 5 toggle bit memory
1558 \   ********************************\
1559 \   Display IR_RC5 code             \
1560 \   ********************************\
1561     SUB #6,PSP                      \   -- x x x TOS
1562     MOV TOS,4(PSP)                  \   -- TOS x x TOS
1563     MOV &BASEADR,2(PSP)             \   -- TOS Base x TOS
1564     MOV #$10,&BASEADR               \                               set hexadecimal base
1565     MOV X,0(PSP)                    \   -- TOS Base RC5_code TOS    convert number to ascii low word = RC5 byte
1566     MOV #0,TOS                      \   -- TOS Base RC5_code 0      convert double number to ascii
1567     LO2HI                           \                               switch from assembler to FORTH
1568     LCD_CLEAR                       \                               set LCD cursor at home
1569     <# # #S #36 HOLD #>             \   -- TOS Base adr cnt         32 bits conversion as "$xx"
1570     ['] LCD_WRC IS EMIT             \                               redirect EMIT to LCD
1571     TYPE                            \   -- TOS Base                 display "$xx" on LCD
1572     ['] EMIT >BODY IS EMIT          \                               restore EMIT
1573     HI2LO                           \                               switch from FORTH to assembler
1574     MOV @PSP+,&BASEADR              \   -- TOS                      restore current BASE
1575     MOV @PSP+,TOS                   \   --
1576 FW1 BIC #$30,&RC5_TIM_CTL           \ stop timer (case of truncated RC5 message)
1577 FW2 BIC #%1111_1000,0(RSP)          \ force CPU Active Mode and disable GIE in saved SR
1578     RETI                            \
1579     ENDCODE                         \
1580 \   ********************************\
1581
1582 \ define our STOP_APP
1583 \ ----------------------------------\
1584     HDNCODE STOP_R2L                \ called by STOP|INIT_R2L|{RC5TOLCD}
1585 \ ----------------------------------\
1586     CMP #WDT_INT,&WDT_TIM_0_VEC     \ value set by START
1587     0= IF                           \ only if START is done
1588         BIC.B #RC5,&IR_IE           \ clear I/O RC5_Int
1589         BIC.B #RC5,&IR_IFG          \ clear I/O RC5_Int flag
1590         MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER, clear LCD_TIMER IFG
1591         MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
1592         MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
1593         MOV #{RC5TOLCD},W           \
1594         MOV #RET_ADR,-2(W)          \ clear MARKER_DOES call
1595         KERNEL_ADDON $3C00 TSTBIT   \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
1596         [IF]
1597         MOV @W+,&UART_WARM+2        \ restore previous ini_APP
1598         [ELSE]
1599         MOV @W+,&I2C_WARM+2         \ restore previous ini_APP
1600         [THEN]
1601         MOV @W+,&WDT_TIM_0_VEC      \ restore Vector previous value
1602         MOV @W+,&IR_VEC             \ restore Vector previous value
1603     THEN
1604     MOV @RSP+,PC                    \ RET to STOP|WARM+4|{RC5TOLCD}
1605     ENDCODE
1606 \ ----------------------------------\
1607
1608 \ ----------------------------------\
1609     CODE STOP                       \ also called by INIT_R2L for some events
1610 \ ----------------------------------\
1611 BW1 CALL #STOP_R2L
1612     COLON                           \
1613     ECHO                            \
1614     ." type START to start RC5toLCD"
1615     ;
1616 \ ----------------------------------\
1617
1618 \ this routine completes the INIT_HARD of FORTH, with INIT_HARD for this app.
1619 \ ----------------------------------\
1620     HDNCODE INIT_R2L                \ called by START|SYS
1621 \ ----------------------------------\
1622 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
1623 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
1624 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
1625 \                           --       \ID input divider \ 10 = /4
1626 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
1627 \                                 -  \TBCLR TimerB Clear
1628 \                                  - \TBIE
1629 \                                   -\TBIFG
1630 \ ----------------------------------\
1631 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
1632 \                  --                 \CM Capture Mode
1633 \                    --               \CCIS
1634 \                       -             \SCS
1635 \                        --           \CLLD
1636 \                          -          \CAP
1637 \                            ---      \OUTMOD \ 011 = set/reset
1638 \                               -     \CCIE
1639 \                                 -   \CCI
1640 \                                  -  \OUT
1641 \                                   - \COV
1642 \                                    -\CCIFG
1643 \ ----------------------------------\
1644 \ LCD_TIM_CCRx                      \
1645 \ ----------------------------------\
1646 \ LCD_TIM_EX0                       \
1647 \ ----------------------------------\
1648 \ set LCD_TIM_ to make 50kHz PWM    \ for LCD_Vo; works without interrupt
1649 \ ----------------------------------\
1650     MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int, set IFG
1651 \    MOV #0,&RC5_TIM_EX0             \ predivide by 1 in RC5_TIM_EX0 register, reset value
1652 \    MOV #0,&LCD_TIM_EX0             \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
1653     FREQ_KHZ @ 16000 =
1654     [IF]                            \ if 16 MHz
1655         MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
1656         MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
1657     [THEN]
1658     FREQ_KHZ @ 24000 =
1659     [IF]                            \ if 24 MHz
1660         MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
1661         MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
1662     [THEN]
1663         MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
1664 \ ----------------------------------\
1665 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
1666 \ ----------------------------------\
1667     MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
1668     MOV #10,&LCD_TIM_CCRn           \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
1669 \    MOV #12,&LCD_TIM_CCRn           \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
1670 \ ----------------------------------\
1671     BIS.B #LCDVo,&LCDVo_DIR         \
1672     BIS.B #LCDVo,&LCDVo_SEL         \ SEL.2
1673 \ ----------------------------------\
1674     BIS.B #LCD_CMD,&LCD_CMD_DIR     \ lcd_cmd as outputs
1675     BIC.B #LCD_CMD,&LCD_CMD_REN     \ lcd_cmd pullup/down disable
1676 \ ----------------------------------\
1677     BIS.B #LCD_DB,&LCD_DB_DIR       \ as output, wired to DB(4-7) LCD_Data
1678     BIC.B #LCD_DB,&LCD_DB_REN       \ LCD_Data pullup/down disable
1679 \ ----------------------------------\
1680 \ init RC5_Int                      \
1681 \ ----------------------------------\
1682     BIS.B #RC5,&IR_IE               \ enable RC5_Int
1683     BIC.B #RC5,&IR_IFG              \ reset RC5_Int flag
1684 \ ----------------------------------\
1685 \ init WatchDog WDT_TIM_            \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
1686 \ ----------------------------------\
1687 \              %01 0001 0100        \ TAxCTL
1688 \               --                  \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
1689 \                  --               \ ID        divided by 1
1690 \                    --             \ MC        MODE = up to TAxCCRn
1691 \                        -          \ TACLR     clear timer count
1692 \                         -         \ TAIE
1693 \                          -        \ TAIFG
1694 \ ----------------------------------\
1695     MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
1696 \ ----------------------------------\
1697 \                        000        \ TAxEX0
1698 \                        ---        \ TAIDEX    pre divisor
1699 \ ----------------------------------\
1700 \          %0000 0000 0000 0101     \ TAxCCR0
1701     MOV ##3276,&WDT_TIM_CCR0        \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
1702 \ ----------------------------------\
1703 \          %0000 0000 0001 0000     \ TAxCCTL0
1704 \                   -               \ CAP capture/compare mode = compare
1705 \                        -          \ CCIEn
1706 \                             -     \ CCIFGn
1707     MOV #%10000,&WDT_TIM_CCTL0      \ enable compare interrupt, clear CCIFG0
1708 \ ----------------------------------\
1709 \ activate I/O                      \
1710 \ ----------------------------------\
1711     CALL &{RC5TOLCD}                \ run previous INIT_HARD_APP
1712 \ ----------------------------------\
1713 \ RESET events handling             \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
1714 \ ----------------------------------\
1715     CMP #$0E,TOS                    \ SYSRSTIV = SVSHIFG SVSH event ?
1716     0<> IF                          \ if not
1717         CMP #$0A,TOS                \   SYSRSTIV >= violation memory protected areas | USERSYS <0 = DEEP_RESET request ?
1718         U>= ?GOTO BW1               \   if yes execute STOP_R2L then RET to BODY of WARM
1719     THEN                            \
1720 \    CMP #2,TOS                      \   Power_ON event
1721 \    0= ?GOTO BW1                    \   uncomment if you want to loose application in this case...
1722     CMP #4,TOS                      \   SYSRSTIV|USERSYS RST ?
1723     0= ?GOTO BW1                    \   if yes run STOP.
1724 \    CMP #$0E,TOS                    \   SYSRSTIV = SVSHIFG SVSH event ?
1725 \    0= ?GOTO BW1                    \   SVSHIFG SVSH event performs STOP
1726 \ ----------------------------------\
1727     LO2HI                           \
1728 \ ----------------------------------\
1729 \   Init LCD 2x20                   \
1730 \ ----------------------------------\
1731     #1000 20_US                     \ 1- wait 20 ms
1732     %011 TOP_LCD                    \ 2- send DB5=DB4=1
1733     #205 20_US                      \ 3- wait 4,1 ms
1734     %011 TOP_LCD                    \ 4- send again DB5=DB4=1
1735     #5 20_US                        \ 5- wait 0,1 ms
1736     %011 TOP_LCD                    \ 6- send again again DB5=DB4=1
1737     #2 20_US                        \    wait 40 us = LCD cycle
1738     %010 TOP_LCD                    \ 7- send DB5=1 DB4=0
1739     #2 20_US                        \    wait 40 us = LCD cycle
1740     %00101000 LCD_WRF               \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
1741     %1000 LCD_WRF                   \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off.
1742     LCD_CLEAR                       \ 10- "LCD_Clear"
1743     %0110 LCD_WRF                   \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
1744     %1100 LCD_WRF                   \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
1745     LCD_CLEAR                       \ 10- "LCD_Clear"
1746     HI2LO                           \
1747     MOV @RSP+,PC                    \ RET to WARM|START
1748     ENDCODE
1749 \ ----------------------------------\
1750
1751 \ ----------------------------------\
1752     CODE START                      \ this routine replaces INT_HARD_APP default values by these of this application.
1753 \ ----------------------------------\
1754     CMP #WDT_INT,&WDT_TIM_0_VEC     \ value set by START
1755     0= IF                           \
1756         MOV @IP+,PC                 \ does nothing if already initialised
1757     THEN
1758     MOV #STOP_R2L,&{RC5TOLCD}-2     \ execution of {RC5TOLCD} will perform STOP_R2L.
1759     KERNEL_ADDON $3C00 TSTBIT       \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
1760     [IF]
1761        MOV &UART_WARM+2,&{RC5TOLCD} \ save previous INI_APP subroutine
1762        MOV #INIT_R2L,&UART_WARM+2   \ replace it by RC5toLCD INI_APP
1763     [ELSE]
1764        MOV &I2C_WARM+2,&{RC5TOLCD}  \ save previous INI_APP subroutine
1765        MOV #INIT_R2L,&I2C_WARM+2    \ replace it by RC5toLCD INI_APP
1766     [THEN]
1767     MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+2 \ save Vector previous value
1768     MOV #WDT_INT,&WDT_TIM_0_VEC     \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
1769     MOV &IR_VEC,&{RC5TOLCD}+4       \ save Vector previous value
1770     MOV #RC5_INT,&IR_VEC            \ init interrupt vector
1771 \ ----------------------------------\
1772 \   init 20 us count loop           \ see 20_US
1773 \ ----------------------------------\ -- TOS
1774     SUB #6,PSP                      \ -- x x x TOS
1775     MOV TOS,4(PSP)                  \ -- TOS x x TOS
1776     MOV &FREQ_KHZ,2(PSP)            \ -- TOS DVDlo x TOS
1777     MOV #0,0(PSP)                   \ -- TOS DVDlo DVDhi TOS
1778     MOV #200,TOS                    \ -- TOS DVDlo DVDhi DIVlo
1779     CALL #MUSMOD                    \ -- TOS REMlo QUOTlo QUOThi
1780     MOV @PSP,&{RC5TOLCD}+6          \                       set count+2 for 20_US
1781     ADD #4,PSP                      \ -- TOS QUOThi
1782     MOV @PSP+,TOS                   \ -- TOS
1783 \ ----------------------------------\
1784     CALL #INIT_R2L                  \ run new INIT_HARD_APP
1785     LO2HI
1786 \    ['] LCD_HOME IS CR              \ ' CR redirected to LCD_HOME
1787 \    ['] LCD_WRC  IS EMIT            \ ' EMIT redirected to LCD_WrC
1788 \    CR ." I love you"               \ display message on LCD
1789 \    ['] CR >BODY IS CR              \ CR executes its default value
1790 \    ['] EMIT >BODY IS EMIT          \ EMIT executes its defaulte value
1791     ." RC5toLCD is running,"        \
1792     ."  Type STOP to quit."         \ display message on FastForth Terminal
1793     HI2LO
1794     MOV #ABORT,PC                   \ goto FORTH interpreter without WARM message.
1795     ENDCODE                         \
1796 \ ----------------------------------\
1797
1798 RST_SET
1799
1800     MARKER {RC5TOLCD}   \ restore the state before MARKER definition
1801 \                       \ {UARTI2CS}-2 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
1802     8 ALLOT             \ {UARTI2CS}    make room to save previous INI_APP address
1803                         \ {RC5TOLCD}+2  make room to save previous WDT_TIM_0_VEC
1804                         \ {RC5TOLCD}+4  make room to save previous IR_VEC
1805                         \ {RC5TOLCD}+6  make room for 20 us count loop.
1806
1807     [UNDEFINED] TSTBIT
1808     [IF]
1809     CODE TSTBIT     \ addr bit_mask -- true/flase flag
1810     MOV @PSP+,X
1811     AND @X,TOS
1812     MOV @IP+,PC
1813     ENDCODE
1814     [THEN]
1815
1816 \ https://forth-standard.org/standard/core/Equal
1817 \ =      x1 x2 -- flag         test x1=x2
1818     [UNDEFINED] =
1819     [IF]
1820     CODE =
1821     SUB @PSP+,TOS   \ 2
1822     0<> IF          \ 2
1823         AND #0,TOS  \ 1
1824         MOV @IP+,PC \ 4
1825     THEN
1826     XOR #-1,TOS     \ 1 flag Z = 1
1827     MOV @IP+,PC     \ 4
1828     ENDCODE
1829     [THEN]
1830
1831     [UNDEFINED] IF
1832     [IF]     \ define IF and THEN
1833 \ https://forth-standard.org/standard/core/IF
1834 \ IF       -- IFadr    initialize conditional forward branch
1835     CODE IF       \ immediate
1836     SUB #2,PSP              \
1837     MOV TOS,0(PSP)          \
1838     MOV &DP,TOS             \ -- HERE
1839     ADD #4,&DP              \           compile one word, reserve one word
1840     MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
1841     ADD #2,TOS              \ -- HERE+2=IFadr
1842     MOV @IP+,PC
1843     ENDCODE IMMEDIATE
1844
1845 \ https://forth-standard.org/standard/core/THEN
1846 \ THEN     IFadr --                resolve forward branch
1847     CODE THEN               \ immediate
1848     MOV &DP,0(TOS)          \ -- IFadr
1849     MOV @PSP+,TOS           \ --
1850     MOV @IP+,PC
1851     ENDCODE IMMEDIATE
1852     [THEN]
1853
1854 \ https://forth-standard.org/standard/core/ELSE
1855 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
1856     [UNDEFINED] ELSE
1857     [IF]
1858     CODE ELSE     \ immediate
1859     ADD #4,&DP              \ make room to compile two words
1860     MOV &DP,W               \ W=HERE+4
1861     MOV #BRAN,-4(W)
1862     MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
1863     SUB #2,W                \ HERE+2
1864     MOV W,TOS               \ -- ELSEadr
1865     MOV @IP+,PC
1866     ENDCODE IMMEDIATE
1867     [THEN]
1868
1869 \ \ https://forth-standard.org/standard/core/DEFERStore
1870 \ \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
1871 \     [UNDEFINED] IS
1872 \     [IF]     \ define DEFER! and IS
1873 \     CODE DEFER!             \ xt2 xt1 --
1874 \     MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
1875 \     MOV @PSP+,TOS           \ --
1876 \     MOV @IP+,PC
1877 \     ENDCODE
1878 \
1879 \ \ https://forth-standard.org/standard/core/IS
1880 \ \ IS <name>        xt --
1881 \ \ used as is :
1882 \ \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
1883 \ \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
1884 \ \ or in a definition : ... ['] U. IS DISPLAY ...
1885 \ \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
1886 \ \
1887 \ \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
1888 \
1889 \     : IS
1890 \     STATEADR @
1891 \     IF  POSTPONE ['] POSTPONE DEFER!
1892 \     ELSE ' DEFER!
1893 \     THEN
1894 \     ; IMMEDIATE
1895 \     [THEN]
1896
1897 \ https://forth-standard.org/standard/core/CR
1898 \ CR      --               send CR+LF to the output device
1899     [UNDEFINED] CR
1900     [IF]
1901 \ create a primary defered word, i.e. with its default runtime beginning at the >BODY of the definition
1902     CODE CR     \ part I : DEFERed definition of CR
1903     MOV #NEXT_ADR,PC                \ [PFA] = NEXT_ADR
1904     ENDCODE
1905
1906     :NONAME
1907     'CR' EMIT 'LF' EMIT
1908     ; IS CR
1909     [THEN]
1910
1911 \ https://forth-standard.org/standard/core/toBODY
1912 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
1913     [UNDEFINED] >BODY
1914     [IF]
1915     CODE >BODY
1916     ADD #4,TOS
1917     MOV @IP+,PC
1918     ENDCODE
1919     [THEN]
1920
1921     CODE 20_US                      \ n --
1922     BEGIN                           \          J_loop           8000    16000  24000  kHz
1923         MOV &{RC5TOLCD}+6,X         \            3          X = {40      80     120}
1924         SUB #2,X                    \           +1          X = {38      78     118} I_loops + 2 J_loops = {40 80 120} * 4 cycles
1925         BEGIN                       \  I_loop
1926             NOP                     \    1
1927             SUB #1,X                \   +1
1928         0=  UNTIL                   \   +2
1929         NOP                         \           +1
1930         SUB #1,TOS                  \           +1
1931     0= UNTIL                        \           +2
1932     MOV @PSP+,TOS                   \
1933     MOV @RSP+,IP                    \
1934     ENDCODE
1935
1936 \                                   \ if write : %xxxx_WWWW --
1937 \                                   \ if read  : -- %0000_RRRR
1938     CODE TOP_LCD                    \ LCD Sample
1939     BIS.B #LCD_EN,&LCD_CMD_OUT      \ lcd_en 0-->1
1940     BIT.B #LCD_RW,&LCD_CMD_IN       \ lcd_rw test
1941     0= IF                           \ write LCD bits pattern
1942         AND.B #LCD_DB,TOS           \
1943         MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
1944         BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
1945         MOV @PSP+,TOS               \
1946         MOV @IP+,PC
1947     THEN                            \ read LCD bits pattern
1948     SUB #2,PSP
1949     MOV TOS,0(PSP)
1950     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
1951     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
1952     AND.B #LCD_DB,TOS           \
1953     MOV @IP+,PC
1954     ENDCODE
1955
1956     CODE LCD_WRC                \ char --         Write Char
1957     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
1958 BW1 SUB #2,PSP                  \
1959     MOV TOS,0(PSP)              \ -- %HHHH_LLLL %HHHH_LLLL
1960     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
1961     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
1962     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
1963     COLON                       \ high level word starts here
1964     TOP_LCD 2 20_US             \ write high nibble first
1965     TOP_LCD 2 20_US
1966     ;
1967
1968     CODE LCD_WRF                \ func --         Write Fonction
1969     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
1970     GOTO BW1
1971     ENDCODE
1972
1973     : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
1974     : LCD_HOME $02 LCD_WRF 100 20_us ;
1975
1976 \     CODE LCD_ENTRY_SET
1977 \     BIS #$04,TOS
1978 \ BW1 COLON
1979 \     LCD_WrF
1980 \     ;
1981 \
1982 \     CODE LCD_DSP_CTRL
1983 \     BIS#$08,TOS
1984 \     GOTO BW1
1985 \     ENDCODE
1986 \
1987 \     CODE LCD_DSP_SHIFT
1988 \     BIS#$10,TOS
1989 \     GOTO BW1
1990 \     ENDCODE
1991 \
1992 \     CODE LCD_FN_SET
1993 \     BIS#$20,TOS
1994 \     GOTO BW1
1995 \     ENDCODE
1996 \
1997 \     CODE LCD_CGRAM_SET
1998 \     BIS #$40,TOS
1999 \     GOTO BW1
2000 \     ENDCODE
2001 \
2002 \     CODE LCD_GOTO
2003 \     BIS #$80,TOS
2004 \     GOTO BW1
2005 \     ENDCODE
2006 \
2007 \ CODE LCD_RDS                    \ -- status       Read Status
2008 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
2009 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
2010 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
2011 \ COLON                           \ starts a FORTH word
2012 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
2013 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
2014 \ HI2LO                           \ switch from FORTH to assembler
2015 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
2016 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
2017 \     MOV @RSP+,IP                \ restore IP saved by COLON
2018 \     MOV @IP+,PC                 \
2019 \ ENDCODE
2020 \
2021 \ CODE LCD_RDC                    \ -- char         Read Char
2022 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
2023 \     GOTO BW1
2024 \ ENDCODE
2025 \
2026 \
2027 \   ********************************\
2028     HDNCODE WDT_INT                 \ Watchdog interrupt routine, warning : not FORTH executable !
2029 \   ********************************\
2030 \    XOR.B #LED1,&LED1_OUT           \ to visualise WDT
2031     BIT.B #SW2,&SW2_IN              \ test switch S2
2032     0= IF                           \ case of switch S2 pressed
2033         CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
2034         U< IF
2035             ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
2036         THEN
2037     ELSE
2038         BIT.B #SW1,&SW1_IN          \ test switch S1 input
2039         0= IF                       \ case of Switch S1 pressed
2040             CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
2041             U>= IF                  \
2042             SUB #1,&LCD_TIM_CCRn    \ action for switch S1 (P2.6) : -150 mV / decrement
2043             THEN                    \
2044         THEN                        \
2045     THEN                            \
2046     RETI                            \ 5
2047     ENDCODE                         \
2048 \   ********************************\
2049
2050 \   ********************************\
2051     HDNCODE RC5_INT                 \   wake up on Px.RC5 change interrupt
2052 \   ********************************\
2053 \   IR_RC5 driver                   \ IP,S,T,W,X,Y registers are free for use
2054 \   ********************************\
2055 \                                   \ in :  SR(9)=old Toggle bit memory (ADD on)
2056 \                                   \       SMclock = 8|16|24 MHz
2057 \                                   \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
2058 \                                   \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
2059 \                                   \       SR(9)=new Toggle bit memory (ADD on)
2060 \   ********************************\
2061 \   RC5_FirstStartBitHalfCycle:     \
2062 \   ********************************\
2063     MOV #1778,X                     \ RC5_Period in us
2064     MOV #14,W                       \ count of loop
2065     BEGIN                           \
2066 \       ****************************\
2067 \       RC5_HalfCycle               \ <--- loop back ---+ with readjusted RC5_Period
2068 \       ****************************\                   |
2069       MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
2070 \       RC5_Compute_3/4_Period:     \                   |
2071         RRUM    #1,X                \ X=1/2 cycle       |
2072         MOV     X,Y                 \                   ^
2073         RRUM    #1,Y                \ Y=1/4
2074         ADD     X,Y                 \ Y=3/4 cycle
2075         BEGIN                       \
2076             CMP Y,&RC5_TIM_R        \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
2077         U>= UNTIL                   \ 2
2078 \       ****************************\
2079 \       RC5_SampleOnFirstQuarter    \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
2080 \       ****************************\
2081         BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
2082         ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
2083         MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
2084         BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
2085         SUB     #1,W                \ decrement count loop
2086 \                                   \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
2087 \                                   \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1
2088     0<> WHILE                       \ ----> out of loop ----+
2089         ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
2090         BEGIN                       \                       |
2091             MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
2092             CMP Y,X                 \ 1                 ^   |   cycle time out of bound ?
2093             U>= ?GOTO FW1           \                   |   |   quit on truncated RC5 message
2094             BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
2095         0<> UNTIL                   \ 2                 |   |
2096     REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
2097 \   ********************************\                       |
2098 \   RC5_SampleEndOf:                \ <---------------------+
2099 \   ********************************\
2100     BIC #$30,&RC5_TIM_CTL           \   stop timer
2101 \   ********************************\
2102 \   RC5_ComputeNewRC5word           \
2103 \   ********************************\
2104     RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
2105     MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
2106     RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
2107 \   ********************************\
2108 \   RC5_ComputeC6bit                \
2109 \   ********************************\
2110     BIT     #BIT14,T                \ test /C6 bit in T
2111     0= IF   BIS #BIT6,X             \ set C6 bit in X
2112     THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
2113 \   ********************************\
2114 \   RC5_CommandByteIsDone           \
2115 \   ********************************\
2116 \   Only New_RC5_Command ADD_ON     \ use SR(10) bit as toggle bit
2117 \   ********************************\
2118     RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
2119     XOR     @RSP,T                  \ (new XOR old) Toggle bits
2120     BIT     #UF10,T                 \ repeated RC5_command ?
2121     0= ?GOTO FW2                    \ yes, RETI without UF10 change and without action !
2122     XOR #UF10,0(RSP)                \ 5 toggle bit memory
2123 \   ********************************\
2124 \   Display IR_RC5 code             \
2125 \   ********************************\
2126     SUB #6,PSP                      \   -- x x x TOS
2127     MOV TOS,4(PSP)                  \   -- TOS x x TOS
2128     MOV &BASEADR,2(PSP)             \   -- TOS Base x TOS
2129     MOV #$10,&BASEADR               \                               set hexadecimal base
2130     MOV X,0(PSP)                    \   -- TOS Base RC5_code TOS    convert number to ascii low word = RC5 byte
2131     MOV #0,TOS                      \   -- TOS Base RC5_code 0      convert double number to ascii
2132     LO2HI                           \                               switch from assembler to FORTH
2133     LCD_CLEAR                       \                               set LCD cursor at home
2134     <# # #S #36 HOLD #>             \   -- TOS Base adr cnt         32 bits conversion as "$xx"
2135     ['] LCD_WRC IS EMIT             \                               redirect EMIT to LCD
2136     TYPE                            \   -- TOS Base                 display "$xx" on LCD
2137     ['] EMIT >BODY IS EMIT          \                               restore EMIT
2138     HI2LO                           \                               switch from FORTH to assembler
2139     MOV @PSP+,&BASEADR              \   -- TOS                      restore current BASE
2140     MOV @PSP+,TOS                   \   --
2141 FW1 BIC #$30,&RC5_TIM_CTL           \ stop timer (case of truncated RC5 message)
2142 FW2 BIC #%1111_1000,0(RSP)          \ force CPU Active Mode and disable GIE in saved SR
2143     RETI                            \
2144     ENDCODE                         \
2145 \   ********************************\
2146
2147 \ define our STOP_APP
2148 \ ----------------------------------\
2149     HDNCODE STOP_R2L                \ called by STOP|INIT_R2L|{RC5TOLCD}
2150 \ ----------------------------------\
2151     CMP #WDT_INT,&WDT_TIM_0_VEC     \ value set by START
2152     0= IF                           \ only if START is done
2153         BIC.B #RC5,&IR_IE           \ clear I/O RC5_Int
2154         BIC.B #RC5,&IR_IFG          \ clear I/O RC5_Int flag
2155         MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER, clear LCD_TIMER IFG
2156         MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
2157         MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
2158         MOV #{RC5TOLCD},W           \
2159         MOV #RET_ADR,-2(W)          \ clear MARKER_DOES call
2160         KERNEL_ADDON $3C00 TSTBIT   \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
2161         [IF]
2162         MOV @W+,&UART_WARM+2        \ restore previous ini_APP
2163         [ELSE]
2164         MOV @W+,&I2C_WARM+2         \ restore previous ini_APP
2165         [THEN]
2166         MOV @W+,&WDT_TIM_0_VEC      \ restore Vector previous value
2167         MOV @W+,&IR_VEC             \ restore Vector previous value
2168     THEN
2169     MOV @RSP+,PC                    \ RET to STOP|WARM+4|{RC5TOLCD}
2170     ENDCODE
2171 \ ----------------------------------\
2172
2173 \ ----------------------------------\
2174     CODE STOP                       \ also called by INIT_R2L for some events
2175 \ ----------------------------------\
2176 BW1 CALL #STOP_R2L
2177     COLON                           \
2178     ECHO                            \
2179     ." type START to start RC5toLCD"
2180     ;
2181 \ ----------------------------------\
2182
2183 \ this routine completes the INIT_HARD of FORTH, with INIT_HARD for this app.
2184 \ ----------------------------------\
2185     HDNCODE INIT_R2L                \ called by START|SYS
2186 \ ----------------------------------\
2187 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
2188 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
2189 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
2190 \                           --       \ID input divider \ 10 = /4
2191 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
2192 \                                 -  \TBCLR TimerB Clear
2193 \                                  - \TBIE
2194 \                                   -\TBIFG
2195 \ ----------------------------------\
2196 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
2197 \                  --                 \CM Capture Mode
2198 \                    --               \CCIS
2199 \                       -             \SCS
2200 \                        --           \CLLD
2201 \                          -          \CAP
2202 \                            ---      \OUTMOD \ 011 = set/reset
2203 \                               -     \CCIE
2204 \                                 -   \CCI
2205 \                                  -  \OUT
2206 \                                   - \COV
2207 \                                    -\CCIFG
2208 \ ----------------------------------\
2209 \ LCD_TIM_CCRx                      \
2210 \ ----------------------------------\
2211 \ LCD_TIM_EX0                       \
2212 \ ----------------------------------\
2213 \ set LCD_TIM_ to make 50kHz PWM    \ for LCD_Vo; works without interrupt
2214 \ ----------------------------------\
2215     MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int, set IFG
2216 \    MOV #0,&RC5_TIM_EX0             \ predivide by 1 in RC5_TIM_EX0 register, reset value
2217 \    MOV #0,&LCD_TIM_EX0             \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
2218     FREQ_KHZ @ 16000 =
2219     [IF]                            \ if 16 MHz
2220         MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
2221         MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
2222     [THEN]
2223     FREQ_KHZ @ 24000 =
2224     [IF]                            \ if 24 MHz
2225         MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
2226         MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
2227     [THEN]
2228         MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
2229 \ ----------------------------------\
2230 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
2231 \ ----------------------------------\
2232     MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
2233     MOV #10,&LCD_TIM_CCRn           \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
2234 \    MOV #12,&LCD_TIM_CCRn           \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
2235 \ ----------------------------------\
2236     BIS.B #LCDVo,&LCDVo_DIR         \
2237     BIS.B #LCDVo,&LCDVo_SEL         \ SEL.2
2238 \ ----------------------------------\
2239     BIS.B #LCD_CMD,&LCD_CMD_DIR     \ lcd_cmd as outputs
2240     BIC.B #LCD_CMD,&LCD_CMD_REN     \ lcd_cmd pullup/down disable
2241 \ ----------------------------------\
2242     BIS.B #LCD_DB,&LCD_DB_DIR       \ as output, wired to DB(4-7) LCD_Data
2243     BIC.B #LCD_DB,&LCD_DB_REN       \ LCD_Data pullup/down disable
2244 \ ----------------------------------\
2245 \ init RC5_Int                      \
2246 \ ----------------------------------\
2247     BIS.B #RC5,&IR_IE               \ enable RC5_Int
2248     BIC.B #RC5,&IR_IFG              \ reset RC5_Int flag
2249 \ ----------------------------------\
2250 \ init WatchDog WDT_TIM_            \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
2251 \ ----------------------------------\
2252 \              %01 0001 0100        \ TAxCTL
2253 \               --                  \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
2254 \                  --               \ ID        divided by 1
2255 \                    --             \ MC        MODE = up to TAxCCRn
2256 \                        -          \ TACLR     clear timer count
2257 \                         -         \ TAIE
2258 \                          -        \ TAIFG
2259 \ ----------------------------------\
2260     MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
2261 \ ----------------------------------\
2262 \                        000        \ TAxEX0
2263 \                        ---        \ TAIDEX    pre divisor
2264 \ ----------------------------------\
2265 \          %0000 0000 0000 0101     \ TAxCCR0
2266     MOV ##3276,&WDT_TIM_CCR0        \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
2267 \ ----------------------------------\
2268 \          %0000 0000 0001 0000     \ TAxCCTL0
2269 \                   -               \ CAP capture/compare mode = compare
2270 \                        -          \ CCIEn
2271 \                             -     \ CCIFGn
2272     MOV #%10000,&WDT_TIM_CCTL0      \ enable compare interrupt, clear CCIFG0
2273 \ ----------------------------------\
2274 \ activate I/O                      \
2275 \ ----------------------------------\
2276     CALL &{RC5TOLCD}                \ run previous INIT_HARD_APP
2277 \ ----------------------------------\
2278 \ RESET events handling             \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
2279 \ ----------------------------------\
2280     CMP #$0E,TOS                    \ SYSRSTIV = SVSHIFG SVSH event ?
2281     0<> IF                          \ if not
2282         CMP #$0A,TOS                \   SYSRSTIV >= violation memory protected areas | USERSYS <0 = DEEP_RESET request ?
2283         U>= ?GOTO BW1               \   if yes execute STOP_R2L then RET to BODY of WARM
2284     THEN                            \
2285 \    CMP #2,TOS                      \   Power_ON event
2286 \    0= ?GOTO BW1                    \   uncomment if you want to loose application in this case...
2287     CMP #4,TOS                      \   SYSRSTIV|USERSYS RST ?
2288     0= ?GOTO BW1                    \   if yes run STOP.
2289 \    CMP #$0E,TOS                    \   SYSRSTIV = SVSHIFG SVSH event ?
2290 \    0= ?GOTO BW1                    \   SVSHIFG SVSH event performs STOP
2291 \ ----------------------------------\
2292     LO2HI                           \
2293 \ ----------------------------------\
2294 \   Init LCD 2x20                   \
2295 \ ----------------------------------\
2296     #1000 20_US                     \ 1- wait 20 ms
2297     %011 TOP_LCD                    \ 2- send DB5=DB4=1
2298     #205 20_US                      \ 3- wait 4,1 ms
2299     %011 TOP_LCD                    \ 4- send again DB5=DB4=1
2300     #5 20_US                        \ 5- wait 0,1 ms
2301     %011 TOP_LCD                    \ 6- send again again DB5=DB4=1
2302     #2 20_US                        \    wait 40 us = LCD cycle
2303     %010 TOP_LCD                    \ 7- send DB5=1 DB4=0
2304     #2 20_US                        \    wait 40 us = LCD cycle
2305     %00101000 LCD_WRF               \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
2306     %1000 LCD_WRF                   \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off.
2307     LCD_CLEAR                       \ 10- "LCD_Clear"
2308     %0110 LCD_WRF                   \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
2309     %1100 LCD_WRF                   \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
2310     LCD_CLEAR                       \ 10- "LCD_Clear"
2311     HI2LO                           \
2312     MOV @RSP+,PC                    \ RET to WARM|START
2313     ENDCODE
2314 \ ----------------------------------\
2315
2316 \ ----------------------------------\
2317     CODE START                      \ this routine replaces INT_HARD_APP default values by these of this application.
2318 \ ----------------------------------\
2319     CMP #WDT_INT,&WDT_TIM_0_VEC     \ value set by START
2320     0= IF                           \
2321         MOV @IP+,PC                 \ does nothing if already initialised
2322     THEN
2323     MOV #STOP_R2L,&{RC5TOLCD}-2     \ execution of {RC5TOLCD} will perform STOP_R2L.
2324     KERNEL_ADDON $3C00 TSTBIT       \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
2325     [IF]
2326        MOV &UART_WARM+2,&{RC5TOLCD} \ save previous INI_APP subroutine
2327        MOV #INIT_R2L,&UART_WARM+2   \ replace it by RC5toLCD INI_APP
2328     [ELSE]
2329        MOV &I2C_WARM+2,&{RC5TOLCD}  \ save previous INI_APP subroutine
2330        MOV #INIT_R2L,&I2C_WARM+2    \ replace it by RC5toLCD INI_APP
2331     [THEN]
2332     MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+2 \ save Vector previous value
2333     MOV #WDT_INT,&WDT_TIM_0_VEC     \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
2334     MOV &IR_VEC,&{RC5TOLCD}+4       \ save Vector previous value
2335     MOV #RC5_INT,&IR_VEC            \ init interrupt vector
2336 \ ----------------------------------\
2337 \   init 20 us count loop           \ see 20_US
2338 \ ----------------------------------\ -- TOS
2339     SUB #6,PSP                      \ -- x x x TOS
2340     MOV TOS,4(PSP)                  \ -- TOS x x TOS
2341     MOV &FREQ_KHZ,2(PSP)            \ -- TOS DVDlo x TOS
2342     MOV #0,0(PSP)                   \ -- TOS DVDlo DVDhi TOS
2343     MOV #200,TOS                    \ -- TOS DVDlo DVDhi DIVlo
2344     CALL #MUSMOD                    \ -- TOS REMlo QUOTlo QUOThi
2345     MOV @PSP,&{RC5TOLCD}+6          \                       set count+2 for 20_US
2346     ADD #4,PSP                      \ -- TOS QUOThi
2347     MOV @PSP+,TOS                   \ -- TOS
2348 \ ----------------------------------\
2349     CALL #INIT_R2L                  \ run new INIT_HARD_APP
2350     LO2HI
2351 \    ['] LCD_HOME IS CR              \ ' CR redirected to LCD_HOME
2352 \    ['] LCD_WRC  IS EMIT            \ ' EMIT redirected to LCD_WrC
2353 \    CR ." I love you"               \ display message on LCD
2354 \    ['] CR >BODY IS CR              \ CR executes its default value
2355 \    ['] EMIT >BODY IS EMIT          \ EMIT executes its defaulte value
2356     ." RC5toLCD is running,"        \
2357     ."  Type STOP to quit."         \ display message on FastForth Terminal
2358     HI2LO
2359     MOV #ABORT,PC                   \ goto FORTH interpreter without WARM message.
2360     ENDCODE                         \
2361 \ ----------------------------------\
2362
2363 RST_SET
2364
2365     MARKER {RC5TOLCD}   \ restore the state before MARKER definition
2366 \                       \ {UARTI2CS}-2 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
2367     8 ALLOT             \ {UARTI2CS}    make room to save previous INI_APP address
2368                         \ {RC5TOLCD}+2  make room to save previous WDT_TIM_0_VEC
2369                         \ {RC5TOLCD}+4  make room to save previous IR_VEC
2370                         \ {RC5TOLCD}+6  make room for 20 us count loop.
2371
2372     [UNDEFINED] TSTBIT
2373     [IF]
2374     CODE TSTBIT     \ addr bit_mask -- true/flase flag
2375     MOV @PSP+,X
2376     AND @X,TOS
2377     MOV @IP+,PC
2378     ENDCODE
2379     [THEN]
2380
2381 \ https://forth-standard.org/standard/core/Equal
2382 \ =      x1 x2 -- flag         test x1=x2
2383     [UNDEFINED] =
2384     [IF]
2385     CODE =
2386     SUB @PSP+,TOS   \ 2
2387     0<> IF          \ 2
2388         AND #0,TOS  \ 1
2389         MOV @IP+,PC \ 4
2390     THEN
2391     XOR #-1,TOS     \ 1 flag Z = 1
2392     MOV @IP+,PC     \ 4
2393     ENDCODE
2394     [THEN]
2395
2396     [UNDEFINED] IF
2397     [IF]     \ define IF and THEN
2398 \ https://forth-standard.org/standard/core/IF
2399 \ IF       -- IFadr    initialize conditional forward branch
2400     CODE IF       \ immediate
2401     SUB #2,PSP              \
2402     MOV TOS,0(PSP)          \
2403     MOV &DP,TOS             \ -- HERE
2404     ADD #4,&DP              \           compile one word, reserve one word
2405     MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
2406     ADD #2,TOS              \ -- HERE+2=IFadr
2407     MOV @IP+,PC
2408     ENDCODE IMMEDIATE
2409
2410 \ https://forth-standard.org/standard/core/THEN
2411 \ THEN     IFadr --                resolve forward branch
2412     CODE THEN               \ immediate
2413     MOV &DP,0(TOS)          \ -- IFadr
2414     MOV @PSP+,TOS           \ --
2415     MOV @IP+,PC
2416     ENDCODE IMMEDIATE
2417     [THEN]
2418
2419 \ https://forth-standard.org/standard/core/ELSE
2420 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
2421     [UNDEFINED] ELSE
2422     [IF]
2423     CODE ELSE     \ immediate
2424     ADD #4,&DP              \ make room to compile two words
2425     MOV &DP,W               \ W=HERE+4
2426     MOV #BRAN,-4(W)
2427     MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
2428     SUB #2,W                \ HERE+2
2429     MOV W,TOS               \ -- ELSEadr
2430     MOV @IP+,PC
2431     ENDCODE IMMEDIATE
2432     [THEN]
2433
2434 \ \ https://forth-standard.org/standard/core/DEFERStore
2435 \ \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
2436 \     [UNDEFINED] IS
2437 \     [IF]     \ define DEFER! and IS
2438 \     CODE DEFER!             \ xt2 xt1 --
2439 \     MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
2440 \     MOV @PSP+,TOS           \ --
2441 \     MOV @IP+,PC
2442 \     ENDCODE
2443 \
2444 \ \ https://forth-standard.org/standard/core/IS
2445 \ \ IS <name>        xt --
2446 \ \ used as is :
2447 \ \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
2448 \ \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
2449 \ \ or in a definition : ... ['] U. IS DISPLAY ...
2450 \ \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
2451 \ \
2452 \ \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
2453 \
2454 \     : IS
2455 \     STATEADR @
2456 \     IF  POSTPONE ['] POSTPONE DEFER!
2457 \     ELSE ' DEFER!
2458 \     THEN
2459 \     ; IMMEDIATE
2460 \     [THEN]
2461
2462 \ https://forth-standard.org/standard/core/CR
2463 \ CR      --               send CR+LF to the output device
2464     [UNDEFINED] CR
2465     [IF]
2466 \ create a primary defered word, i.e. with its default runtime beginning at the >BODY of the definition
2467     CODE CR     \ part I : DEFERed definition of CR
2468     MOV #NEXT_ADR,PC                \ [PFA] = NEXT_ADR
2469     ENDCODE
2470
2471     :NONAME
2472     'CR' EMIT 'LF' EMIT
2473     ; IS CR
2474     [THEN]
2475
2476 \ https://forth-standard.org/standard/core/toBODY
2477 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
2478     [UNDEFINED] >BODY
2479     [IF]
2480     CODE >BODY
2481     ADD #4,TOS
2482     MOV @IP+,PC
2483     ENDCODE
2484     [THEN]
2485
2486     CODE 20_US                      \ n --
2487     BEGIN                           \          J_loop           8000    16000  24000  kHz
2488         MOV &{RC5TOLCD}+6,X         \            3          X = {40      80     120}
2489         SUB #2,X                    \           +1          X = {38      78     118} I_loops + 2 J_loops = {40 80 120} * 4 cycles
2490         BEGIN                       \  I_loop
2491             NOP                     \    1
2492             SUB #1,X                \   +1
2493         0=  UNTIL                   \   +2
2494         NOP                         \           +1
2495         SUB #1,TOS                  \           +1
2496     0= UNTIL                        \           +2
2497     MOV @PSP+,TOS                   \
2498     MOV @RSP+,IP                    \
2499     ENDCODE
2500
2501 \                                   \ if write : %xxxx_WWWW --
2502 \                                   \ if read  : -- %0000_RRRR
2503     CODE TOP_LCD                    \ LCD Sample
2504     BIS.B #LCD_EN,&LCD_CMD_OUT      \ lcd_en 0-->1
2505     BIT.B #LCD_RW,&LCD_CMD_IN       \ lcd_rw test
2506     0= IF                           \ write LCD bits pattern
2507         AND.B #LCD_DB,TOS           \
2508         MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
2509         BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
2510         MOV @PSP+,TOS               \
2511         MOV @IP+,PC
2512     THEN                            \ read LCD bits pattern
2513     SUB #2,PSP
2514     MOV TOS,0(PSP)
2515     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
2516     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
2517     AND.B #LCD_DB,TOS           \
2518     MOV @IP+,PC
2519     ENDCODE
2520
2521     CODE LCD_WRC                \ char --         Write Char
2522     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
2523 BW1 SUB #2,PSP                  \
2524     MOV TOS,0(PSP)              \ -- %HHHH_LLLL %HHHH_LLLL
2525     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
2526     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
2527     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
2528     COLON                       \ high level word starts here
2529     TOP_LCD 2 20_US             \ write high nibble first
2530     TOP_LCD 2 20_US
2531     ;
2532
2533     CODE LCD_WRF                \ func --         Write Fonction
2534     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
2535     GOTO BW1
2536     ENDCODE
2537
2538     : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
2539     : LCD_HOME $02 LCD_WRF 100 20_us ;
2540
2541 \     CODE LCD_ENTRY_SET
2542 \     BIS #$04,TOS
2543 \ BW1 COLON
2544 \     LCD_WrF
2545 \     ;
2546 \
2547 \     CODE LCD_DSP_CTRL
2548 \     BIS#$08,TOS
2549 \     GOTO BW1
2550 \     ENDCODE
2551 \
2552 \     CODE LCD_DSP_SHIFT
2553 \     BIS#$10,TOS
2554 \     GOTO BW1
2555 \     ENDCODE
2556 \
2557 \     CODE LCD_FN_SET
2558 \     BIS#$20,TOS
2559 \     GOTO BW1
2560 \     ENDCODE
2561 \
2562 \     CODE LCD_CGRAM_SET
2563 \     BIS #$40,TOS
2564 \     GOTO BW1
2565 \     ENDCODE
2566 \
2567 \     CODE LCD_GOTO
2568 \     BIS #$80,TOS
2569 \     GOTO BW1
2570 \     ENDCODE
2571 \
2572 \ CODE LCD_RDS                    \ -- status       Read Status
2573 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
2574 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
2575 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
2576 \ COLON                           \ starts a FORTH word
2577 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
2578 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
2579 \ HI2LO                           \ switch from FORTH to assembler
2580 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
2581 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
2582 \     MOV @RSP+,IP                \ restore IP saved by COLON
2583 \     MOV @IP+,PC                 \
2584 \ ENDCODE
2585 \
2586 \ CODE LCD_RDC                    \ -- char         Read Char
2587 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
2588 \     GOTO BW1
2589 \ ENDCODE
2590 \
2591 \
2592 \   ********************************\
2593     HDNCODE WDT_INT                 \ Watchdog interrupt routine, warning : not FORTH executable !
2594 \   ********************************\
2595 \    XOR.B #LED1,&LED1_OUT           \ to visualise WDT
2596     BIT.B #SW2,&SW2_IN              \ test switch S2
2597     0= IF                           \ case of switch S2 pressed
2598         CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
2599         U< IF
2600             ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
2601         THEN
2602     ELSE
2603         BIT.B #SW1,&SW1_IN          \ test switch S1 input
2604         0= IF                       \ case of Switch S1 pressed
2605             CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
2606             U>= IF                  \
2607             SUB #1,&LCD_TIM_CCRn    \ action for switch S1 (P2.6) : -150 mV / decrement
2608             THEN                    \
2609         THEN                        \
2610     THEN                            \
2611     RETI                            \ 5
2612     ENDCODE                         \
2613 \   ********************************\
2614
2615 \   ********************************\
2616     HDNCODE RC5_INT                 \   wake up on Px.RC5 change interrupt
2617 \   ********************************\
2618 \   IR_RC5 driver                   \ IP,S,T,W,X,Y registers are free for use
2619 \   ********************************\
2620 \                                   \ in :  SR(9)=old Toggle bit memory (ADD on)
2621 \                                   \       SMclock = 8|16|24 MHz
2622 \                                   \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
2623 \                                   \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
2624 \                                   \       SR(9)=new Toggle bit memory (ADD on)
2625 \   ********************************\
2626 \   RC5_FirstStartBitHalfCycle:     \
2627 \   ********************************\
2628     MOV #1778,X                     \ RC5_Period in us
2629     MOV #14,W                       \ count of loop
2630     BEGIN                           \
2631 \       ****************************\
2632 \       RC5_HalfCycle               \ <--- loop back ---+ with readjusted RC5_Period
2633 \       ****************************\                   |
2634       MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
2635 \       RC5_Compute_3/4_Period:     \                   |
2636         RRUM    #1,X                \ X=1/2 cycle       |
2637         MOV     X,Y                 \                   ^
2638         RRUM    #1,Y                \ Y=1/4
2639         ADD     X,Y                 \ Y=3/4 cycle
2640         BEGIN                       \
2641             CMP Y,&RC5_TIM_R        \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
2642         U>= UNTIL                   \ 2
2643 \       ****************************\
2644 \       RC5_SampleOnFirstQuarter    \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
2645 \       ****************************\
2646         BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
2647         ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
2648         MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
2649         BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
2650         SUB     #1,W                \ decrement count loop
2651 \                                   \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
2652 \                                   \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1
2653     0<> WHILE                       \ ----> out of loop ----+
2654         ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
2655         BEGIN                       \                       |
2656             MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
2657             CMP Y,X                 \ 1                 ^   |   cycle time out of bound ?
2658             U>= ?GOTO FW1           \                   |   |   quit on truncated RC5 message
2659             BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
2660         0<> UNTIL                   \ 2                 |   |
2661     REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
2662 \   ********************************\                       |
2663 \   RC5_SampleEndOf:                \ <---------------------+
2664 \   ********************************\
2665     BIC #$30,&RC5_TIM_CTL           \   stop timer
2666 \   ********************************\
2667 \   RC5_ComputeNewRC5word           \
2668 \   ********************************\
2669     RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
2670     MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
2671     RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
2672 \   ********************************\
2673 \   RC5_ComputeC6bit                \
2674 \   ********************************\
2675     BIT     #BIT14,T                \ test /C6 bit in T
2676     0= IF   BIS #BIT6,X             \ set C6 bit in X
2677     THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
2678 \   ********************************\
2679 \   RC5_CommandByteIsDone           \
2680 \   ********************************\
2681 \   Only New_RC5_Command ADD_ON     \ use SR(10) bit as toggle bit
2682 \   ********************************\
2683     RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
2684     XOR     @RSP,T                  \ (new XOR old) Toggle bits
2685     BIT     #UF10,T                 \ repeated RC5_command ?
2686     0= ?GOTO FW2                    \ yes, RETI without UF10 change and without action !
2687     XOR #UF10,0(RSP)                \ 5 toggle bit memory
2688 \   ********************************\
2689 \   Display IR_RC5 code             \
2690 \   ********************************\
2691     SUB #6,PSP                      \   -- x x x TOS
2692     MOV TOS,4(PSP)                  \   -- TOS x x TOS
2693     MOV &BASEADR,2(PSP)             \   -- TOS Base x TOS
2694     MOV #$10,&BASEADR               \                               set hexadecimal base
2695     MOV X,0(PSP)                    \   -- TOS Base RC5_code TOS    convert number to ascii low word = RC5 byte
2696     MOV #0,TOS                      \   -- TOS Base RC5_code 0      convert double number to ascii
2697     LO2HI                           \                               switch from assembler to FORTH
2698     LCD_CLEAR                       \                               set LCD cursor at home
2699     <# # #S #36 HOLD #>             \   -- TOS Base adr cnt         32 bits conversion as "$xx"
2700     ['] LCD_WRC IS EMIT             \                               redirect EMIT to LCD
2701     TYPE                            \   -- TOS Base                 display "$xx" on LCD
2702     ['] EMIT >BODY IS EMIT          \                               restore EMIT
2703     HI2LO                           \                               switch from FORTH to assembler
2704     MOV @PSP+,&BASEADR              \   -- TOS                      restore current BASE
2705     MOV @PSP+,TOS                   \   --
2706 FW1 BIC #$30,&RC5_TIM_CTL           \ stop timer (case of truncated RC5 message)
2707 FW2 BIC #%1111_1000,0(RSP)          \ force CPU Active Mode and disable GIE in saved SR
2708     RETI                            \
2709     ENDCODE                         \
2710 \   ********************************\
2711
2712 \ define our STOP_APP
2713 \ ----------------------------------\
2714     HDNCODE STOP_R2L                \ called by STOP|INIT_R2L|{RC5TOLCD}
2715 \ ----------------------------------\
2716     CMP #WDT_INT,&WDT_TIM_0_VEC     \ value set by START
2717     0= IF                           \ only if START is done
2718         BIC.B #RC5,&IR_IE           \ clear I/O RC5_Int
2719         BIC.B #RC5,&IR_IFG          \ clear I/O RC5_Int flag
2720         MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER, clear LCD_TIMER IFG
2721         MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
2722         MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
2723         MOV #{RC5TOLCD},W           \
2724         MOV #RET_ADR,-2(W)          \ clear MARKER_DOES call
2725         KERNEL_ADDON $3C00 TSTBIT   \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
2726         [IF]
2727         MOV @W+,&UART_WARM+2        \ restore previous ini_APP
2728         [ELSE]
2729         MOV @W+,&I2C_WARM+2         \ restore previous ini_APP
2730         [THEN]
2731         MOV @W+,&WDT_TIM_0_VEC      \ restore Vector previous value
2732         MOV @W+,&IR_VEC             \ restore Vector previous value
2733     THEN
2734     MOV @RSP+,PC                    \ RET to STOP|WARM+4|{RC5TOLCD}
2735     ENDCODE
2736 \ ----------------------------------\
2737
2738 \ ----------------------------------\
2739     CODE STOP                       \ also called by INIT_R2L for some events
2740 \ ----------------------------------\
2741 BW1 CALL #STOP_R2L
2742     COLON                           \
2743     ECHO                            \
2744     ." type START to start RC5toLCD"
2745     ;
2746 \ ----------------------------------\
2747
2748 \ this routine completes the INIT_HARD of FORTH, with INIT_HARD for this app.
2749 \ ----------------------------------\
2750     HDNCODE INIT_R2L                \ called by START|SYS
2751 \ ----------------------------------\
2752 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
2753 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
2754 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
2755 \                           --       \ID input divider \ 10 = /4
2756 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
2757 \                                 -  \TBCLR TimerB Clear
2758 \                                  - \TBIE
2759 \                                   -\TBIFG
2760 \ ----------------------------------\
2761 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
2762 \                  --                 \CM Capture Mode
2763 \                    --               \CCIS
2764 \                       -             \SCS
2765 \                        --           \CLLD
2766 \                          -          \CAP
2767 \                            ---      \OUTMOD \ 011 = set/reset
2768 \                               -     \CCIE
2769 \                                 -   \CCI
2770 \                                  -  \OUT
2771 \                                   - \COV
2772 \                                    -\CCIFG
2773 \ ----------------------------------\
2774 \ LCD_TIM_CCRx                      \
2775 \ ----------------------------------\
2776 \ LCD_TIM_EX0                       \
2777 \ ----------------------------------\
2778 \ set LCD_TIM_ to make 50kHz PWM    \ for LCD_Vo; works without interrupt
2779 \ ----------------------------------\
2780     MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int, set IFG
2781 \    MOV #0,&RC5_TIM_EX0             \ predivide by 1 in RC5_TIM_EX0 register, reset value
2782 \    MOV #0,&LCD_TIM_EX0             \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
2783     FREQ_KHZ @ 16000 =
2784     [IF]                            \ if 16 MHz
2785         MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
2786         MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
2787     [THEN]
2788     FREQ_KHZ @ 24000 =
2789     [IF]                            \ if 24 MHz
2790         MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
2791         MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
2792     [THEN]
2793         MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
2794 \ ----------------------------------\
2795 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
2796 \ ----------------------------------\
2797     MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
2798     MOV #10,&LCD_TIM_CCRn           \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
2799 \    MOV #12,&LCD_TIM_CCRn           \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
2800 \ ----------------------------------\
2801     BIS.B #LCDVo,&LCDVo_DIR         \
2802     BIS.B #LCDVo,&LCDVo_SEL         \ SEL.2
2803 \ ----------------------------------\
2804     BIS.B #LCD_CMD,&LCD_CMD_DIR     \ lcd_cmd as outputs
2805     BIC.B #LCD_CMD,&LCD_CMD_REN     \ lcd_cmd pullup/down disable
2806 \ ----------------------------------\
2807     BIS.B #LCD_DB,&LCD_DB_DIR       \ as output, wired to DB(4-7) LCD_Data
2808     BIC.B #LCD_DB,&LCD_DB_REN       \ LCD_Data pullup/down disable
2809 \ ----------------------------------\
2810 \ init RC5_Int                      \
2811 \ ----------------------------------\
2812     BIS.B #RC5,&IR_IE               \ enable RC5_Int
2813     BIC.B #RC5,&IR_IFG              \ reset RC5_Int flag
2814 \ ----------------------------------\
2815 \ init WatchDog WDT_TIM_            \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
2816 \ ----------------------------------\
2817 \              %01 0001 0100        \ TAxCTL
2818 \               --                  \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
2819 \                  --               \ ID        divided by 1
2820 \                    --             \ MC        MODE = up to TAxCCRn
2821 \                        -          \ TACLR     clear timer count
2822 \                         -         \ TAIE
2823 \                          -        \ TAIFG
2824 \ ----------------------------------\
2825     MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
2826 \ ----------------------------------\
2827 \                        000        \ TAxEX0
2828 \                        ---        \ TAIDEX    pre divisor
2829 \ ----------------------------------\
2830 \          %0000 0000 0000 0101     \ TAxCCR0
2831     MOV ##3276,&WDT_TIM_CCR0        \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
2832 \ ----------------------------------\
2833 \          %0000 0000 0001 0000     \ TAxCCTL0
2834 \                   -               \ CAP capture/compare mode = compare
2835 \                        -          \ CCIEn
2836 \                             -     \ CCIFGn
2837     MOV #%10000,&WDT_TIM_CCTL0      \ enable compare interrupt, clear CCIFG0
2838 \ ----------------------------------\
2839 \ activate I/O                      \
2840 \ ----------------------------------\
2841     CALL &{RC5TOLCD}                \ run previous INIT_HARD_APP
2842 \ ----------------------------------\
2843 \ RESET events handling             \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
2844 \ ----------------------------------\
2845     CMP #$0E,TOS                    \ SYSRSTIV = SVSHIFG SVSH event ?
2846     0<> IF                          \ if not
2847         CMP #$0A,TOS                \   SYSRSTIV >= violation memory protected areas | USERSYS <0 = DEEP_RESET request ?
2848         U>= ?GOTO BW1               \   if yes execute STOP_R2L then RET to BODY of WARM
2849     THEN                            \
2850 \    CMP #2,TOS                      \   Power_ON event
2851 \    0= ?GOTO BW1                    \   uncomment if you want to loose application in this case...
2852     CMP #4,TOS                      \   SYSRSTIV|USERSYS RST ?
2853     0= ?GOTO BW1                    \   if yes run STOP.
2854 \    CMP #$0E,TOS                    \   SYSRSTIV = SVSHIFG SVSH event ?
2855 \    0= ?GOTO BW1                    \   SVSHIFG SVSH event performs STOP
2856 \ ----------------------------------\
2857     LO2HI                           \
2858 \ ----------------------------------\
2859 \   Init LCD 2x20                   \
2860 \ ----------------------------------\
2861     #1000 20_US                     \ 1- wait 20 ms
2862     %011 TOP_LCD                    \ 2- send DB5=DB4=1
2863     #205 20_US                      \ 3- wait 4,1 ms
2864     %011 TOP_LCD                    \ 4- send again DB5=DB4=1
2865     #5 20_US                        \ 5- wait 0,1 ms
2866     %011 TOP_LCD                    \ 6- send again again DB5=DB4=1
2867     #2 20_US                        \    wait 40 us = LCD cycle
2868     %010 TOP_LCD                    \ 7- send DB5=1 DB4=0
2869     #2 20_US                        \    wait 40 us = LCD cycle
2870     %00101000 LCD_WRF               \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
2871     %1000 LCD_WRF                   \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off.
2872     LCD_CLEAR                       \ 10- "LCD_Clear"
2873     %0110 LCD_WRF                   \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
2874     %1100 LCD_WRF                   \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
2875     LCD_CLEAR                       \ 10- "LCD_Clear"
2876     HI2LO                           \
2877     MOV @RSP+,PC                    \ RET to WARM|START
2878     ENDCODE
2879 \ ----------------------------------\
2880
2881 \ ----------------------------------\
2882     CODE START                      \ this routine replaces INT_HARD_APP default values by these of this application.
2883 \ ----------------------------------\
2884     CMP #WDT_INT,&WDT_TIM_0_VEC     \ value set by START
2885     0= IF                           \
2886         MOV @IP+,PC                 \ does nothing if already initialised
2887     THEN
2888     MOV #STOP_R2L,&{RC5TOLCD}-2     \ execution of {RC5TOLCD} will perform STOP_R2L.
2889     KERNEL_ADDON $3C00 TSTBIT       \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
2890     [IF]
2891        MOV &UART_WARM+2,&{RC5TOLCD} \ save previous INI_APP subroutine
2892        MOV #INIT_R2L,&UART_WARM+2   \ replace it by RC5toLCD INI_APP
2893     [ELSE]
2894        MOV &I2C_WARM+2,&{RC5TOLCD}  \ save previous INI_APP subroutine
2895        MOV #INIT_R2L,&I2C_WARM+2    \ replace it by RC5toLCD INI_APP
2896     [THEN]
2897     MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+2 \ save Vector previous value
2898     MOV #WDT_INT,&WDT_TIM_0_VEC     \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
2899     MOV &IR_VEC,&{RC5TOLCD}+4       \ save Vector previous value
2900     MOV #RC5_INT,&IR_VEC            \ init interrupt vector
2901 \ ----------------------------------\
2902 \   init 20 us count loop           \ see 20_US
2903 \ ----------------------------------\ -- TOS
2904     SUB #6,PSP                      \ -- x x x TOS
2905     MOV TOS,4(PSP)                  \ -- TOS x x TOS
2906     MOV &FREQ_KHZ,2(PSP)            \ -- TOS DVDlo x TOS
2907     MOV #0,0(PSP)                   \ -- TOS DVDlo DVDhi TOS
2908     MOV #200,TOS                    \ -- TOS DVDlo DVDhi DIVlo
2909     CALL #MUSMOD                    \ -- TOS REMlo QUOTlo QUOThi
2910     MOV @PSP,&{RC5TOLCD}+6          \                       set count+2 for 20_US
2911     ADD #4,PSP                      \ -- TOS QUOThi
2912     MOV @PSP+,TOS                   \ -- TOS
2913 \ ----------------------------------\
2914     CALL #INIT_R2L                  \ run new INIT_HARD_APP
2915     LO2HI
2916 \    ['] LCD_HOME IS CR              \ ' CR redirected to LCD_HOME
2917 \    ['] LCD_WRC  IS EMIT            \ ' EMIT redirected to LCD_WrC
2918 \    CR ." I love you"               \ display message on LCD
2919 \    ['] CR >BODY IS CR              \ CR executes its default value
2920 \    ['] EMIT >BODY IS EMIT          \ EMIT executes its defaulte value
2921     ." RC5toLCD is running,"        \
2922     ."  Type STOP to quit."         \ display message on FastForth Terminal
2923     HI2LO
2924     MOV #ABORT,PC                   \ goto FORTH interpreter without WARM message.
2925     ENDCODE                         \
2926 \ ----------------------------------\
2927
2928 RST_SET
2929
2930     MARKER {RC5TOLCD}   \ restore the state before MARKER definition
2931 \                       \ {UARTI2CS}-2 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
2932     8 ALLOT             \ {UARTI2CS}    make room to save previous INI_APP address
2933                         \ {RC5TOLCD}+2  make room to save previous WDT_TIM_0_VEC
2934                         \ {RC5TOLCD}+4  make room to save previous IR_VEC
2935                         \ {RC5TOLCD}+6  make room for 20 us count loop.
2936
2937     [UNDEFINED] TSTBIT
2938     [IF]
2939     CODE TSTBIT     \ addr bit_mask -- true/flase flag
2940     MOV @PSP+,X
2941     AND @X,TOS
2942     MOV @IP+,PC
2943     ENDCODE
2944     [THEN]
2945
2946 \ https://forth-standard.org/standard/core/Equal
2947 \ =      x1 x2 -- flag         test x1=x2
2948     [UNDEFINED] =
2949     [IF]
2950     CODE =
2951     SUB @PSP+,TOS   \ 2
2952     0<> IF          \ 2
2953         AND #0,TOS  \ 1
2954         MOV @IP+,PC \ 4
2955     THEN
2956     XOR #-1,TOS     \ 1 flag Z = 1
2957     MOV @IP+,PC     \ 4
2958     ENDCODE
2959     [THEN]
2960
2961     [UNDEFINED] IF
2962     [IF]     \ define IF and THEN
2963 \ https://forth-standard.org/standard/core/IF
2964 \ IF       -- IFadr    initialize conditional forward branch
2965     CODE IF       \ immediate
2966     SUB #2,PSP              \
2967     MOV TOS,0(PSP)          \
2968     MOV &DP,TOS             \ -- HERE
2969     ADD #4,&DP              \           compile one word, reserve one word
2970     MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
2971     ADD #2,TOS              \ -- HERE+2=IFadr
2972     MOV @IP+,PC
2973     ENDCODE IMMEDIATE
2974
2975 \ https://forth-standard.org/standard/core/THEN
2976 \ THEN     IFadr --                resolve forward branch
2977     CODE THEN               \ immediate
2978     MOV &DP,0(TOS)          \ -- IFadr
2979     MOV @PSP+,TOS           \ --
2980     MOV @IP+,PC
2981     ENDCODE IMMEDIATE
2982     [THEN]
2983
2984 \ https://forth-standard.org/standard/core/ELSE
2985 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
2986     [UNDEFINED] ELSE
2987     [IF]
2988     CODE ELSE     \ immediate
2989     ADD #4,&DP              \ make room to compile two words
2990     MOV &DP,W               \ W=HERE+4
2991     MOV #BRAN,-4(W)
2992     MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
2993     SUB #2,W                \ HERE+2
2994     MOV W,TOS               \ -- ELSEadr
2995     MOV @IP+,PC
2996     ENDCODE IMMEDIATE
2997     [THEN]
2998
2999 \ \ https://forth-standard.org/standard/core/DEFERStore
3000 \ \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
3001 \     [UNDEFINED] IS
3002 \     [IF]     \ define DEFER! and IS
3003 \     CODE DEFER!             \ xt2 xt1 --
3004 \     MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
3005 \     MOV @PSP+,TOS           \ --
3006 \     MOV @IP+,PC
3007 \     ENDCODE
3008 \
3009 \ \ https://forth-standard.org/standard/core/IS
3010 \ \ IS <name>        xt --
3011 \ \ used as is :
3012 \ \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
3013 \ \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
3014 \ \ or in a definition : ... ['] U. IS DISPLAY ...
3015 \ \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
3016 \ \
3017 \ \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
3018 \
3019 \     : IS
3020 \     STATEADR @
3021 \     IF  POSTPONE ['] POSTPONE DEFER!
3022 \     ELSE ' DEFER!
3023 \     THEN
3024 \     ; IMMEDIATE
3025 \     [THEN]
3026
3027 \ https://forth-standard.org/standard/core/CR
3028 \ CR      --               send CR+LF to the output device
3029     [UNDEFINED] CR
3030     [IF]
3031 \ create a primary defered word, i.e. with its default runtime beginning at the >BODY of the definition
3032     CODE CR     \ part I : DEFERed definition of CR
3033     MOV #NEXT_ADR,PC                \ [PFA] = NEXT_ADR
3034     ENDCODE
3035
3036     :NONAME
3037     'CR' EMIT 'LF' EMIT
3038     ; IS CR
3039     [THEN]
3040
3041 \ https://forth-standard.org/standard/core/toBODY
3042 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
3043     [UNDEFINED] >BODY
3044     [IF]
3045     CODE >BODY
3046     ADD #4,TOS
3047     MOV @IP+,PC
3048     ENDCODE
3049     [THEN]
3050
3051     CODE 20_US                      \ n --
3052     BEGIN                           \          J_loop           8000    16000  24000  kHz
3053         MOV &{RC5TOLCD}+6,X         \            3          X = {40      80     120}
3054         SUB #2,X                    \           +1          X = {38      78     118} I_loops + 2 J_loops = {40 80 120} * 4 cycles
3055         BEGIN                       \  I_loop
3056             NOP                     \    1
3057             SUB #1,X                \   +1
3058         0=  UNTIL                   \   +2
3059         NOP                         \           +1
3060         SUB #1,TOS                  \           +1
3061     0= UNTIL                        \           +2
3062     MOV @PSP+,TOS                   \
3063     MOV @RSP+,IP                    \
3064     ENDCODE
3065
3066 \                                   \ if write : %xxxx_WWWW --
3067 \                                   \ if read  : -- %0000_RRRR
3068     CODE TOP_LCD                    \ LCD Sample
3069     BIS.B #LCD_EN,&LCD_CMD_OUT      \ lcd_en 0-->1
3070     BIT.B #LCD_RW,&LCD_CMD_IN       \ lcd_rw test
3071     0= IF                           \ write LCD bits pattern
3072         AND.B #LCD_DB,TOS           \
3073         MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
3074         BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
3075         MOV @PSP+,TOS               \
3076         MOV @IP+,PC
3077     THEN                            \ read LCD bits pattern
3078     SUB #2,PSP
3079     MOV TOS,0(PSP)
3080     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
3081     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
3082     AND.B #LCD_DB,TOS           \
3083     MOV @IP+,PC
3084     ENDCODE
3085
3086     CODE LCD_WRC                \ char --         Write Char
3087     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
3088 BW1 SUB #2,PSP                  \
3089     MOV TOS,0(PSP)              \ -- %HHHH_LLLL %HHHH_LLLL
3090     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
3091     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
3092     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
3093     COLON                       \ high level word starts here
3094     TOP_LCD 2 20_US             \ write high nibble first
3095     TOP_LCD 2 20_US
3096     ;
3097
3098     CODE LCD_WRF                \ func --         Write Fonction
3099     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
3100     GOTO BW1
3101     ENDCODE
3102
3103     : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
3104     : LCD_HOME $02 LCD_WRF 100 20_us ;
3105
3106 \     CODE LCD_ENTRY_SET
3107 \     BIS #$04,TOS
3108 \ BW1 COLON
3109 \     LCD_WrF
3110 \     ;
3111 \
3112 \     CODE LCD_DSP_CTRL
3113 \     BIS#$08,TOS
3114 \     GOTO BW1
3115 \     ENDCODE
3116 \
3117 \     CODE LCD_DSP_SHIFT
3118 \     BIS#$10,TOS
3119 \     GOTO BW1
3120 \     ENDCODE
3121 \
3122 \     CODE LCD_FN_SET
3123 \     BIS#$20,TOS
3124 \     GOTO BW1
3125 \     ENDCODE
3126 \
3127 \     CODE LCD_CGRAM_SET
3128 \     BIS #$40,TOS
3129 \     GOTO BW1
3130 \     ENDCODE
3131 \
3132 \     CODE LCD_GOTO
3133 \     BIS #$80,TOS
3134 \     GOTO BW1
3135 \     ENDCODE
3136 \
3137 \ CODE LCD_RDS                    \ -- status       Read Status
3138 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
3139 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
3140 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
3141 \ COLON                           \ starts a FORTH word
3142 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
3143 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
3144 \ HI2LO                           \ switch from FORTH to assembler
3145 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
3146 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
3147 \     MOV @RSP+,IP                \ restore IP saved by COLON
3148 \     MOV @IP+,PC                 \
3149 \ ENDCODE
3150 \
3151 \ CODE LCD_RDC                    \ -- char         Read Char
3152 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
3153 \     GOTO BW1
3154 \ ENDCODE
3155 \
3156 \
3157 \   ********************************\
3158     HDNCODE WDT_INT                 \ Watchdog interrupt routine, warning : not FORTH executable !
3159 \   ********************************\
3160 \    XOR.B #LED1,&LED1_OUT           \ to visualise WDT
3161     BIT.B #SW2,&SW2_IN              \ test switch S2
3162     0= IF                           \ case of switch S2 pressed
3163         CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
3164         U< IF
3165             ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
3166         THEN
3167     ELSE
3168         BIT.B #SW1,&SW1_IN          \ test switch S1 input
3169         0= IF                       \ case of Switch S1 pressed
3170             CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
3171             U>= IF                  \
3172             SUB #1,&LCD_TIM_CCRn    \ action for switch S1 (P2.6) : -150 mV / decrement
3173             THEN                    \
3174         THEN                        \
3175     THEN                            \
3176     RETI                            \ 5
3177     ENDCODE                         \
3178 \   ********************************\
3179
3180 \   ********************************\
3181     HDNCODE RC5_INT                 \   wake up on Px.RC5 change interrupt
3182 \   ********************************\
3183 \   IR_RC5 driver                   \ IP,S,T,W,X,Y registers are free for use
3184 \   ********************************\
3185 \                                   \ in :  SR(9)=old Toggle bit memory (ADD on)
3186 \                                   \       SMclock = 8|16|24 MHz
3187 \                                   \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
3188 \                                   \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
3189 \                                   \       SR(9)=new Toggle bit memory (ADD on)
3190 \   ********************************\
3191 \   RC5_FirstStartBitHalfCycle:     \
3192 \   ********************************\
3193     MOV #1778,X                     \ RC5_Period in us
3194     MOV #14,W                       \ count of loop
3195     BEGIN                           \
3196 \       ****************************\
3197 \       RC5_HalfCycle               \ <--- loop back ---+ with readjusted RC5_Period
3198 \       ****************************\                   |
3199       MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
3200 \       RC5_Compute_3/4_Period:     \                   |
3201         RRUM    #1,X                \ X=1/2 cycle       |
3202         MOV     X,Y                 \                   ^
3203         RRUM    #1,Y                \ Y=1/4
3204         ADD     X,Y                 \ Y=3/4 cycle
3205         BEGIN                       \
3206             CMP Y,&RC5_TIM_R        \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
3207         U>= UNTIL                   \ 2
3208 \       ****************************\
3209 \       RC5_SampleOnFirstQuarter    \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
3210 \       ****************************\
3211         BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
3212         ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
3213         MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
3214         BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
3215         SUB     #1,W                \ decrement count loop
3216 \                                   \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
3217 \                                   \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1
3218     0<> WHILE                       \ ----> out of loop ----+
3219         ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
3220         BEGIN                       \                       |
3221             MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
3222             CMP Y,X                 \ 1                 ^   |   cycle time out of bound ?
3223             U>= ?GOTO FW1           \                   |   |   quit on truncated RC5 message
3224             BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
3225         0<> UNTIL                   \ 2                 |   |
3226     REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
3227 \   ********************************\                       |
3228 \   RC5_SampleEndOf:                \ <---------------------+
3229 \   ********************************\
3230     BIC #$30,&RC5_TIM_CTL           \   stop timer
3231 \   ********************************\
3232 \   RC5_ComputeNewRC5word           \
3233 \   ********************************\
3234     RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
3235     MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
3236     RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
3237 \   ********************************\
3238 \   RC5_ComputeC6bit                \
3239 \   ********************************\
3240     BIT     #BIT14,T                \ test /C6 bit in T
3241     0= IF   BIS #BIT6,X             \ set C6 bit in X
3242     THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
3243 \   ********************************\
3244 \   RC5_CommandByteIsDone           \
3245 \   ********************************\
3246 \   Only New_RC5_Command ADD_ON     \ use SR(10) bit as toggle bit
3247 \   ********************************\
3248     RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
3249     XOR     @RSP,T                  \ (new XOR old) Toggle bits
3250     BIT     #UF10,T                 \ repeated RC5_command ?
3251     0= ?GOTO FW2                    \ yes, RETI without UF10 change and without action !
3252     XOR #UF10,0(RSP)                \ 5 toggle bit memory
3253 \   ********************************\
3254 \   Display IR_RC5 code             \
3255 \   ********************************\
3256     SUB #6,PSP                      \   -- x x x TOS
3257     MOV TOS,4(PSP)                  \   -- TOS x x TOS
3258     MOV &BASEADR,2(PSP)             \   -- TOS Base x TOS
3259     MOV #$10,&BASEADR               \                               set hexadecimal base
3260     MOV X,0(PSP)                    \   -- TOS Base RC5_code TOS    convert number to ascii low word = RC5 byte
3261     MOV #0,TOS                      \   -- TOS Base RC5_code 0      convert double number to ascii
3262     LO2HI                           \                               switch from assembler to FORTH
3263     LCD_CLEAR                       \                               set LCD cursor at home
3264     <# # #S #36 HOLD #>             \   -- TOS Base adr cnt         32 bits conversion as "$xx"
3265     ['] LCD_WRC IS EMIT             \                               redirect EMIT to LCD
3266     TYPE                            \   -- TOS Base                 display "$xx" on LCD
3267     ['] EMIT >BODY IS EMIT          \                               restore EMIT
3268     HI2LO                           \                               switch from FORTH to assembler
3269     MOV @PSP+,&BASEADR              \   -- TOS                      restore current BASE
3270     MOV @PSP+,TOS                   \   --
3271 FW1 BIC #$30,&RC5_TIM_CTL           \ stop timer (case of truncated RC5 message)
3272 FW2 BIC #%1111_1000,0(RSP)          \ force CPU Active Mode and disable GIE in saved SR
3273     RETI                            \
3274     ENDCODE                         \
3275 \   ********************************\
3276
3277 \ define our STOP_APP
3278 \ ----------------------------------\
3279     HDNCODE STOP_R2L                \ called by STOP|INIT_R2L|{RC5TOLCD}
3280 \ ----------------------------------\
3281     CMP #WDT_INT,&WDT_TIM_0_VEC     \ value set by START
3282     0= IF                           \ only if START is done
3283         BIC.B #RC5,&IR_IE           \ clear I/O RC5_Int
3284         BIC.B #RC5,&IR_IFG          \ clear I/O RC5_Int flag
3285         MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER, clear LCD_TIMER IFG
3286         MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
3287         MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
3288         MOV #{RC5TOLCD},W           \
3289         MOV #RET_ADR,-2(W)          \ clear MARKER_DOES call
3290         KERNEL_ADDON $3C00 TSTBIT   \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
3291         [IF]
3292         MOV @W+,&UART_WARM+2        \ restore previous ini_APP
3293         [ELSE]
3294         MOV @W+,&I2C_WARM+2         \ restore previous ini_APP
3295         [THEN]
3296         MOV @W+,&WDT_TIM_0_VEC      \ restore Vector previous value
3297         MOV @W+,&IR_VEC             \ restore Vector previous value
3298     THEN
3299     MOV @RSP+,PC                    \ RET to STOP|WARM+4|{RC5TOLCD}
3300     ENDCODE
3301 \ ----------------------------------\
3302
3303 \ ----------------------------------\
3304     CODE STOP                       \ also called by INIT_R2L for some events
3305 \ ----------------------------------\
3306 BW1 CALL #STOP_R2L
3307     COLON                           \
3308     ECHO                            \
3309     ." type START to start RC5toLCD"
3310     ;
3311 \ ----------------------------------\
3312
3313 \ this routine completes the INIT_HARD of FORTH, with INIT_HARD for this app.
3314 \ ----------------------------------\
3315     HDNCODE INIT_R2L                \ called by START|SYS
3316 \ ----------------------------------\
3317 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
3318 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
3319 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
3320 \                           --       \ID input divider \ 10 = /4
3321 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
3322 \                                 -  \TBCLR TimerB Clear
3323 \                                  - \TBIE
3324 \                                   -\TBIFG
3325 \ ----------------------------------\
3326 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
3327 \                  --                 \CM Capture Mode
3328 \                    --               \CCIS
3329 \                       -             \SCS
3330 \                        --           \CLLD
3331 \                          -          \CAP
3332 \                            ---      \OUTMOD \ 011 = set/reset
3333 \                               -     \CCIE
3334 \                                 -   \CCI
3335 \                                  -  \OUT
3336 \                                   - \COV
3337 \                                    -\CCIFG
3338 \ ----------------------------------\
3339 \ LCD_TIM_CCRx                      \
3340 \ ----------------------------------\
3341 \ LCD_TIM_EX0                       \
3342 \ ----------------------------------\
3343 \ set LCD_TIM_ to make 50kHz PWM    \ for LCD_Vo; works without interrupt
3344 \ ----------------------------------\
3345     MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int, set IFG
3346 \    MOV #0,&RC5_TIM_EX0             \ predivide by 1 in RC5_TIM_EX0 register, reset value
3347 \    MOV #0,&LCD_TIM_EX0             \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
3348     FREQ_KHZ @ 16000 =
3349     [IF]                            \ if 16 MHz
3350         MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
3351         MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
3352     [THEN]
3353     FREQ_KHZ @ 24000 =
3354     [IF]                            \ if 24 MHz
3355         MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
3356         MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
3357     [THEN]
3358         MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
3359 \ ----------------------------------\
3360 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
3361 \ ----------------------------------\
3362     MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
3363     MOV #10,&LCD_TIM_CCRn           \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
3364 \    MOV #12,&LCD_TIM_CCRn           \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
3365 \ ----------------------------------\
3366     BIS.B #LCDVo,&LCDVo_DIR         \
3367     BIS.B #LCDVo,&LCDVo_SEL         \ SEL.2
3368 \ ----------------------------------\
3369     BIS.B #LCD_CMD,&LCD_CMD_DIR     \ lcd_cmd as outputs
3370     BIC.B #LCD_CMD,&LCD_CMD_REN     \ lcd_cmd pullup/down disable
3371 \ ----------------------------------\
3372     BIS.B #LCD_DB,&LCD_DB_DIR       \ as output, wired to DB(4-7) LCD_Data
3373     BIC.B #LCD_DB,&LCD_DB_REN       \ LCD_Data pullup/down disable
3374 \ ----------------------------------\
3375 \ init RC5_Int                      \
3376 \ ----------------------------------\
3377     BIS.B #RC5,&IR_IE               \ enable RC5_Int
3378     BIC.B #RC5,&IR_IFG              \ reset RC5_Int flag
3379 \ ----------------------------------\
3380 \ init WatchDog WDT_TIM_            \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
3381 \ ----------------------------------\
3382 \              %01 0001 0100        \ TAxCTL
3383 \               --                  \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
3384 \                  --               \ ID        divided by 1
3385 \                    --             \ MC        MODE = up to TAxCCRn
3386 \                        -          \ TACLR     clear timer count
3387 \                         -         \ TAIE
3388 \                          -        \ TAIFG
3389 \ ----------------------------------\
3390     MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
3391 \ ----------------------------------\
3392 \                        000        \ TAxEX0
3393 \                        ---        \ TAIDEX    pre divisor
3394 \ ----------------------------------\
3395 \          %0000 0000 0000 0101     \ TAxCCR0
3396     MOV ##3276,&WDT_TIM_CCR0        \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
3397 \ ----------------------------------\
3398 \          %0000 0000 0001 0000     \ TAxCCTL0
3399 \                   -               \ CAP capture/compare mode = compare
3400 \                        -          \ CCIEn
3401 \                             -     \ CCIFGn
3402     MOV #%10000,&WDT_TIM_CCTL0      \ enable compare interrupt, clear CCIFG0
3403 \ ----------------------------------\
3404 \ activate I/O                      \
3405 \ ----------------------------------\
3406     CALL &{RC5TOLCD}                \ run previous INIT_HARD_APP
3407 \ ----------------------------------\
3408 \ RESET events handling             \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
3409 \ ----------------------------------\
3410     CMP #$0E,TOS                    \ SYSRSTIV = SVSHIFG SVSH event ?
3411     0<> IF                          \ if not
3412         CMP #$0A,TOS                \   SYSRSTIV >= violation memory protected areas | USERSYS <0 = DEEP_RESET request ?
3413         U>= ?GOTO BW1               \   if yes execute STOP_R2L then RET to BODY of WARM
3414     THEN                            \
3415 \    CMP #2,TOS                      \   Power_ON event
3416 \    0= ?GOTO BW1                    \   uncomment if you want to loose application in this case...
3417     CMP #4,TOS                      \   SYSRSTIV|USERSYS RST ?
3418     0= ?GOTO BW1                    \   if yes run STOP.
3419 \    CMP #$0E,TOS                    \   SYSRSTIV = SVSHIFG SVSH event ?
3420 \    0= ?GOTO BW1                    \   SVSHIFG SVSH event performs STOP
3421 \ ----------------------------------\
3422     LO2HI                           \
3423 \ ----------------------------------\
3424 \   Init LCD 2x20                   \
3425 \ ----------------------------------\
3426     #1000 20_US                     \ 1- wait 20 ms
3427     %011 TOP_LCD                    \ 2- send DB5=DB4=1
3428     #205 20_US                      \ 3- wait 4,1 ms
3429     %011 TOP_LCD                    \ 4- send again DB5=DB4=1
3430     #5 20_US                        \ 5- wait 0,1 ms
3431     %011 TOP_LCD                    \ 6- send again again DB5=DB4=1
3432     #2 20_US                        \    wait 40 us = LCD cycle
3433     %010 TOP_LCD                    \ 7- send DB5=1 DB4=0
3434     #2 20_US                        \    wait 40 us = LCD cycle
3435     %00101000 LCD_WRF               \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
3436     %1000 LCD_WRF                   \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off.
3437     LCD_CLEAR                       \ 10- "LCD_Clear"
3438     %0110 LCD_WRF                   \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
3439     %1100 LCD_WRF                   \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
3440     LCD_CLEAR                       \ 10- "LCD_Clear"
3441     HI2LO                           \
3442     MOV @RSP+,PC                    \ RET to WARM|START
3443     ENDCODE
3444 \ ----------------------------------\
3445
3446 \ ----------------------------------\
3447     CODE START                      \ this routine replaces INT_HARD_APP default values by these of this application.
3448 \ ----------------------------------\
3449     CMP #WDT_INT,&WDT_TIM_0_VEC     \ value set by START
3450     0= IF                           \
3451         MOV @IP+,PC                 \ does nothing if already initialised
3452     THEN
3453     MOV #STOP_R2L,&{RC5TOLCD}-2     \ execution of {RC5TOLCD} will perform STOP_R2L.
3454     KERNEL_ADDON $3C00 TSTBIT       \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
3455     [IF]
3456        MOV &UART_WARM+2,&{RC5TOLCD} \ save previous INI_APP subroutine
3457        MOV #INIT_R2L,&UART_WARM+2   \ replace it by RC5toLCD INI_APP
3458     [ELSE]
3459        MOV &I2C_WARM+2,&{RC5TOLCD}  \ save previous INI_APP subroutine
3460        MOV #INIT_R2L,&I2C_WARM+2    \ replace it by RC5toLCD INI_APP
3461     [THEN]
3462     MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+2 \ save Vector previous value
3463     MOV #WDT_INT,&WDT_TIM_0_VEC     \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
3464     MOV &IR_VEC,&{RC5TOLCD}+4       \ save Vector previous value
3465     MOV #RC5_INT,&IR_VEC            \ init interrupt vector
3466 \ ----------------------------------\
3467 \   init 20 us count loop           \ see 20_US
3468 \ ----------------------------------\ -- TOS
3469     SUB #6,PSP                      \ -- x x x TOS
3470     MOV TOS,4(PSP)                  \ -- TOS x x TOS
3471     MOV &FREQ_KHZ,2(PSP)            \ -- TOS DVDlo x TOS
3472     MOV #0,0(PSP)                   \ -- TOS DVDlo DVDhi TOS
3473     MOV #200,TOS                    \ -- TOS DVDlo DVDhi DIVlo
3474     CALL #MUSMOD                    \ -- TOS REMlo QUOTlo QUOThi
3475     MOV @PSP,&{RC5TOLCD}+6          \                       set count+2 for 20_US
3476     ADD #4,PSP                      \ -- TOS QUOThi
3477     MOV @PSP+,TOS                   \ -- TOS
3478 \ ----------------------------------\
3479     CALL #INIT_R2L                  \ run new INIT_HARD_APP
3480     LO2HI
3481 \    ['] LCD_HOME IS CR              \ ' CR redirected to LCD_HOME
3482 \    ['] LCD_WRC  IS EMIT            \ ' EMIT redirected to LCD_WrC
3483 \    CR ." I love you"               \ display message on LCD
3484 \    ['] CR >BODY IS CR              \ CR executes its default value
3485 \    ['] EMIT >BODY IS EMIT          \ EMIT executes its defaulte value
3486     ." RC5toLCD is running,"        \
3487     ."  Type STOP to quit."         \ display message on FastForth Terminal
3488     HI2LO
3489     MOV #ABORT,PC                   \ goto FORTH interpreter without WARM message.
3490     ENDCODE                         \
3491 \ ----------------------------------\
3492
3493 RST_SET
3494
3495     MARKER {RC5TOLCD}   \ restore the state before MARKER definition
3496 \                       \ {UARTI2CS}-2 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
3497     8 ALLOT             \ {UARTI2CS}    make room to save previous INI_APP address
3498                         \ {RC5TOLCD}+2  make room to save previous WDT_TIM_0_VEC
3499                         \ {RC5TOLCD}+4  make room to save previous IR_VEC
3500                         \ {RC5TOLCD}+6  make room for 20 us count loop.
3501
3502     [UNDEFINED] TSTBIT
3503     [IF]
3504     CODE TSTBIT     \ addr bit_mask -- true/flase flag
3505     MOV @PSP+,X
3506     AND @X,TOS
3507     MOV @IP+,PC
3508     ENDCODE
3509     [THEN]
3510
3511 \ https://forth-standard.org/standard/core/Equal
3512 \ =      x1 x2 -- flag         test x1=x2
3513     [UNDEFINED] =
3514     [IF]
3515     CODE =
3516     SUB @PSP+,TOS   \ 2
3517     0<> IF          \ 2
3518         AND #0,TOS  \ 1
3519         MOV @IP+,PC \ 4
3520     THEN
3521     XOR #-1,TOS     \ 1 flag Z = 1
3522     MOV @IP+,PC     \ 4
3523     ENDCODE
3524     [THEN]
3525
3526     [UNDEFINED] IF
3527     [IF]     \ define IF and THEN
3528 \ https://forth-standard.org/standard/core/IF
3529 \ IF       -- IFadr    initialize conditional forward branch
3530     CODE IF       \ immediate
3531     SUB #2,PSP              \
3532     MOV TOS,0(PSP)          \
3533     MOV &DP,TOS             \ -- HERE
3534     ADD #4,&DP              \           compile one word, reserve one word
3535     MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
3536     ADD #2,TOS              \ -- HERE+2=IFadr
3537     MOV @IP+,PC
3538     ENDCODE IMMEDIATE
3539
3540 \ https://forth-standard.org/standard/core/THEN
3541 \ THEN     IFadr --                resolve forward branch
3542     CODE THEN               \ immediate
3543     MOV &DP,0(TOS)          \ -- IFadr
3544     MOV @PSP+,TOS           \ --
3545     MOV @IP+,PC
3546     ENDCODE IMMEDIATE
3547     [THEN]
3548
3549 \ https://forth-standard.org/standard/core/ELSE
3550 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
3551     [UNDEFINED] ELSE
3552     [IF]
3553     CODE ELSE     \ immediate
3554     ADD #4,&DP              \ make room to compile two words
3555     MOV &DP,W               \ W=HERE+4
3556     MOV #BRAN,-4(W)
3557     MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
3558     SUB #2,W                \ HERE+2
3559     MOV W,TOS               \ -- ELSEadr
3560     MOV @IP+,PC
3561     ENDCODE IMMEDIATE
3562     [THEN]
3563
3564 \ \ https://forth-standard.org/standard/core/DEFERStore
3565 \ \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
3566 \     [UNDEFINED] IS
3567 \     [IF]     \ define DEFER! and IS
3568 \     CODE DEFER!             \ xt2 xt1 --
3569 \     MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
3570 \     MOV @PSP+,TOS           \ --
3571 \     MOV @IP+,PC
3572 \     ENDCODE
3573 \
3574 \ \ https://forth-standard.org/standard/core/IS
3575 \ \ IS <name>        xt --
3576 \ \ used as is :
3577 \ \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
3578 \ \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
3579 \ \ or in a definition : ... ['] U. IS DISPLAY ...
3580 \ \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
3581 \ \
3582 \ \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
3583 \
3584 \     : IS
3585 \     STATEADR @
3586 \     IF  POSTPONE ['] POSTPONE DEFER!
3587 \     ELSE ' DEFER!
3588 \     THEN
3589 \     ; IMMEDIATE
3590 \     [THEN]
3591
3592 \ https://forth-standard.org/standard/core/CR
3593 \ CR      --               send CR+LF to the output device
3594     [UNDEFINED] CR
3595     [IF]
3596 \ create a primary defered word, i.e. with its default runtime beginning at the >BODY of the definition
3597     CODE CR     \ part I : DEFERed definition of CR
3598     MOV #NEXT_ADR,PC                \ [PFA] = NEXT_ADR
3599     ENDCODE
3600
3601     :NONAME
3602     'CR' EMIT 'LF' EMIT
3603     ; IS CR
3604     [THEN]
3605
3606 \ https://forth-standard.org/standard/core/toBODY
3607 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
3608     [UNDEFINED] >BODY
3609     [IF]
3610     CODE >BODY
3611     ADD #4,TOS
3612     MOV @IP+,PC
3613     ENDCODE
3614     [THEN]
3615
3616     CODE 20_US                      \ n --
3617     BEGIN                           \          J_loop           8000    16000  24000  kHz
3618         MOV &{RC5TOLCD}+6,X         \            3          X = {40      80     120}
3619         SUB #2,X                    \           +1          X = {38      78     118} I_loops + 2 J_loops = {40 80 120} * 4 cycles
3620         BEGIN                       \  I_loop
3621             NOP                     \    1
3622             SUB #1,X                \   +1
3623         0=  UNTIL                   \   +2
3624         NOP                         \           +1
3625         SUB #1,TOS                  \           +1
3626     0= UNTIL                        \           +2
3627     MOV @PSP+,TOS                   \
3628     MOV @RSP+,IP                    \
3629     ENDCODE
3630
3631 \                                   \ if write : %xxxx_WWWW --
3632 \                                   \ if read  : -- %0000_RRRR
3633     CODE TOP_LCD                    \ LCD Sample
3634     BIS.B #LCD_EN,&LCD_CMD_OUT      \ lcd_en 0-->1
3635     BIT.B #LCD_RW,&LCD_CMD_IN       \ lcd_rw test
3636     0= IF                           \ write LCD bits pattern
3637         AND.B #LCD_DB,TOS           \
3638         MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
3639         BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
3640         MOV @PSP+,TOS               \
3641         MOV @IP+,PC
3642     THEN                            \ read LCD bits pattern
3643     SUB #2,PSP
3644     MOV TOS,0(PSP)
3645     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
3646     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
3647     AND.B #LCD_DB,TOS           \
3648     MOV @IP+,PC
3649     ENDCODE
3650
3651     CODE LCD_WRC                \ char --         Write Char
3652     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
3653 BW1 SUB #2,PSP                  \
3654     MOV TOS,0(PSP)              \ -- %HHHH_LLLL %HHHH_LLLL
3655     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
3656     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
3657     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
3658     COLON                       \ high level word starts here
3659     TOP_LCD 2 20_US             \ write high nibble first
3660     TOP_LCD 2 20_US
3661     ;
3662
3663     CODE LCD_WRF                \ func --         Write Fonction
3664     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
3665     GOTO BW1
3666     ENDCODE
3667
3668     : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
3669     : LCD_HOME $02 LCD_WRF 100 20_us ;
3670
3671 \     CODE LCD_ENTRY_SET
3672 \     BIS #$04,TOS
3673 \ BW1 COLON
3674 \     LCD_WrF
3675 \     ;
3676 \
3677 \     CODE LCD_DSP_CTRL
3678 \     BIS#$08,TOS
3679 \     GOTO BW1
3680 \     ENDCODE
3681 \
3682 \     CODE LCD_DSP_SHIFT
3683 \     BIS#$10,TOS
3684 \     GOTO BW1
3685 \     ENDCODE
3686 \
3687 \     CODE LCD_FN_SET
3688 \     BIS#$20,TOS
3689 \     GOTO BW1
3690 \     ENDCODE
3691 \
3692 \     CODE LCD_CGRAM_SET
3693 \     BIS #$40,TOS
3694 \     GOTO BW1
3695 \     ENDCODE
3696 \
3697 \     CODE LCD_GOTO
3698 \     BIS #$80,TOS
3699 \     GOTO BW1
3700 \     ENDCODE
3701 \
3702 \ CODE LCD_RDS                    \ -- status       Read Status
3703 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
3704 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
3705 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
3706 \ COLON                           \ starts a FORTH word
3707 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
3708 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
3709 \ HI2LO                           \ switch from FORTH to assembler
3710 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
3711 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
3712 \     MOV @RSP+,IP                \ restore IP saved by COLON
3713 \     MOV @IP+,PC                 \
3714 \ ENDCODE
3715 \
3716 \ CODE LCD_RDC                    \ -- char         Read Char
3717 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
3718 \     GOTO BW1
3719 \ ENDCODE
3720 \
3721 \
3722 \   ********************************\
3723     HDNCODE WDT_INT                 \ Watchdog interrupt routine, warning : not FORTH executable !
3724 \   ********************************\
3725 \    XOR.B #LED1,&LED1_OUT           \ to visualise WDT
3726     BIT.B #SW2,&SW2_IN              \ test switch S2
3727     0= IF                           \ case of switch S2 pressed
3728         CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
3729         U< IF
3730             ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
3731         THEN
3732     ELSE
3733         BIT.B #SW1,&SW1_IN          \ test switch S1 input
3734         0= IF                       \ case of Switch S1 pressed
3735             CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
3736             U>= IF                  \
3737             SUB #1,&LCD_TIM_CCRn    \ action for switch S1 (P2.6) : -150 mV / decrement
3738             THEN                    \
3739         THEN                        \
3740     THEN                            \
3741     RETI                            \ 5
3742     ENDCODE                         \
3743 \   ********************************\
3744
3745 \   ********************************\
3746     HDNCODE RC5_INT                 \   wake up on Px.RC5 change interrupt
3747 \   ********************************\
3748 \   IR_RC5 driver                   \ IP,S,T,W,X,Y registers are free for use
3749 \   ********************************\
3750 \                                   \ in :  SR(9)=old Toggle bit memory (ADD on)
3751 \                                   \       SMclock = 8|16|24 MHz
3752 \                                   \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
3753 \                                   \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
3754 \                                   \       SR(9)=new Toggle bit memory (ADD on)
3755 \   ********************************\
3756 \   RC5_FirstStartBitHalfCycle:     \
3757 \   ********************************\
3758     MOV #1778,X                     \ RC5_Period in us
3759     MOV #14,W                       \ count of loop
3760     BEGIN                           \
3761 \       ****************************\
3762 \       RC5_HalfCycle               \ <--- loop back ---+ with readjusted RC5_Period
3763 \       ****************************\                   |
3764       MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
3765 \       RC5_Compute_3/4_Period:     \                   |
3766         RRUM    #1,X                \ X=1/2 cycle       |
3767         MOV     X,Y                 \                   ^
3768         RRUM    #1,Y                \ Y=1/4
3769         ADD     X,Y                 \ Y=3/4 cycle
3770         BEGIN                       \
3771             CMP Y,&RC5_TIM_R        \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
3772         U>= UNTIL                   \ 2
3773 \       ****************************\
3774 \       RC5_SampleOnFirstQuarter    \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
3775 \       ****************************\
3776         BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
3777         ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
3778         MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
3779         BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
3780         SUB     #1,W                \ decrement count loop
3781 \                                   \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
3782 \                                   \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1
3783     0<> WHILE                       \ ----> out of loop ----+
3784         ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
3785         BEGIN                       \                       |
3786             MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
3787             CMP Y,X                 \ 1                 ^   |   cycle time out of bound ?
3788             U>= ?GOTO FW1           \                   |   |   quit on truncated RC5 message
3789             BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
3790         0<> UNTIL                   \ 2                 |   |
3791     REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
3792 \   ********************************\                       |
3793 \   RC5_SampleEndOf:                \ <---------------------+
3794 \   ********************************\
3795     BIC #$30,&RC5_TIM_CTL           \   stop timer
3796 \   ********************************\
3797 \   RC5_ComputeNewRC5word           \
3798 \   ********************************\
3799     RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
3800     MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
3801     RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
3802 \   ********************************\
3803 \   RC5_ComputeC6bit                \
3804 \   ********************************\
3805     BIT     #BIT14,T                \ test /C6 bit in T
3806     0= IF   BIS #BIT6,X             \ set C6 bit in X
3807     THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
3808 \   ********************************\
3809 \   RC5_CommandByteIsDone           \
3810 \   ********************************\
3811 \   Only New_RC5_Command ADD_ON     \ use SR(10) bit as toggle bit
3812 \   ********************************\
3813     RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
3814     XOR     @RSP,T                  \ (new XOR old) Toggle bits
3815     BIT     #UF10,T                 \ repeated RC5_command ?
3816     0= ?GOTO FW2                    \ yes, RETI without UF10 change and without action !
3817     XOR #UF10,0(RSP)                \ 5 toggle bit memory
3818 \   ********************************\
3819 \   Display IR_RC5 code             \
3820 \   ********************************\
3821     SUB #6,PSP                      \   -- x x x TOS
3822     MOV TOS,4(PSP)                  \   -- TOS x x TOS
3823     MOV &BASEADR,2(PSP)             \   -- TOS Base x TOS
3824     MOV #$10,&BASEADR               \                               set hexadecimal base
3825     MOV X,0(PSP)                    \   -- TOS Base RC5_code TOS    convert number to ascii low word = RC5 byte
3826     MOV #0,TOS                      \   -- TOS Base RC5_code 0      convert double number to ascii
3827     LO2HI                           \                               switch from assembler to FORTH
3828     LCD_CLEAR                       \                               set LCD cursor at home
3829     <# # #S #36 HOLD #>             \   -- TOS Base adr cnt         32 bits conversion as "$xx"
3830     ['] LCD_WRC IS EMIT             \                               redirect EMIT to LCD
3831     TYPE                            \   -- TOS Base                 display "$xx" on LCD
3832     ['] EMIT >BODY IS EMIT          \                               restore EMIT
3833     HI2LO                           \                               switch from FORTH to assembler
3834     MOV @PSP+,&BASEADR              \   -- TOS                      restore current BASE
3835     MOV @PSP+,TOS                   \   --
3836 FW1 BIC #$30,&RC5_TIM_CTL           \ stop timer (case of truncated RC5 message)
3837 FW2 BIC #%1111_1000,0(RSP)          \ force CPU Active Mode and disable GIE in saved SR
3838     RETI                            \
3839     ENDCODE                         \
3840 \   ********************************\
3841
3842 \ define our STOP_APP
3843 \ ----------------------------------\
3844     HDNCODE STOP_R2L                \ called by STOP|INIT_R2L|{RC5TOLCD}
3845 \ ----------------------------------\
3846     CMP #WDT_INT,&WDT_TIM_0_VEC     \ value set by START
3847     0= IF                           \ only if START is done
3848         BIC.B #RC5,&IR_IE           \ clear I/O RC5_Int
3849         BIC.B #RC5,&IR_IFG          \ clear I/O RC5_Int flag
3850         MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER, clear LCD_TIMER IFG
3851         MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
3852         MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
3853         MOV #{RC5TOLCD},W           \
3854         MOV #RET_ADR,-2(W)          \ clear MARKER_DOES call
3855         KERNEL_ADDON $3C00 TSTBIT   \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
3856         [IF]
3857         MOV @W+,&UART_WARM+2        \ restore previous ini_APP
3858         [ELSE]
3859         MOV @W+,&I2C_WARM+2         \ restore previous ini_APP
3860         [THEN]
3861         MOV @W+,&WDT_TIM_0_VEC      \ restore Vector previous value
3862         MOV @W+,&IR_VEC             \ restore Vector previous value
3863     THEN
3864     MOV @RSP+,PC                    \ RET to STOP|WARM+4|{RC5TOLCD}
3865     ENDCODE
3866 \ ----------------------------------\
3867
3868 \ ----------------------------------\
3869     CODE STOP                       \ also called by INIT_R2L for some events
3870 \ ----------------------------------\
3871 BW1 CALL #STOP_R2L
3872     COLON                           \
3873     ECHO                            \
3874     ." type START to start RC5toLCD"
3875     ;
3876 \ ----------------------------------\
3877
3878 \ this routine completes the INIT_HARD of FORTH, with INIT_HARD for this app.
3879 \ ----------------------------------\
3880     HDNCODE INIT_R2L                \ called by START|SYS
3881 \ ----------------------------------\
3882 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
3883 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
3884 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
3885 \                           --       \ID input divider \ 10 = /4
3886 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
3887 \                                 -  \TBCLR TimerB Clear
3888 \                                  - \TBIE
3889 \                                   -\TBIFG
3890 \ ----------------------------------\
3891 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
3892 \                  --                 \CM Capture Mode
3893 \                    --               \CCIS
3894 \                       -             \SCS
3895 \                        --           \CLLD
3896 \                          -          \CAP
3897 \                            ---      \OUTMOD \ 011 = set/reset
3898 \                               -     \CCIE
3899 \                                 -   \CCI
3900 \                                  -  \OUT
3901 \                                   - \COV
3902 \                                    -\CCIFG
3903 \ ----------------------------------\
3904 \ LCD_TIM_CCRx                      \
3905 \ ----------------------------------\
3906 \ LCD_TIM_EX0                       \
3907 \ ----------------------------------\
3908 \ set LCD_TIM_ to make 50kHz PWM    \ for LCD_Vo; works without interrupt
3909 \ ----------------------------------\
3910     MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int, set IFG
3911 \    MOV #0,&RC5_TIM_EX0             \ predivide by 1 in RC5_TIM_EX0 register, reset value
3912 \    MOV #0,&LCD_TIM_EX0             \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
3913     FREQ_KHZ @ 16000 =
3914     [IF]                            \ if 16 MHz
3915         MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
3916         MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
3917     [THEN]
3918     FREQ_KHZ @ 24000 =
3919     [IF]                            \ if 24 MHz
3920         MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
3921         MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
3922     [THEN]
3923         MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
3924 \ ----------------------------------\
3925 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
3926 \ ----------------------------------\
3927     MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
3928     MOV #10,&LCD_TIM_CCRn           \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
3929 \    MOV #12,&LCD_TIM_CCRn           \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
3930 \ ----------------------------------\
3931     BIS.B #LCDVo,&LCDVo_DIR         \
3932     BIS.B #LCDVo,&LCDVo_SEL         \ SEL.2
3933 \ ----------------------------------\
3934     BIS.B #LCD_CMD,&LCD_CMD_DIR     \ lcd_cmd as outputs
3935     BIC.B #LCD_CMD,&LCD_CMD_REN     \ lcd_cmd pullup/down disable
3936 \ ----------------------------------\
3937     BIS.B #LCD_DB,&LCD_DB_DIR       \ as output, wired to DB(4-7) LCD_Data
3938     BIC.B #LCD_DB,&LCD_DB_REN       \ LCD_Data pullup/down disable
3939 \ ----------------------------------\
3940 \ init RC5_Int                      \
3941 \ ----------------------------------\
3942     BIS.B #RC5,&IR_IE               \ enable RC5_Int
3943     BIC.B #RC5,&IR_IFG              \ reset RC5_Int flag
3944 \ ----------------------------------\
3945 \ init WatchDog WDT_TIM_            \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
3946 \ ----------------------------------\
3947 \              %01 0001 0100        \ TAxCTL
3948 \               --                  \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
3949 \                  --               \ ID        divided by 1
3950 \                    --             \ MC        MODE = up to TAxCCRn
3951 \                        -          \ TACLR     clear timer count
3952 \                         -         \ TAIE
3953 \                          -        \ TAIFG
3954 \ ----------------------------------\
3955     MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
3956 \ ----------------------------------\
3957 \                        000        \ TAxEX0
3958 \                        ---        \ TAIDEX    pre divisor
3959 \ ----------------------------------\
3960 \          %0000 0000 0000 0101     \ TAxCCR0
3961     MOV ##3276,&WDT_TIM_CCR0        \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
3962 \ ----------------------------------\
3963 \          %0000 0000 0001 0000     \ TAxCCTL0
3964 \                   -               \ CAP capture/compare mode = compare
3965 \                        -          \ CCIEn
3966 \                             -     \ CCIFGn
3967     MOV #%10000,&WDT_TIM_CCTL0      \ enable compare interrupt, clear CCIFG0
3968 \ ----------------------------------\
3969 \ activate I/O                      \
3970 \ ----------------------------------\
3971     CALL &{RC5TOLCD}                \ run previous INIT_HARD_APP
3972 \ ----------------------------------\
3973 \ RESET events handling             \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
3974 \ ----------------------------------\
3975     CMP #$0E,TOS                    \ SYSRSTIV = SVSHIFG SVSH event ?
3976     0<> IF                          \ if not
3977         CMP #$0A,TOS                \   SYSRSTIV >= violation memory protected areas | USERSYS <0 = DEEP_RESET request ?
3978         U>= ?GOTO BW1               \   if yes execute STOP_R2L then RET to BODY of WARM
3979     THEN                            \
3980 \    CMP #2,TOS                      \   Power_ON event
3981 \    0= ?GOTO BW1                    \   uncomment if you want to loose application in this case...
3982     CMP #4,TOS                      \   SYSRSTIV|USERSYS RST ?
3983     0= ?GOTO BW1                    \   if yes run STOP.
3984 \    CMP #$0E,TOS                    \   SYSRSTIV = SVSHIFG SVSH event ?
3985 \    0= ?GOTO BW1                    \   SVSHIFG SVSH event performs STOP
3986 \ ----------------------------------\
3987     LO2HI                           \
3988 \ ----------------------------------\
3989 \   Init LCD 2x20                   \
3990 \ ----------------------------------\
3991     #1000 20_US                     \ 1- wait 20 ms
3992     %011 TOP_LCD                    \ 2- send DB5=DB4=1
3993     #205 20_US                      \ 3- wait 4,1 ms
3994     %011 TOP_LCD                    \ 4- send again DB5=DB4=1
3995     #5 20_US                        \ 5- wait 0,1 ms
3996     %011 TOP_LCD                    \ 6- send again again DB5=DB4=1
3997     #2 20_US                        \    wait 40 us = LCD cycle
3998     %010 TOP_LCD                    \ 7- send DB5=1 DB4=0
3999     #2 20_US                        \    wait 40 us = LCD cycle
4000     %00101000 LCD_WRF               \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
4001     %1000 LCD_WRF                   \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off.
4002     LCD_CLEAR                       \ 10- "LCD_Clear"
4003     %0110 LCD_WRF                   \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
4004     %1100 LCD_WRF                   \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
4005     LCD_CLEAR                       \ 10- "LCD_Clear"
4006     HI2LO                           \
4007     MOV @RSP+,PC                    \ RET to WARM|START
4008     ENDCODE
4009 \ ----------------------------------\
4010
4011 \ ----------------------------------\
4012     CODE START                      \ this routine replaces INT_HARD_APP default values by these of this application.
4013 \ ----------------------------------\
4014     CMP #WDT_INT,&WDT_TIM_0_VEC     \ value set by START
4015     0= IF                           \
4016         MOV @IP+,PC                 \ does nothing if already initialised
4017     THEN
4018     MOV #STOP_R2L,&{RC5TOLCD}-2     \ execution of {RC5TOLCD} will perform STOP_R2L.
4019     KERNEL_ADDON $3C00 TSTBIT       \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
4020     [IF]
4021        MOV &UART_WARM+2,&{RC5TOLCD} \ save previous INI_APP subroutine
4022        MOV #INIT_R2L,&UART_WARM+2   \ replace it by RC5toLCD INI_APP
4023     [ELSE]
4024        MOV &I2C_WARM+2,&{RC5TOLCD}  \ save previous INI_APP subroutine
4025        MOV #INIT_R2L,&I2C_WARM+2    \ replace it by RC5toLCD INI_APP
4026     [THEN]
4027     MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+2 \ save Vector previous value
4028     MOV #WDT_INT,&WDT_TIM_0_VEC     \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
4029     MOV &IR_VEC,&{RC5TOLCD}+4       \ save Vector previous value
4030     MOV #RC5_INT,&IR_VEC            \ init interrupt vector
4031 \ ----------------------------------\
4032 \   init 20 us count loop           \ see 20_US
4033 \ ----------------------------------\ -- TOS
4034     SUB #6,PSP                      \ -- x x x TOS
4035     MOV TOS,4(PSP)                  \ -- TOS x x TOS
4036     MOV &FREQ_KHZ,2(PSP)            \ -- TOS DVDlo x TOS
4037     MOV #0,0(PSP)                   \ -- TOS DVDlo DVDhi TOS
4038     MOV #200,TOS                    \ -- TOS DVDlo DVDhi DIVlo
4039     CALL #MUSMOD                    \ -- TOS REMlo QUOTlo QUOThi
4040     MOV @PSP,&{RC5TOLCD}+6          \                       set count+2 for 20_US
4041     ADD #4,PSP                      \ -- TOS QUOThi
4042     MOV @PSP+,TOS                   \ -- TOS
4043 \ ----------------------------------\
4044     CALL #INIT_R2L                  \ run new INIT_HARD_APP
4045     LO2HI
4046 \    ['] LCD_HOME IS CR              \ ' CR redirected to LCD_HOME
4047 \    ['] LCD_WRC  IS EMIT            \ ' EMIT redirected to LCD_WrC
4048 \    CR ." I love you"               \ display message on LCD
4049 \    ['] CR >BODY IS CR              \ CR executes its default value
4050 \    ['] EMIT >BODY IS EMIT          \ EMIT executes its defaulte value
4051     ." RC5toLCD is running,"        \
4052     ."  Type STOP to quit."         \ display message on FastForth Terminal
4053     HI2LO
4054     MOV #ABORT,PC                   \ goto FORTH interpreter without WARM message.
4055     ENDCODE                         \
4056 \ ----------------------------------\
4057
4058 RST_SET
4059
4060     MARKER {RC5TOLCD}   \ restore the state before MARKER definition
4061 \                       \ {UARTI2CS}-2 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
4062     8 ALLOT             \ {UARTI2CS}    make room to save previous INI_APP address
4063                         \ {RC5TOLCD}+2  make room to save previous WDT_TIM_0_VEC
4064                         \ {RC5TOLCD}+4  make room to save previous IR_VEC
4065                         \ {RC5TOLCD}+6  make room for 20 us count loop.
4066
4067     [UNDEFINED] TSTBIT
4068     [IF]
4069     CODE TSTBIT     \ addr bit_mask -- true/flase flag
4070     MOV @PSP+,X
4071     AND @X,TOS
4072     MOV @IP+,PC
4073     ENDCODE
4074     [THEN]
4075
4076 \ https://forth-standard.org/standard/core/Equal
4077 \ =      x1 x2 -- flag         test x1=x2
4078     [UNDEFINED] =
4079     [IF]
4080     CODE =
4081     SUB @PSP+,TOS   \ 2
4082     0<> IF          \ 2
4083         AND #0,TOS  \ 1
4084         MOV @IP+,PC \ 4
4085     THEN
4086     XOR #-1,TOS     \ 1 flag Z = 1
4087     MOV @IP+,PC     \ 4
4088     ENDCODE
4089     [THEN]
4090
4091     [UNDEFINED] IF
4092     [IF]     \ define IF and THEN
4093 \ https://forth-standard.org/standard/core/IF
4094 \ IF       -- IFadr    initialize conditional forward branch
4095     CODE IF       \ immediate
4096     SUB #2,PSP              \
4097     MOV TOS,0(PSP)          \
4098     MOV &DP,TOS             \ -- HERE
4099     ADD #4,&DP              \           compile one word, reserve one word
4100     MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
4101     ADD #2,TOS              \ -- HERE+2=IFadr
4102     MOV @IP+,PC
4103     ENDCODE IMMEDIATE
4104
4105 \ https://forth-standard.org/standard/core/THEN
4106 \ THEN     IFadr --                resolve forward branch
4107     CODE THEN               \ immediate
4108     MOV &DP,0(TOS)          \ -- IFadr
4109     MOV @PSP+,TOS           \ --
4110     MOV @IP+,PC
4111     ENDCODE IMMEDIATE
4112     [THEN]
4113
4114 \ https://forth-standard.org/standard/core/ELSE
4115 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
4116     [UNDEFINED] ELSE
4117     [IF]
4118     CODE ELSE     \ immediate
4119     ADD #4,&DP              \ make room to compile two words
4120     MOV &DP,W               \ W=HERE+4
4121     MOV #BRAN,-4(W)
4122     MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
4123     SUB #2,W                \ HERE+2
4124     MOV W,TOS               \ -- ELSEadr
4125     MOV @IP+,PC
4126     ENDCODE IMMEDIATE
4127     [THEN]
4128
4129 \ \ https://forth-standard.org/standard/core/DEFERStore
4130 \ \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
4131 \     [UNDEFINED] IS
4132 \     [IF]     \ define DEFER! and IS
4133 \     CODE DEFER!             \ xt2 xt1 --
4134 \     MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
4135 \     MOV @PSP+,TOS           \ --
4136 \     MOV @IP+,PC
4137 \     ENDCODE
4138 \
4139 \ \ https://forth-standard.org/standard/core/IS
4140 \ \ IS <name>        xt --
4141 \ \ used as is :
4142 \ \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
4143 \ \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
4144 \ \ or in a definition : ... ['] U. IS DISPLAY ...
4145 \ \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
4146 \ \
4147 \ \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
4148 \
4149 \     : IS
4150 \     STATEADR @
4151 \     IF  POSTPONE ['] POSTPONE DEFER!
4152 \     ELSE ' DEFER!
4153 \     THEN
4154 \     ; IMMEDIATE
4155 \     [THEN]
4156
4157 \ https://forth-standard.org/standard/core/CR
4158 \ CR      --               send CR+LF to the output device
4159     [UNDEFINED] CR
4160     [IF]
4161 \ create a primary defered word, i.e. with its default runtime beginning at the >BODY of the definition
4162     CODE CR     \ part I : DEFERed definition of CR
4163     MOV #NEXT_ADR,PC                \ [PFA] = NEXT_ADR
4164     ENDCODE
4165
4166     :NONAME
4167     'CR' EMIT 'LF' EMIT
4168     ; IS CR
4169     [THEN]
4170
4171 \ https://forth-standard.org/standard/core/toBODY
4172 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
4173     [UNDEFINED] >BODY
4174     [IF]
4175     CODE >BODY
4176     ADD #4,TOS
4177     MOV @IP+,PC
4178     ENDCODE
4179     [THEN]
4180
4181     CODE 20_US                      \ n --
4182     BEGIN                           \          J_loop           8000    16000  24000  kHz
4183         MOV &{RC5TOLCD}+6,X         \            3          X = {40      80     120}
4184         SUB #2,X                    \           +1          X = {38      78     118} I_loops + 2 J_loops = {40 80 120} * 4 cycles
4185         BEGIN                       \  I_loop
4186             NOP                     \    1
4187             SUB #1,X                \   +1
4188         0=  UNTIL                   \   +2
4189         NOP                         \           +1
4190         SUB #1,TOS                  \           +1
4191     0= UNTIL                        \           +2
4192     MOV @PSP+,TOS                   \
4193     MOV @RSP+,IP                    \
4194     ENDCODE
4195
4196 \                                   \ if write : %xxxx_WWWW --
4197 \                                   \ if read  : -- %0000_RRRR
4198     CODE TOP_LCD                    \ LCD Sample
4199     BIS.B #LCD_EN,&LCD_CMD_OUT      \ lcd_en 0-->1
4200     BIT.B #LCD_RW,&LCD_CMD_IN       \ lcd_rw test
4201     0= IF                           \ write LCD bits pattern
4202         AND.B #LCD_DB,TOS           \
4203         MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
4204         BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
4205         MOV @PSP+,TOS               \
4206         MOV @IP+,PC
4207     THEN                            \ read LCD bits pattern
4208     SUB #2,PSP
4209     MOV TOS,0(PSP)
4210     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
4211     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
4212     AND.B #LCD_DB,TOS           \
4213     MOV @IP+,PC
4214     ENDCODE
4215
4216     CODE LCD_WRC                \ char --         Write Char
4217     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
4218 BW1 SUB #2,PSP                  \
4219     MOV TOS,0(PSP)              \ -- %HHHH_LLLL %HHHH_LLLL
4220     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
4221     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
4222     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
4223     COLON                       \ high level word starts here
4224     TOP_LCD 2 20_US             \ write high nibble first
4225     TOP_LCD 2 20_US
4226     ;
4227
4228     CODE LCD_WRF                \ func --         Write Fonction
4229     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
4230     GOTO BW1
4231     ENDCODE
4232
4233     : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
4234     : LCD_HOME $02 LCD_WRF 100 20_us ;
4235
4236 \     CODE LCD_ENTRY_SET
4237 \     BIS #$04,TOS
4238 \ BW1 COLON
4239 \     LCD_WrF
4240 \     ;
4241 \
4242 \     CODE LCD_DSP_CTRL
4243 \     BIS#$08,TOS
4244 \     GOTO BW1
4245 \     ENDCODE
4246 \
4247 \     CODE LCD_DSP_SHIFT
4248 \     BIS#$10,TOS
4249 \     GOTO BW1
4250 \     ENDCODE
4251 \
4252 \     CODE LCD_FN_SET
4253 \     BIS#$20,TOS
4254 \     GOTO BW1
4255 \     ENDCODE
4256 \
4257 \     CODE LCD_CGRAM_SET
4258 \     BIS #$40,TOS
4259 \     GOTO BW1
4260 \     ENDCODE
4261 \
4262 \     CODE LCD_GOTO
4263 \     BIS #$80,TOS
4264 \     GOTO BW1
4265 \     ENDCODE
4266 \
4267 \ CODE LCD_RDS                    \ -- status       Read Status
4268 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
4269 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
4270 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
4271 \ COLON                           \ starts a FORTH word
4272 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
4273 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
4274 \ HI2LO                           \ switch from FORTH to assembler
4275 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
4276 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
4277 \     MOV @RSP+,IP                \ restore IP saved by COLON
4278 \     MOV @IP+,PC                 \
4279 \ ENDCODE
4280 \
4281 \ CODE LCD_RDC                    \ -- char         Read Char
4282 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
4283 \     GOTO BW1
4284 \ ENDCODE
4285 \
4286 \
4287 \   ********************************\
4288     HDNCODE WDT_INT                 \ Watchdog interrupt routine, warning : not FORTH executable !
4289 \   ********************************\
4290 \    XOR.B #LED1,&LED1_OUT           \ to visualise WDT
4291     BIT.B #SW2,&SW2_IN              \ test switch S2
4292     0= IF                           \ case of switch S2 pressed
4293         CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
4294         U< IF
4295             ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
4296         THEN
4297     ELSE
4298         BIT.B #SW1,&SW1_IN          \ test switch S1 input
4299         0= IF                       \ case of Switch S1 pressed
4300             CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
4301             U>= IF                  \
4302             SUB #1,&LCD_TIM_CCRn    \ action for switch S1 (P2.6) : -150 mV / decrement
4303             THEN                    \
4304         THEN                        \
4305     THEN                            \
4306     RETI                            \ 5
4307     ENDCODE                         \
4308 \   ********************************\
4309
4310 \   ********************************\
4311     HDNCODE RC5_INT                 \   wake up on Px.RC5 change interrupt
4312 \   ********************************\
4313 \   IR_RC5 driver                   \ IP,S,T,W,X,Y registers are free for use
4314 \   ********************************\
4315 \                                   \ in :  SR(9)=old Toggle bit memory (ADD on)
4316 \                                   \       SMclock = 8|16|24 MHz
4317 \                                   \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
4318 \                                   \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
4319 \                                   \       SR(9)=new Toggle bit memory (ADD on)
4320 \   ********************************\
4321 \   RC5_FirstStartBitHalfCycle:     \
4322 \   ********************************\
4323     MOV #1778,X                     \ RC5_Period in us
4324     MOV #14,W                       \ count of loop
4325     BEGIN                           \
4326 \       ****************************\
4327 \       RC5_HalfCycle               \ <--- loop back ---+ with readjusted RC5_Period
4328 \       ****************************\                   |
4329       MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
4330 \       RC5_Compute_3/4_Period:     \                   |
4331         RRUM    #1,X                \ X=1/2 cycle       |
4332         MOV     X,Y                 \                   ^
4333         RRUM    #1,Y                \ Y=1/4
4334         ADD     X,Y                 \ Y=3/4 cycle
4335         BEGIN                       \
4336             CMP Y,&RC5_TIM_R        \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
4337         U>= UNTIL                   \ 2
4338 \       ****************************\
4339 \       RC5_SampleOnFirstQuarter    \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
4340 \       ****************************\
4341         BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
4342         ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
4343         MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
4344         BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
4345         SUB     #1,W                \ decrement count loop
4346 \                                   \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
4347 \                                   \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1
4348     0<> WHILE                       \ ----> out of loop ----+
4349         ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
4350         BEGIN                       \                       |
4351             MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
4352             CMP Y,X                 \ 1                 ^   |   cycle time out of bound ?
4353             U>= ?GOTO FW1           \                   |   |   quit on truncated RC5 message
4354             BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
4355         0<> UNTIL                   \ 2                 |   |
4356     REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
4357 \   ********************************\                       |
4358 \   RC5_SampleEndOf:                \ <---------------------+
4359 \   ********************************\
4360     BIC #$30,&RC5_TIM_CTL           \   stop timer
4361 \   ********************************\
4362 \   RC5_ComputeNewRC5word           \
4363 \   ********************************\
4364     RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
4365     MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
4366     RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
4367 \   ********************************\
4368 \   RC5_ComputeC6bit                \
4369 \   ********************************\
4370     BIT     #BIT14,T                \ test /C6 bit in T
4371     0= IF   BIS #BIT6,X             \ set C6 bit in X
4372     THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
4373 \   ********************************\
4374 \   RC5_CommandByteIsDone           \
4375 \   ********************************\
4376 \   Only New_RC5_Command ADD_ON     \ use SR(10) bit as toggle bit
4377 \   ********************************\
4378     RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
4379     XOR     @RSP,T                  \ (new XOR old) Toggle bits
4380     BIT     #UF10,T                 \ repeated RC5_command ?
4381     0= ?GOTO FW2                    \ yes, RETI without UF10 change and without action !
4382     XOR #UF10,0(RSP)                \ 5 toggle bit memory
4383 \   ********************************\
4384 \   Display IR_RC5 code             \
4385 \   ********************************\
4386     SUB #6,PSP                      \   -- x x x TOS
4387     MOV TOS,4(PSP)                  \   -- TOS x x TOS
4388     MOV &BASEADR,2(PSP)             \   -- TOS Base x TOS
4389     MOV #$10,&BASEADR               \                               set hexadecimal base
4390     MOV X,0(PSP)                    \   -- TOS Base RC5_code TOS    convert number to ascii low word = RC5 byte
4391     MOV #0,TOS                      \   -- TOS Base RC5_code 0      convert double number to ascii
4392     LO2HI                           \                               switch from assembler to FORTH
4393     LCD_CLEAR                       \                               set LCD cursor at home
4394     <# # #S #36 HOLD #>             \   -- TOS Base adr cnt         32 bits conversion as "$xx"
4395     ['] LCD_WRC IS EMIT             \                               redirect EMIT to LCD
4396     TYPE                            \   -- TOS Base                 display "$xx" on LCD
4397     ['] EMIT >BODY IS EMIT          \                               restore EMIT
4398     HI2LO                           \                               switch from FORTH to assembler
4399     MOV @PSP+,&BASEADR              \   -- TOS                      restore current BASE
4400     MOV @PSP+,TOS                   \   --
4401 FW1 BIC #$30,&RC5_TIM_CTL           \ stop timer (case of truncated RC5 message)
4402 FW2 BIC #%1111_1000,0(RSP)          \ force CPU Active Mode and disable GIE in saved SR
4403     RETI                            \
4404     ENDCODE                         \
4405 \   ********************************\
4406
4407 \ define our STOP_APP
4408 \ ----------------------------------\
4409     HDNCODE STOP_R2L                \ called by STOP|INIT_R2L|{RC5TOLCD}
4410 \ ----------------------------------\
4411     CMP #WDT_INT,&WDT_TIM_0_VEC     \ value set by START
4412     0= IF                           \ only if START is done
4413         BIC.B #RC5,&IR_IE           \ clear I/O RC5_Int
4414         BIC.B #RC5,&IR_IFG          \ clear I/O RC5_Int flag
4415         MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER, clear LCD_TIMER IFG
4416         MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
4417         MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
4418         MOV #{RC5TOLCD},W           \
4419         MOV #RET_ADR,-2(W)          \ clear MARKER_DOES call
4420         KERNEL_ADDON $3C00 TSTBIT   \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
4421         [IF]
4422         MOV @W+,&UART_WARM+2        \ restore previous ini_APP
4423         [ELSE]
4424         MOV @W+,&I2C_WARM+2         \ restore previous ini_APP
4425         [THEN]
4426         MOV @W+,&WDT_TIM_0_VEC      \ restore Vector previous value
4427         MOV @W+,&IR_VEC             \ restore Vector previous value
4428     THEN
4429     MOV @RSP+,PC                    \ RET to STOP|WARM+4|{RC5TOLCD}
4430     ENDCODE
4431 \ ----------------------------------\
4432
4433 \ ----------------------------------\
4434     CODE STOP                       \ also called by INIT_R2L for some events
4435 \ ----------------------------------\
4436 BW1 CALL #STOP_R2L
4437     COLON                           \
4438     ECHO                            \
4439     ." type START to start RC5toLCD"
4440     ;
4441 \ ----------------------------------\
4442
4443 \ this routine completes the INIT_HARD of FORTH, with INIT_HARD for this app.
4444 \ ----------------------------------\
4445     HDNCODE INIT_R2L                \ called by START|SYS
4446 \ ----------------------------------\
4447 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
4448 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
4449 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
4450 \                           --       \ID input divider \ 10 = /4
4451 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
4452 \                                 -  \TBCLR TimerB Clear
4453 \                                  - \TBIE
4454 \                                   -\TBIFG
4455 \ ----------------------------------\
4456 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
4457 \                  --                 \CM Capture Mode
4458 \                    --               \CCIS
4459 \                       -             \SCS
4460 \                        --           \CLLD
4461 \                          -          \CAP
4462 \                            ---      \OUTMOD \ 011 = set/reset
4463 \                               -     \CCIE
4464 \                                 -   \CCI
4465 \                                  -  \OUT
4466 \                                   - \COV
4467 \                                    -\CCIFG
4468 \ ----------------------------------\
4469 \ LCD_TIM_CCRx                      \
4470 \ ----------------------------------\
4471 \ LCD_TIM_EX0                       \
4472 \ ----------------------------------\
4473 \ set LCD_TIM_ to make 50kHz PWM    \ for LCD_Vo; works without interrupt
4474 \ ----------------------------------\
4475     MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int, set IFG
4476 \    MOV #0,&RC5_TIM_EX0             \ predivide by 1 in RC5_TIM_EX0 register, reset value
4477 \    MOV #0,&LCD_TIM_EX0             \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
4478     FREQ_KHZ @ 16000 =
4479     [IF]                            \ if 16 MHz
4480         MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
4481         MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
4482     [THEN]
4483     FREQ_KHZ @ 24000 =
4484     [IF]                            \ if 24 MHz
4485         MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
4486         MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
4487     [THEN]
4488         MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
4489 \ ----------------------------------\
4490 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
4491 \ ----------------------------------\
4492     MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
4493     MOV #10,&LCD_TIM_CCRn           \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
4494 \    MOV #12,&LCD_TIM_CCRn           \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
4495 \ ----------------------------------\
4496     BIS.B #LCDVo,&LCDVo_DIR         \
4497     BIS.B #LCDVo,&LCDVo_SEL         \ SEL.2
4498 \ ----------------------------------\
4499     BIS.B #LCD_CMD,&LCD_CMD_DIR     \ lcd_cmd as outputs
4500     BIC.B #LCD_CMD,&LCD_CMD_REN     \ lcd_cmd pullup/down disable
4501 \ ----------------------------------\
4502     BIS.B #LCD_DB,&LCD_DB_DIR       \ as output, wired to DB(4-7) LCD_Data
4503     BIC.B #LCD_DB,&LCD_DB_REN       \ LCD_Data pullup/down disable
4504 \ ----------------------------------\
4505 \ init RC5_Int                      \
4506 \ ----------------------------------\
4507     BIS.B #RC5,&IR_IE               \ enable RC5_Int
4508     BIC.B #RC5,&IR_IFG              \ reset RC5_Int flag
4509 \ ----------------------------------\
4510 \ init WatchDog WDT_TIM_            \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
4511 \ ----------------------------------\
4512 \              %01 0001 0100        \ TAxCTL
4513 \               --                  \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
4514 \                  --               \ ID        divided by 1
4515 \                    --             \ MC        MODE = up to TAxCCRn
4516 \                        -          \ TACLR     clear timer count
4517 \                         -         \ TAIE
4518 \                          -        \ TAIFG
4519 \ ----------------------------------\
4520     MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
4521 \ ----------------------------------\
4522 \                        000        \ TAxEX0
4523 \                        ---        \ TAIDEX    pre divisor
4524 \ ----------------------------------\
4525 \          %0000 0000 0000 0101     \ TAxCCR0
4526     MOV ##3276,&WDT_TIM_CCR0        \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
4527 \ ----------------------------------\
4528 \          %0000 0000 0001 0000     \ TAxCCTL0
4529 \                   -               \ CAP capture/compare mode = compare
4530 \                        -          \ CCIEn
4531 \                             -     \ CCIFGn
4532     MOV #%10000,&WDT_TIM_CCTL0      \ enable compare interrupt, clear CCIFG0
4533 \ ----------------------------------\
4534 \ activate I/O                      \
4535 \ ----------------------------------\
4536     CALL &{RC5TOLCD}                \ run previous INIT_HARD_APP
4537 \ ----------------------------------\
4538 \ RESET events handling             \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
4539 \ ----------------------------------\
4540     CMP #$0E,TOS                    \ SYSRSTIV = SVSHIFG SVSH event ?
4541     0<> IF                          \ if not
4542         CMP #$0A,TOS                \   SYSRSTIV >= violation memory protected areas | USERSYS <0 = DEEP_RESET request ?
4543         U>= ?GOTO BW1               \   if yes execute STOP_R2L then RET to BODY of WARM
4544     THEN                            \
4545 \    CMP #2,TOS                      \   Power_ON event
4546 \    0= ?GOTO BW1                    \   uncomment if you want to loose application in this case...
4547     CMP #4,TOS                      \   SYSRSTIV|USERSYS RST ?
4548     0= ?GOTO BW1                    \   if yes run STOP.
4549 \    CMP #$0E,TOS                    \   SYSRSTIV = SVSHIFG SVSH event ?
4550 \    0= ?GOTO BW1                    \   SVSHIFG SVSH event performs STOP
4551 \ ----------------------------------\
4552     LO2HI                           \
4553 \ ----------------------------------\
4554 \   Init LCD 2x20                   \
4555 \ ----------------------------------\
4556     #1000 20_US                     \ 1- wait 20 ms
4557     %011 TOP_LCD                    \ 2- send DB5=DB4=1
4558     #205 20_US                      \ 3- wait 4,1 ms
4559     %011 TOP_LCD                    \ 4- send again DB5=DB4=1
4560     #5 20_US                        \ 5- wait 0,1 ms
4561     %011 TOP_LCD                    \ 6- send again again DB5=DB4=1
4562     #2 20_US                        \    wait 40 us = LCD cycle
4563     %010 TOP_LCD                    \ 7- send DB5=1 DB4=0
4564     #2 20_US                        \    wait 40 us = LCD cycle
4565     %00101000 LCD_WRF               \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
4566     %1000 LCD_WRF                   \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off.
4567     LCD_CLEAR                       \ 10- "LCD_Clear"
4568     %0110 LCD_WRF                   \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
4569     %1100 LCD_WRF                   \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
4570     LCD_CLEAR                       \ 10- "LCD_Clear"
4571     HI2LO                           \
4572     MOV @RSP+,PC                    \ RET to WARM|START
4573     ENDCODE
4574 \ ----------------------------------\
4575
4576 \ ----------------------------------\
4577     CODE START                      \ this routine replaces INT_HARD_APP default values by these of this application.
4578 \ ----------------------------------\
4579     CMP #WDT_INT,&WDT_TIM_0_VEC     \ value set by START
4580     0= IF                           \
4581         MOV @IP+,PC                 \ does nothing if already initialised
4582     THEN
4583     MOV #STOP_R2L,&{RC5TOLCD}-2     \ execution of {RC5TOLCD} will perform STOP_R2L.
4584     KERNEL_ADDON $3C00 TSTBIT       \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
4585     [IF]
4586        MOV &UART_WARM+2,&{RC5TOLCD} \ save previous INI_APP subroutine
4587        MOV #INIT_R2L,&UART_WARM+2   \ replace it by RC5toLCD INI_APP
4588     [ELSE]
4589        MOV &I2C_WARM+2,&{RC5TOLCD}  \ save previous INI_APP subroutine
4590        MOV #INIT_R2L,&I2C_WARM+2    \ replace it by RC5toLCD INI_APP
4591     [THEN]
4592     MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+2 \ save Vector previous value
4593     MOV #WDT_INT,&WDT_TIM_0_VEC     \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
4594     MOV &IR_VEC,&{RC5TOLCD}+4       \ save Vector previous value
4595     MOV #RC5_INT,&IR_VEC            \ init interrupt vector
4596 \ ----------------------------------\
4597 \   init 20 us count loop           \ see 20_US
4598 \ ----------------------------------\ -- TOS
4599     SUB #6,PSP                      \ -- x x x TOS
4600     MOV TOS,4(PSP)                  \ -- TOS x x TOS
4601     MOV &FREQ_KHZ,2(PSP)            \ -- TOS DVDlo x TOS
4602     MOV #0,0(PSP)                   \ -- TOS DVDlo DVDhi TOS
4603     MOV #200,TOS                    \ -- TOS DVDlo DVDhi DIVlo
4604     CALL #MUSMOD                    \ -- TOS REMlo QUOTlo QUOThi
4605     MOV @PSP,&{RC5TOLCD}+6          \                       set count+2 for 20_US
4606     ADD #4,PSP                      \ -- TOS QUOThi
4607     MOV @PSP+,TOS                   \ -- TOS
4608 \ ----------------------------------\
4609     CALL #INIT_R2L                  \ run new INIT_HARD_APP
4610     LO2HI
4611 \    ['] LCD_HOME IS CR              \ ' CR redirected to LCD_HOME
4612 \    ['] LCD_WRC  IS EMIT            \ ' EMIT redirected to LCD_WrC
4613 \    CR ." I love you"               \ display message on LCD
4614 \    ['] CR >BODY IS CR              \ CR executes its default value
4615 \    ['] EMIT >BODY IS EMIT          \ EMIT executes its defaulte value
4616     ." RC5toLCD is running,"        \
4617     ."  Type STOP to quit."         \ display message on FastForth Terminal
4618     HI2LO
4619     MOV #ABORT,PC                   \ goto FORTH interpreter without WARM message.
4620     ENDCODE                         \
4621 \ ----------------------------------\
4622
4623 RST_SET
4624
4625 \ START