OSDN Git Service

V309
[fast-forth/master.git] / MSP430-FORTH / RC5toLCD.f
1 \ -*- coding: utf-8 -*-
2
3 ; -----------------------------------
4 ; RC5TOLCD.f
5 ; -----------------------------------
6 \
7 \ to see kernel options, download FastForthSpecs.f
8 \ FastForth kernel options: MSP430ASSEMBLER, CONDCOMP, FREQUENCY = 8/16/24 MHz
9 \
10 \ TARGET SELECTION ( = the name of \INC\target.pat file without the extension)
11 \ MSP_EXP430FR5739  MSP_EXP430FR5969    MSP_EXP430FR5994    MSP_EXP430FR6989
12 \ MSP_EXP430FR2355
13 \ LP_MSP430FR2476
14 \
15 \ from scite editor : copy your target selection in (shift+F8) parameter 1:
16 \
17 \ OR
18 \
19 \ drag and drop this file onto SendSourceFileToTarget.bat
20 \ then select your TARGET when asked.
21 \
22 \
23 \ ================================================================================
24 \ REGISTERS USAGE for embedded MSP430 ASSEMBLER
25 \ ================================================================================
26 \ don't use R2, R3, R4
27 \ R5, R6, R7 must be PUSHed/POPed before/after use, OR restored after: MOV #{XDOCOL|XDOCON|R>},{rDODOES|rDOCON|rDOVAR}
28 \ scratch registers Y to S are free,
29 \ under interrupt, IP is free,
30 \ use FORTH rules for reg. TOS, PSP, RSP.
31 \
32 \ PUSHM order : PSP,TOS, IP, S , T , W , X , Y ,rDOVAR,rDOCON,rDODOES,rDOCOL, R3, SR,RSP, PC
33 \ PUSHM order : R15,R14,R13,R12,R11,R10, R9, R8,  R7  ,  R6  ,  R5   ,  R4  , R3, R2, R1, R0
34 \
35 \ example : PUSHM #6,IP pushes IP,S,T,W,X,Y registers to return stack
36 \
37 \ POPM  order :  PC,RSP, SR, R3, rDODOES,rDOCON,rDOVAR,rEXIT,  Y,  X,  W,  T,  S, IP,TOS,PSP
38 \ POPM  order :  R0, R1, R2, R3,   R4   ,  R5  ,  R6  ,  R7 , R8, R9,R10,R11,R12,R13,R14,R15
39 \
40 \ example : POPM #6,IP   pop Y,X,W,T,S,IP registers from return stack
41 \
42 \ ASSEMBLER conditionnal usage after IF UNTIL WHILE : S< S>= U< U>= 0= 0<> 0>=
43 \ ASSEMBLER conditionnal usage before      ?GOTO    : S< S>= U< U>= 0= 0<> 0<
44 \
45 \
46 \ display on a LCD 2x20 CHAR the code sent by an IR remote under philips RC5 protocol
47 \ target : any TI MSP-EXP430FRxxxx launchpad (FRAM)
48 \ LPM_MODE = LPM0 because use SMCLK for LCDVo
49 \
50 \ DEMO : driver for IR remote compatible with the PHILIPS RC5 protocol
51 \ plus : driver for 5V LCD 2x20 characters display with 4 bits data interface
52 \        without usage of an auxiliary 5V to feed the LCD_Vo
53 \        and without potentiometer to adjust the LCD contrast :
54 \        to adjust LCD contrast, just press S1 (-) or S2 (+)
55 \        LCDVo current consumption ~ 500 uA.
56 \
57 \ ===================================================================================
58 \ notice : adjust WDT_TIM_EX0,LCD_TIM_CTL,LCD_TIM_EX0 and 20_us to the target frequency if <> 8MHz !
59 \ ===================================================================================
60 \
61 \
62 \ layout : I/O are defined in the launchpad.pat file (don't work with ChipStick_FR2433)
63 \
64 \  GND  <-------o---0V0---------->  1 LCD_Vss
65 \  VCC  >-------|---3V6-----o---->  2 LCD_Vdd
66 \               |           |
67 \              ___    470n ---
68 \               ^          ---
69 \              / \ 1N4148   |
70 \              ---          |
71 \          100n |    2k2    |
72 \ TB0.2 >---||--o--^/\/\/v--o---->  3 LCD_Vo (= 0V6 without modulation)
73 \       ------------------------->  4 LCD_RW
74 \       ------------------------->  5 LCD_RW
75 \       ------------------------->  6 LCD_EN
76 \       <------------------------> 11 LCD_DB4
77 \       <------------------------> 12 LCD_DB5
78 \       <------------------------> 13 LCD_DB5
79 \       <------------------------> 14 LCD_DB7
80 \
81 \       <----- LCD contrast + <---    Sw1   <--- (finger) :-)
82 \       <----- LCD contrast - <---    Sw2   <--- (finger) :-)
83 \
84 \ rc5   <--- OUT IR_Receiver (1 TSOP32236)
85
86
87 \ first, we test for downloading driver only if UART TERMINAL target
88     CODE ABORT_RC5TOLCD
89     SUB #2,PSP
90     MOV TOS,0(PSP)
91     MOV &VERSION,TOS
92     SUB #309,TOS        \                   FastForth V3.9
93     COLON
94     'CR' EMIT            \ return to column 1 without 'LF'
95     ABORT" FastForth V3.9 please!"
96     RST_RET              \ remove ABORT_UARTI2CS definition before resuming
97     ;
98
99     ABORT_RC5TOLCD
100
101     MARKER {RC5TOLCD}   \ restore the state before MARKER definition
102 \                       \ {UARTI2CS}-2 = RET_ADR: by default MARKER_DOES does CALL #RET_ADR
103     8 ALLOT             \ {UARTI2CS}    make room to save previous INI_APP address
104                         \ {RC5TOLCD}+2  make room to save previous WDT_TIM_0_VEC
105                         \ {RC5TOLCD}+4  make room to save previous IR_VEC
106                         \ {RC5TOLCD}+6  make room for 20 us count loop.
107
108     [UNDEFINED] TSTBIT
109     [IF]
110     CODE TSTBIT     \ addr bit_mask -- true/flase flag
111     MOV @PSP+,X
112     AND @X,TOS
113     MOV @IP+,PC
114     ENDCODE
115     [THEN]
116
117 \ https://forth-standard.org/standard/core/Equal
118 \ =      x1 x2 -- flag         test x1=x2
119     [UNDEFINED] =
120     [IF]
121     CODE =
122     SUB @PSP+,TOS   \ 2
123     0<> IF          \ 2
124         AND #0,TOS  \ 1
125         MOV @IP+,PC \ 4
126     THEN
127     XOR #-1,TOS     \ 1 flag Z = 1
128     MOV @IP+,PC     \ 4
129     ENDCODE
130     [THEN]
131
132     [UNDEFINED] IF
133     [IF]     \ define IF and THEN
134 \ https://forth-standard.org/standard/core/IF
135 \ IF       -- IFadr    initialize conditional forward branch
136     CODE IF       \ immediate
137     SUB #2,PSP              \
138     MOV TOS,0(PSP)          \
139     MOV &DP,TOS             \ -- HERE
140     ADD #4,&DP              \           compile one word, reserve one word
141     MOV #QFBRAN,0(TOS)      \ -- HERE   compile QFBRAN
142     ADD #2,TOS              \ -- HERE+2=IFadr
143     MOV @IP+,PC
144     ENDCODE IMMEDIATE
145
146 \ https://forth-standard.org/standard/core/THEN
147 \ THEN     IFadr --                resolve forward branch
148     CODE THEN               \ immediate
149     MOV &DP,0(TOS)          \ -- IFadr
150     MOV @PSP+,TOS           \ --
151     MOV @IP+,PC
152     ENDCODE IMMEDIATE
153     [THEN]
154
155 \ https://forth-standard.org/standard/core/ELSE
156 \ ELSE     IFadr -- ELSEadr        resolve forward IF branch, leave ELSEadr on stack
157     [UNDEFINED] ELSE
158     [IF]
159     CODE ELSE     \ immediate
160     ADD #4,&DP              \ make room to compile two words
161     MOV &DP,W               \ W=HERE+4
162     MOV #BRAN,-4(W)
163     MOV W,0(TOS)            \ HERE+4 ==> [IFadr]
164     SUB #2,W                \ HERE+2
165     MOV W,TOS               \ -- ELSEadr
166     MOV @IP+,PC
167     ENDCODE IMMEDIATE
168     [THEN]
169
170 \ \ https://forth-standard.org/standard/core/DEFERStore
171 \ \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
172 \     [UNDEFINED] IS
173 \     [IF]     \ define DEFER! and IS
174 \     CODE DEFER!             \ xt2 xt1 --
175 \     MOV @PSP+,2(TOS)        \ -- xt1=CFA_DEFER          xt2 --> [CFA_DEFER+2]
176 \     MOV @PSP+,TOS           \ --
177 \     MOV @IP+,PC
178 \     ENDCODE
179 \
180 \ \ https://forth-standard.org/standard/core/IS
181 \ \ IS <name>        xt --
182 \ \ used as is :
183 \ \ DEFER DISPLAY                         create a "do nothing" definition (2 CELLS)
184 \ \ inline command : ' U. IS DISPLAY      U. becomes the runtime of the word DISPLAY
185 \ \ or in a definition : ... ['] U. IS DISPLAY ...
186 \ \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
187 \ \
188 \ \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
189 \
190 \     : IS
191 \     STATEADR @
192 \     IF  POSTPONE ['] POSTPONE DEFER!
193 \     ELSE ' DEFER!
194 \     THEN
195 \     ; IMMEDIATE
196 \     [THEN]
197
198 \ https://forth-standard.org/standard/core/CR
199 \ CR      --               send CR+LF to the output device
200     [UNDEFINED] CR
201     [IF]
202 \ create a primary defered word, i.e. with its default runtime beginning at the >BODY of the definition
203     CODE CR     \ part I : DEFERed definition of CR
204     MOV #NEXT_ADR,PC                \ [PFA] = NEXT_ADR
205     ENDCODE
206
207     :NONAME
208     'CR' EMIT 'LF' EMIT
209     ; IS CR
210     [THEN]
211
212 \ https://forth-standard.org/standard/core/toBODY
213 \ >BODY     -- addr      leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
214     [UNDEFINED] >BODY
215     [IF]
216     CODE >BODY
217     ADD #4,TOS
218     MOV @IP+,PC
219     ENDCODE
220     [THEN]
221
222     CODE 20_US                      \ n --
223     BEGIN                           \          J_loop           8000    16000  24000  kHz
224         MOV &{RC5TOLCD}+6,X         \            3          X = {40      80     120}
225         SUB #2,X                    \           +1          X = {38      78     118} I_loops + 2 J_loops = {40 80 120} * 4 cycles
226         BEGIN                       \  I_loop
227             NOP                     \    1
228             SUB #1,X                \   +1
229         0=  UNTIL                   \   +2
230         NOP                         \           +1
231         SUB #1,TOS                  \           +1
232     0= UNTIL                        \           +2
233     MOV @PSP+,TOS                   \
234     MOV @RSP+,IP                    \
235     ENDCODE
236
237 \                                   \ if write : %xxxx_WWWW --
238 \                                   \ if read  : -- %0000_RRRR
239     CODE TOP_LCD                    \ LCD Sample
240     BIS.B #LCD_EN,&LCD_CMD_OUT      \ lcd_en 0-->1
241     BIT.B #LCD_RW,&LCD_CMD_IN       \ lcd_rw test
242     0= IF                           \ write LCD bits pattern
243         AND.B #LCD_DB,TOS           \
244         MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
245         BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
246         MOV @PSP+,TOS               \
247         MOV @IP+,PC
248     THEN                            \ read LCD bits pattern
249     SUB #2,PSP
250     MOV TOS,0(PSP)
251     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
252     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
253     AND.B #LCD_DB,TOS           \
254     MOV @IP+,PC
255     ENDCODE
256
257     CODE LCD_WRC                \ char --         Write Char
258     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
259 BW1 SUB #2,PSP                  \
260     MOV TOS,0(PSP)              \ -- %HHHH_LLLL %HHHH_LLLL
261     RRUM #4,TOS                 \ -- %xxxx_LLLL %xxxx_HHHH
262     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
263     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
264     COLON                       \ high level word starts here
265     TOP_LCD 2 20_US             \ write high nibble first
266     TOP_LCD 2 20_US
267     ;
268
269     CODE LCD_WRF                \ func --         Write Fonction
270     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
271     GOTO BW1
272     ENDCODE
273
274     : LCD_CLEAR $01 LCD_WRF 100 20_us ;    \  $01 LCD_WrF 80 20_us ==> bad init !
275     : LCD_HOME $02 LCD_WRF 100 20_us ;
276
277 \     CODE LCD_ENTRY_SET
278 \     BIS #$04,TOS
279 \ BW1 COLON
280 \     LCD_WrF
281 \     ;
282 \
283 \     CODE LCD_DSP_CTRL
284 \     BIS#$08,TOS
285 \     GOTO BW1
286 \     ENDCODE
287 \
288 \     CODE LCD_DSP_SHIFT
289 \     BIS#$10,TOS
290 \     GOTO BW1
291 \     ENDCODE
292 \
293 \     CODE LCD_FN_SET
294 \     BIS#$20,TOS
295 \     GOTO BW1
296 \     ENDCODE
297 \
298 \     CODE LCD_CGRAM_SET
299 \     BIS #$40,TOS
300 \     GOTO BW1
301 \     ENDCODE
302 \
303 \     CODE LCD_GOTO
304 \     BIS #$80,TOS
305 \     GOTO BW1
306 \     ENDCODE
307 \
308 \ CODE LCD_RDS                    \ -- status       Read Status
309 \     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
310 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
311 \     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
312 \ COLON                           \ starts a FORTH word
313 \     TOP_LCD 2 20_us             \ -- %0000_HHHH
314 \     TOP_LCD 2 20_us             \ -- %0000_HHHH %0000_LLLL
315 \ HI2LO                           \ switch from FORTH to assembler
316 \     RLAM #4,0(PSP)              \ -- %HHHH_0000 %0000_LLLL
317 \     ADD.B @PSP+,TOS             \ -- %HHHH_LLLL
318 \     MOV @RSP+,IP                \ restore IP saved by COLON
319 \     MOV @IP+,PC                 \
320 \ ENDCODE
321 \
322 \ CODE LCD_RDC                    \ -- char         Read Char
323 \     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
324 \     GOTO BW1
325 \ ENDCODE
326 \
327 \
328 \   ********************************\
329     HDNCODE WDT_INT                 \ Watchdog interrupt routine, warning : not FORTH executable !
330 \   ********************************\
331 \    XOR.B #LED1,&LED1_OUT           \ to visualise WDT
332     BIT.B #SW2,&SW2_IN              \ test switch S2
333     0= IF                           \ case of switch S2 pressed
334         CMP #19,&LCD_TIM_CCRn       \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
335         U< IF
336             ADD #1,&LCD_TIM_CCRn    \ action for switch S2 (P2.5) : 150 mV / increment
337         THEN
338     ELSE
339         BIT.B #SW1,&SW1_IN          \ test switch S1 input
340         0= IF                       \ case of Switch S1 pressed
341             CMP #3,&LCD_TIM_CCRn    \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
342             U>= IF                  \
343             SUB #1,&LCD_TIM_CCRn    \ action for switch S1 (P2.6) : -150 mV / decrement
344             THEN                    \
345         THEN                        \
346     THEN                            \
347     RETI                            \ 5
348     ENDCODE                         \
349 \   ********************************\
350
351 \   ********************************\
352     HDNCODE RC5_INT                 \   wake up on Px.RC5 change interrupt
353 \   ********************************\
354 \   IR_RC5 driver                   \ IP,S,T,W,X,Y registers are free for use
355 \   ********************************\
356 \                                   \ in :  SR(9)=old Toggle bit memory (ADD on)
357 \                                   \       SMclock = 8|16|24 MHz
358 \                                   \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
359 \                                   \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
360 \                                   \       SR(9)=new Toggle bit memory (ADD on)
361 \   ********************************\
362 \   RC5_FirstStartBitHalfCycle:     \
363 \   ********************************\
364     MOV #1778,X                     \ RC5_Period in us
365     MOV #14,W                       \ count of loop
366     BEGIN                           \
367 \       ****************************\
368 \       RC5_HalfCycle               \ <--- loop back ---+ with readjusted RC5_Period
369 \       ****************************\                   |
370       MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
371 \       RC5_Compute_3/4_Period:     \                   |
372         RRUM    #1,X                \ X=1/2 cycle       |
373         MOV     X,Y                 \                   ^
374         RRUM    #1,Y                \ Y=1/4
375         ADD     X,Y                 \ Y=3/4 cycle
376         BEGIN                       \
377             CMP Y,&RC5_TIM_R        \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
378         U>= UNTIL                   \ 2
379 \       ****************************\
380 \       RC5_SampleOnFirstQuarter    \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
381 \       ****************************\
382         BIT.B   #RC5,&IR_IN         \ C_flag = IR bit
383         ADDC    T,T                 \ C_flag <-- T(15):T(0) <-- C_flag
384         MOV.B   &IR_IN,&IR_IES      \ preset Px_IES.y state for next IFG
385         BIC.B   #RC5,&IR_IFG        \ clear Px_IFG.y after 4/4 cycle pin change
386         SUB     #1,W                \ decrement count loop
387 \                                   \  count = 13 ==> T = x  x  x  x  x  x  x  x |x  x  x  x  x  x  x /C6
388 \                                   \  count = 0  ==> T = x  x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0  1
389     0<> WHILE                       \ ----> out of loop ----+
390         ADD X,Y                     \                       |   Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
391         BEGIN                       \                       |
392             MOV &RC5_TIM_R,X        \ 3                     |   X grows from n+1/4 up to n+3/4 cycles
393             CMP Y,X                 \ 1                 ^   |   cycle time out of bound ?
394             U>= ?GOTO FW1           \                   |   |   quit on truncated RC5 message
395             BIT.B #RC5,&IR_IFG      \ 3                 |   |   n+1/2 cycles edge is always present
396         0<> UNTIL                   \ 2                 |   |
397     REPEAT                          \ ----> loop back --+   |   with X = new RC5_period value
398 \   ********************************\                       |
399 \   RC5_SampleEndOf:                \ <---------------------+
400 \   ********************************\
401     BIC #$30,&RC5_TIM_CTL           \   stop timer
402 \   ********************************\
403 \   RC5_ComputeNewRC5word           \
404 \   ********************************\
405     RLAM    #1,T                    \ T =  x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0  1  0
406     MOV.B   T,X                     \ X = C5 C4 C3 C2 C1 C0  1  0
407     RRUM    #2,X                    \ X =  0  0 C5 C4 C3 C2 C1 C0
408 \   ********************************\
409 \   RC5_ComputeC6bit                \
410 \   ********************************\
411     BIT     #BIT14,T                \ test /C6 bit in T
412     0= IF   BIS #BIT6,X             \ set C6 bit in X
413     THEN                            \ X =  0  C6 C5 C4 C3 C2 C1 C0
414 \   ********************************\
415 \   RC5_CommandByteIsDone           \
416 \   ********************************\
417 \   Only New_RC5_Command ADD_ON     \ use SR(10) bit as toggle bit
418 \   ********************************\
419     RRUM    #3,T                    \ new toggle bit = T(13) ==> T(10)
420     XOR     @RSP,T                  \ (new XOR old) Toggle bits
421     BIT     #UF10,T                 \ repeated RC5_command ?
422     0= ?GOTO FW2                    \ yes, RETI without UF10 change and without action !
423     XOR #UF10,0(RSP)                \ 5 toggle bit memory
424 \   ********************************\
425 \   Display IR_RC5 code             \
426 \   ********************************\
427     SUB #6,PSP                      \   -- x x x TOS
428     MOV TOS,4(PSP)                  \   -- TOS x x TOS
429     MOV &BASEADR,2(PSP)             \   -- TOS Base x TOS
430     MOV #$10,&BASEADR               \                               set hexadecimal base
431     MOV X,0(PSP)                    \   -- TOS Base RC5_code TOS    convert number to ascii low word = RC5 byte
432     MOV #0,TOS                      \   -- TOS Base RC5_code 0      convert double number to ascii
433     LO2HI                           \                               switch from assembler to FORTH
434     LCD_CLEAR                       \                               set LCD cursor at home
435     <# # #S #36 HOLD #>             \   -- TOS Base adr cnt         32 bits conversion as "$xx"
436     ['] LCD_WRC IS EMIT             \                               redirect EMIT to LCD
437     TYPE                            \   -- TOS Base                 display "$xx" on LCD
438     ['] EMIT >BODY IS EMIT          \                               restore EMIT
439     HI2LO                           \                               switch from FORTH to assembler
440     MOV @PSP+,&BASEADR              \   -- TOS                      restore current BASE
441     MOV @PSP+,TOS                   \   --
442 FW1 BIC #$30,&RC5_TIM_CTL           \ stop timer (case of truncated RC5 message)
443 FW2 BIC #%1111_1000,0(RSP)          \ force CPU Active Mode and disable GIE in saved SR
444     RETI                            \
445     ENDCODE                         \
446 \   ********************************\
447
448 \ define our STOP_APP
449 \ ----------------------------------\
450     HDNCODE STOP_R2L                \ called by STOP|INIT_R2L|{RC5TOLCD}
451 \ ----------------------------------\
452     CMP #WDT_INT,&WDT_TIM_0_VEC     \ value set by START
453     0= IF                           \ only if START is done
454         BIC.B #RC5,&IR_IE           \ clear I/O RC5_Int
455         BIC.B #RC5,&IR_IFG          \ clear I/O RC5_Int flag
456         MOV #0,&LCD_TIM_CTL         \ stop LCD_TIMER, clear LCD_TIMER IFG
457         MOV #0,&WDT_TIM_CTL         \ stop WDT_TIMER
458         MOV #0,&WDT_TIM_CCTL0       \ clear CCIFG0 disable CCIE0
459         MOV #{RC5TOLCD},W           \
460         MOV #RET_ADR,-2(W)          \ clear MARKER_DOES call
461         KERNEL_ADDON $3C00 TSTBIT   \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
462         [IF]
463         MOV @W+,&UART_WARM+2        \ restore previous ini_APP
464         [ELSE]
465         MOV @W+,&I2C_WARM+2         \ restore previous ini_APP
466         [THEN]
467         MOV @W+,&WDT_TIM_0_VEC      \ restore Vector previous value
468         MOV @W+,&IR_VEC             \ restore Vector previous value
469     THEN
470     MOV @RSP+,PC                    \ RET to STOP|WARM+4|{RC5TOLCD}
471     ENDCODE
472 \ ----------------------------------\
473
474 \ ----------------------------------\
475     CODE STOP                       \ also called by INIT_R2L for some events
476 \ ----------------------------------\
477 BW1 CALL #STOP_R2L
478     COLON                           \
479     ECHO                            \
480     ." type START to start RC5toLCD"
481     ;
482 \ ----------------------------------\
483
484 \ this routine completes the INIT_HARD of FORTH, with INIT_HARD for this app.
485 \ ----------------------------------\
486     HDNCODE INIT_R2L                \ called by START|SYS
487 \ ----------------------------------\
488 \ LCD_TIM_CTL =  %0000 0010 1001 0100\$3C0
489 \                    - -             \CNTL Counter lentgh \ 00 = 16 bits
490 \                        --          \TBSSEL TimerB clock select \ 10 = SMCLK
491 \                           --       \ID input divider \ 10 = /4
492 \                             --     \MC Mode Control \ 01 = up to LCD_TIM_CCR0
493 \                                 -  \TBCLR TimerB Clear
494 \                                  - \TBIE
495 \                                   -\TBIFG
496 \ ----------------------------------\
497 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
498 \                  --                 \CM Capture Mode
499 \                    --               \CCIS
500 \                       -             \SCS
501 \                        --           \CLLD
502 \                          -          \CAP
503 \                            ---      \OUTMOD \ 011 = set/reset
504 \                               -     \CCIE
505 \                                 -   \CCI
506 \                                  -  \OUT
507 \                                   - \COV
508 \                                    -\CCIFG
509 \ ----------------------------------\
510 \ LCD_TIM_CCRx                      \
511 \ ----------------------------------\
512 \ LCD_TIM_EX0                       \
513 \ ----------------------------------\
514 \ set LCD_TIM_ to make 50kHz PWM    \ for LCD_Vo; works without interrupt
515 \ ----------------------------------\
516     MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int, set IFG
517 \    MOV #0,&RC5_TIM_EX0             \ predivide by 1 in RC5_TIM_EX0 register, reset value
518 \    MOV #0,&LCD_TIM_EX0             \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
519     FREQ_KHZ @ 16000 =
520     [IF]                            \ if 16 MHz
521         MOV #1,&RC5_TIM_EX0         \ predivide by 2 in RC5_TIM_EX0 register
522         MOV #1,&LCD_TIM_EX0         \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
523     [THEN]
524     FREQ_KHZ @ 24000 =
525     [IF]                            \ if 24 MHz
526         MOV #2,&RC5_TIM_EX0         \ predivide by 3 in RC5_TIM_EX0 register
527         MOV #2,&LCD_TIM_EX0         \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
528     [THEN]
529         MOV #19,&LCD_TIM_CCR0       \ 19+1=20*1us=20us
530 \ ----------------------------------\
531 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
532 \ ----------------------------------\
533     MOV #%0110_0000,&LCD_TIM_CCTLn  \ output mode = set/reset \ clear CCIFG
534     MOV #10,&LCD_TIM_CCRn           \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
535 \    MOV #12,&LCD_TIM_CCRn           \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
536 \ ----------------------------------\
537     BIS.B #LCDVo,&LCDVo_DIR         \
538     BIS.B #LCDVo,&LCDVo_SEL         \ SEL.2
539 \ ----------------------------------\
540     BIS.B #LCD_CMD,&LCD_CMD_DIR     \ lcd_cmd as outputs
541     BIC.B #LCD_CMD,&LCD_CMD_REN     \ lcd_cmd pullup/down disable
542 \ ----------------------------------\
543     BIS.B #LCD_DB,&LCD_DB_DIR       \ as output, wired to DB(4-7) LCD_Data
544     BIC.B #LCD_DB,&LCD_DB_REN       \ LCD_Data pullup/down disable
545 \ ----------------------------------\
546 \ init RC5_Int                      \
547 \ ----------------------------------\
548     BIS.B #RC5,&IR_IE               \ enable RC5_Int
549     BIC.B #RC5,&IR_IFG              \ reset RC5_Int flag
550 \ ----------------------------------\
551 \ init WatchDog WDT_TIM_            \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
552 \ ----------------------------------\
553 \              %01 0001 0100        \ TAxCTL
554 \               --                  \ TASSEL    CLK = ACLK = LFXT = 32768 Hz
555 \                  --               \ ID        divided by 1
556 \                    --             \ MC        MODE = up to TAxCCRn
557 \                        -          \ TACLR     clear timer count
558 \                         -         \ TAIE
559 \                          -        \ TAIFG
560 \ ----------------------------------\
561     MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
562 \ ----------------------------------\
563 \                        000        \ TAxEX0
564 \                        ---        \ TAIDEX    pre divisor
565 \ ----------------------------------\
566 \          %0000 0000 0000 0101     \ TAxCCR0
567     MOV ##3276,&WDT_TIM_CCR0        \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
568 \ ----------------------------------\
569 \          %0000 0000 0001 0000     \ TAxCCTL0
570 \                   -               \ CAP capture/compare mode = compare
571 \                        -          \ CCIEn
572 \                             -     \ CCIFGn
573     MOV #%10000,&WDT_TIM_CCTL0      \ enable compare interrupt, clear CCIFG0
574 \ ----------------------------------\
575 \ activate I/O                      \
576 \ ----------------------------------\
577     CALL &{RC5TOLCD}                \ run previous INIT_HARD_APP
578 \ ----------------------------------\
579 \ RESET events handling             \ search "SYSRSTIV" in your MSP430FRxxxx datasheet to get listing
580 \ ----------------------------------\
581     CMP #$0E,TOS                    \ SYSRSTIV = SVSHIFG SVSH event ?
582     0<> IF                          \ if not
583         CMP #$0A,TOS                \   SYSRSTIV >= violation memory protected areas | USERSYS <0 = DEEP_RESET request ?
584         U>= ?GOTO BW1               \   if yes execute STOP_R2L then RET to BODY of WARM
585     THEN                            \
586 \    CMP #2,TOS                      \   Power_ON event
587 \    0= ?GOTO BW1                    \   uncomment if you want to loose application in this case...
588     CMP #4,TOS                      \   SYSRSTIV|USERSYS RST ?
589     0= ?GOTO BW1                    \   if yes run STOP.
590 \    CMP #$0E,TOS                    \   SYSRSTIV = SVSHIFG SVSH event ?
591 \    0= ?GOTO BW1                    \   SVSHIFG SVSH event performs STOP
592 \ ----------------------------------\
593     LO2HI                           \
594 \ ----------------------------------\
595 \   Init LCD 2x20                   \
596 \ ----------------------------------\
597     #1000 20_US                     \ 1- wait 20 ms
598     %011 TOP_LCD                    \ 2- send DB5=DB4=1
599     #205 20_US                      \ 3- wait 4,1 ms
600     %011 TOP_LCD                    \ 4- send again DB5=DB4=1
601     #5 20_US                        \ 5- wait 0,1 ms
602     %011 TOP_LCD                    \ 6- send again again DB5=DB4=1
603     #2 20_US                        \    wait 40 us = LCD cycle
604     %010 TOP_LCD                    \ 7- send DB5=1 DB4=0
605     #2 20_US                        \    wait 40 us = LCD cycle
606     %00101000 LCD_WRF               \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
607     %1000 LCD_WRF                   \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off.
608     LCD_CLEAR                       \ 10- "LCD_Clear"
609     %0110 LCD_WRF                   \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
610     %1100 LCD_WRF                   \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
611     LCD_CLEAR                       \ 10- "LCD_Clear"
612     HI2LO                           \
613     MOV @RSP+,PC                    \ RET to WARM|START
614     ENDCODE
615 \ ----------------------------------\
616
617 \ ----------------------------------\
618     CODE START                      \ this routine replaces INT_HARD_APP default values by these of this application.
619 \ ----------------------------------\
620     CMP #WDT_INT,&WDT_TIM_0_VEC     \ value set by START
621     0= IF                           \
622         MOV @IP+,PC                 \ does nothing if already initialised
623     THEN
624     MOV #STOP_R2L,&{RC5TOLCD}-2     \ execution of {RC5TOLCD} will perform STOP_R2L.
625     KERNEL_ADDON $3C00 TSTBIT       \ BIT13|BIT12|BIT11|BIT10 test (UART TERMINAL test)
626     [IF]
627        MOV &UART_WARM+2,&{RC5TOLCD} \ save previous INI_APP subroutine
628        MOV #INIT_R2L,&UART_WARM+2   \ replace it by RC5toLCD INI_APP
629     [ELSE]
630        MOV &I2C_WARM+2,&{RC5TOLCD}  \ save previous INI_APP subroutine
631        MOV #INIT_R2L,&I2C_WARM+2    \ replace it by RC5toLCD INI_APP
632     [THEN]
633     MOV &WDT_TIM_0_VEC,&{RC5TOLCD}+2 \ save Vector previous value
634     MOV #WDT_INT,&WDT_TIM_0_VEC     \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
635     MOV &IR_VEC,&{RC5TOLCD}+4       \ save Vector previous value
636     MOV #RC5_INT,&IR_VEC            \ init interrupt vector
637 \ ----------------------------------\
638 \   init 20 us count loop           \ see 20_US
639 \ ----------------------------------\ -- TOS
640     SUB #6,PSP                      \ -- x x x TOS
641     MOV TOS,4(PSP)                  \ -- TOS x x TOS
642     MOV &FREQ_KHZ,2(PSP)            \ -- TOS DVDlo x TOS
643     MOV #0,0(PSP)                   \ -- TOS DVDlo DVDhi TOS
644     MOV #200,TOS                    \ -- TOS DVDlo DVDhi DIVlo
645     CALL #MUSMOD                    \ -- TOS REMlo QUOTlo QUOThi
646     MOV @PSP,&{RC5TOLCD}+6          \                       set count+2 for 20_US
647     ADD #4,PSP                      \ -- TOS QUOThi
648     MOV @PSP+,TOS                   \ -- TOS
649 \ ----------------------------------\
650     CALL #INIT_R2L                  \ run new INIT_HARD_APP
651     LO2HI
652 \    ['] LCD_HOME IS CR              \ ' CR redirected to LCD_HOME
653 \    ['] LCD_WRC  IS EMIT            \ ' EMIT redirected to LCD_WrC
654 \    CR ." I love you"               \ display message on LCD
655 \    ['] CR >BODY IS CR              \ CR executes its default value
656 \    ['] EMIT >BODY IS EMIT          \ EMIT executes its defaulte value
657     ." RC5toLCD is running,"        \
658     ."  Type STOP to quit."         \ display message on FastForth Terminal
659     HI2LO
660     MOV #ABORT,PC                   \ goto FORTH interpreter without WARM message.
661     ENDCODE                         \
662 \ ----------------------------------\
663
664 RST_SET
665 ECHO
666
667 \ START