OSDN Git Service

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