OSDN Git Service

bug bug bug...
[fast-forth/master.git] / MSP430-FORTH / lib / I2C_Slave_to_LCD_2x20.f
1 \ name : I2C_Slave_to_LCD_2x20.f
2
3 \ Copyright (C) <2015>  <J.M. THOORENS>
4 \
5 \ This program is free software: you can redistribute it and/or modify
6 \ it under the terms of the GNU General Public License as published by
7 \ the Free Software Foundation, either version 3 of the License, or
8 \ (at your option) any later version.
9 \
10 \ This program is distributed in the hope that it will be useful,
11 \ but WITHOUT ANY WARRANTY\ without even the implied warranty of
12 \ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 \ GNU General Public License for more details.
14 \
15 \ You should have received a copy of the GNU General Public License
16 \ along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 \
18
19 \ --------------------------------------\
20 \ example of App running under interrupt
21 \ --------------------------------------\
22
23 \ for MSP_EXP430FR5739, MSP_EXP430FR5969, MSP_EXP430FR6989, ... launchpads @ 8MHz
24
25 \ prerequisites : your launchpad is wired as described in launchpad.pat file : UART0, SDA, SCL, LCD parts
26 \                 and FastForth runs @ 8MHz
27 \ usage :   create a logical network drive ( a: b: as you want) from your local copy of Gitlab FAST FORTH
28 \           with scite.exe open this file MSP430-FORTH\I2C_Slave_to_LCD_2x20.f,
29 \           select "tools" menu, "preprocess" item 2 (CTRL+1),
30 \           a dialog box asks you for 4 parameters $(1) to $(4),
31 \           in the 2th param. field, type your launchpad to select the launchpad.pat to be used : for example MSP_EXP430FR5969,
32 \           in the 3th param. field, type the COMx port of your USBtoUART device.
33 \ result :  a file.4th in which all symbolic addresses are resolved according to the rules described in the selected launchpad.pat
34 \           the word START starts the app that runs under LPMx.
35 \           to recover the console input (i.e. to quit LPMx), type a space. Then you can enter a command, for example STOP.
36
37 WIPE
38     \
39
40 : U.R           \ u n --           display u unsigned in n width
41   >R  <# 0 # #S #>  
42   R> OVER - 0 MAX SPACES TYPE
43 ;
44     \
45
46 CODE ?          \ adr --           display the content of adr
47     MOV @TOS,TOS
48     MOV #U.,PC
49 ENDCODE
50     \
51
52
53 \ ------------------------------\
54 CODE 20_us                      \ n --      n * 20 us
55 \ ------------------------------\
56 BEGIN                           \ 3 cycles loop + 6~  
57 \    MOV     #5,W                \ 3 MCLK = 1 MHz
58 \    MOV     #23,W               \ 3 MCLK = 4 MHz
59     MOV     #51,W               \ 3 MCLK = 8 MHz
60 \    MOV     #104,W              \ 3 MCLK = 16 MHz
61 \    MOV     #158,W              \ 3 MCLK = 24 MHz
62     BEGIN                       \ 3 cycles loop ==> 3 * W / F us = 100 us - 1 @ 8 MHz
63         SUB #1,W                \ 1
64     0= UNTIL                    \ 2
65     SUB     #1,TOS              \ 1
66 0= UNTIL                        \ 2
67     MOV     @PSP+,TOS           \ 2
68     MOV     @IP+,PC             \ 4
69 ENDCODE
70     \
71 \ ------------------------------\
72 CODE TOP_LCD                    \ LCD Sample
73 \ ------------------------------\ if write : %xxxxWWWW --
74 \                               \ if read  : -- %0000RRRR
75     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
76     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
77 0= IF                           \ write LCD bits pattern
78     AND #LCD_DB,TOS             \ 
79     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
80     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
81     MOV @PSP+,TOS               \
82     MOV @IP+,PC
83 THEN                            \ read LCD bits pattern
84     SUB #2,PSP
85     MOV TOS,0(PSP)
86     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
87     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
88     AND.B #LCD_DB,TOS           \
89     MOV @IP+,PC
90 ENDCODE
91     \
92 \ ------------------------------\
93 CODE LCD_W                      \ byte --       write byte 
94 \ ------------------------------\
95     SUB #2,PSP                  \
96     MOV TOS,0(PSP)              \ -- %xxxxLLLL %HHHHLLLL
97     RRUM #4,TOS                 \ -- %xxxxLLLL %xxxxHHHH
98     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
99     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
100     COLON
101     TOP_LCD 2 20_us             \ write high nibble first
102     TOP_LCD 2 20_us ;
103     \
104 \ ------------------------------\
105 CODE LCD_R                      \ -- byte       read byte
106 \ ------------------------------\
107     BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
108     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
109     COLON
110     TOP_LCD 2 20_us             \ read high nibble first
111     TOP_LCD 2 20_us
112     HI2LO                       \ -- %0000HHHH %0000LLLL
113     MOV @RSP+,IP
114     MOV @PSP+,W                 \ W = high nibble
115     RLAM #4,W                   \ -- %0000LLLL     W = %HHHH0000 
116     ADD.B W,TOS
117     MOV @IP+,PC
118 ENDCODE
119     \
120 \ ------------------------------\
121 CODE LCD_WrF                    \ func --         Write Fonction
122 \ ------------------------------\
123     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
124     JMP LCD_W
125 ENDCODE
126     \
127 \ ------------------------------\
128 CODE LCD_RdS                    \ -- status       Read Status
129 \ ------------------------------\
130     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
131     JMP LCD_R
132 ENDCODE
133     \
134 \ ------------------------------\
135 CODE LCD_WrC                    \ char --         Write Char
136 \ ------------------------------\
137     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
138     JMP LCD_W
139 ENDCODE
140     \
141 \ ------------------------------\
142 CODE LCD_RdC                    \ -- char         Read Char
143 \ ------------------------------\
144     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
145     JMP LCD_R
146 ENDCODE
147     \
148 \ ------------------------------\
149 \  : LCD_Clear $01 LCD_WrF 80 20_us \ bad init !
150 : LCD_Clear $01 LCD_WrF 100 20_us ;
151     \
152 \ ------------------------------\
153 : LCD_Home $02 LCD_WrF 80 20_us ;
154     \
155 \ ------------------------------\
156 \ : LCD_Entry_set       $04 OR LCD_WrF ;
157 \ : LCD_Display_Ctrl    $08 OR LCD_WrF ;
158 \ : LCD_Display_Shift   $10 OR LCD_WrF ;
159 \ : LCD_Fn_Set          $20 OR LCD_WrF ;
160 \ : LCD_CGRAM_Set       $40 OR LCD_WrF ;
161 \ : LCD_Goto            $80 OR LCD_WrF ;
162
163 \ -------------+------+------+------+------++---+---+---+---+---------+
164 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
165 \ -------------+------+------+------+------++---+---+---+---+---------+
166 \ LPM0 = $18  |  0   |  0   |  0   |  1   || 1 | x | x | x |  180uA  | default mode
167 \ LPM1 = $58  |  0   |  1   |  0   |  1   || 1 | x | x | x |         | same mode as LPM0
168 \ LPM2 = $98  |  1   |  0   |  0   |  1   || 1 | x | x | x |   60uA  |
169 \ LPM3 = $D8  |  1   |  1   |  0   |  1   || 1 | x | x | x |   10uA  | 32768Hz XTAL is running
170 \ LPM4 = $F8  |  1   |  1   |  1   |  1   || 1 | x | x | x |    6uA  |
171 \ -------------+------+------+------+------++---+---+---+---+---------+
172
173 \ ******************************\
174 ASM WDT_Int                     \ Watchdog interrupt routine, warning : not FORTH executable !
175 \ ******************************\
176 \ ------------------------------\
177 \ define LPM mode for ACCEPT    \ LPM0 is the default mode.
178 \ ------------------------------\
179 \ MOV #LPM4,&LPM_MODE             \ with MSP430FR59xx
180 \ MOV #LPM2,&LPM_MODE             \ with MSP430FR57xx, terminal input don't work for LPMx > 2
181 \                                 \ with MSP430FR2xxx, terminal input don't work for LPMx > 0
182 \ ------------------------------\
183 BIT.B #SW2,&SW2_IN              \ test switch S2
184 0= IF                           \ case of switch S2 pressed
185   CMP #34,&TB0CCR2              \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
186   U< IF
187     ADD #1,&TB0CCR2             \ action for switch S2 (P2.5) : 78 mV / increment
188   THEN
189 ELSE
190     BIT.B #SW1,&SW1_IN          \ test switch S1 input
191     0= IF                       \ case of Switch S1 pressed
192         CMP #7,&TB0CCR2         \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
193         U>= IF                  \
194         SUB #1,&TB0CCR2         \ action for switch S1 (P2.6) : -78 mV / decrement
195         THEN                    \
196     THEN                        \
197 THEN                            \
198 BIC #WDTIFG,&SFRIFG1            \ reset WDT_INT flag
199 BIC #$F8,0(RSP)                 \ set CPU ON and GIE OFF in retiSR
200 RETI                            \ CPU is ON, GIE is OFF
201 ENDASM                          \
202     \
203
204
205
206 VARIABLE I2CS_OWN       \ slave I2C address without RW flag (low byte) + DATA0 input (HIGH byte)
207 \ 2 ALLOT               \ next the low byte of I2CS_OWN word, it is the input buffer
208 VARIABLE I2CS_BUF       \ buffer output, lentgh (low byte),DATA0 output (HIGH byte)
209 \ 2 ALLOT               \ this byte lentgh is shared by input and output buffers
210
211 \ ******************************\
212 ASM I2CS_TX                     \ TX part of I2C_Slave
213 \ ******************************\
214 \                               \       T = TX buffer_org
215 \                               \ use   W = TX buffer_ptr
216 \                               \ out : low(I2CS_BUF) = RX or TX lentgh
217 \ ------------------------------\
218 MOV T,W                         \ W = TX_buf_ptr -1
219 BEGIN                           \
220     ADD #1,W                    \ first reserve one byte for length then inc
221     MOV.B @W,&UCB0TXBUF         \ +[W] --> UCB0TXBUF
222 \   ----------------------------\
223 \   slave send byte             \
224 \   ----------------------------\
225     BEGIN                       \
226         BIT #$0C,&UCB0IFG       \ UCB0IFG(STP,STT) = 1 ?
227         0<> IF                  \
228 \           --------------------\
229 \           stop or restart received
230 \           --------------------\
231             SUB   T,W           \
232             SUB.B #1,W          \ sub #1, because char +[W] is not sent
233             MOV.B W,0(T)        \ store length in first byte of buffer output
234             BIC #UCTR,&UCB0CTLW0  \ reset UCTR R/W bit for next START
235             MOV @RSP+,PC        \ ===> ret
236 \           --------------------\
237         THEN                    \
238         BIT #2,&UCB0IFG         \ UCB0IFG(TX0) = 1 ?
239     0<> UNTIL                   \
240 AGAIN                           \
241 ENDASM                          \
242     \
243
244 \ -------------+------+------+------+------++---+---+---+---+---------+
245 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
246 \ -------------+------+------+------+------++---+---+---+---+---------+
247 \ LPM0 = $18  |  0   |  0   |  0   |  1   || 1 | x | x | x |  180uA  | default mode
248 \ LPM1 = $58  |  0   |  1   |  0   |  1   || 1 | x | x | x |         | same mode as LPM0
249 \ LPM2 = $98  |  1   |  0   |  0   |  1   || 1 | x | x | x |   60uA  |
250 \ LPM3 = $D8  |  1   |  1   |  0   |  1   || 1 | x | x | x |   10uA  | 32768Hz XTAL is running
251 \ LPM4 = $F8  |  1   |  1   |  1   |  1   || 1 | x | x | x |    6uA  |
252 \ -------------+------+------+------+------++---+---+---+---+---------+
253
254 \ **************************************\
255 ASM I2C_S                               \ <== eUSCIB0 interrupt vector : i2c_addres&R/w sent by master is received
256 \ **************************************\
257 BIC #$F8,0(RSP)                         \ SCG1,SCG0,OSCOFF,CPUOFF and GIE are OFF in retiSR to force LPM0_LOOP with pending interrupt
258 \ --------------------------------------\
259 \ define LPM mode for ACCEPT            \ LPM0 is the default mode.
260 \ --------------------------------------\
261 \ MOV #LPM4,&LPM_MODE                     \ MSP430FR59xx family : LPM 0 to 4
262 \ MOV #LPM2,&LPM_MODE                     \ MSP430FR57xx family : terminal input don't work for LPMx > 2
263 \                                         \ MSP430FR2xxx family : terminal input don't work for LPMx > 0
264 \ --------------------------------------\
265 MOV #I2CS_BUF,T                         \ T = buffer output address -1
266 MOV #I2CS_OWN,S                         \ S = buffer input address -1
267 MOV #0,&UCB0IFG                         \ write UCB0IFG to clear all int flags (STTIFG,TXIFG,..)
268 CMP.B &UCB0I2COA0,&UCB0ADDRX            \ UCB0ADDRX = own address ?
269 0= IF                                   \ 
270     BIS #UCTXACK,&UCB0CTLW0             \ send software Ack address
271     BIT #UCTR,&UCB0CTLW0                \ test UCB0CTLW0(UCTR) R/W bit
272     0= IF                               \ I2C_Master Write
273 \       --------------------------------\
274 \       slave receive datas             \ yes
275 \       --------------------------------\
276         MOV S,W                         \ W = input buffer address - 1
277         BEGIN                           \
278 \           ----------------------------\
279 \           slave receive one byte      \
280 \           ----------------------------\
281             BEGIN                       \
282                 BIT #$8C,&UCB0IFG       \ UCB0IFG(STP,STT,CLTO) = 1 ? (STOP, START, SCL low timeout)
283                 0<> IF                  \
284 \                   --------------------\
285 \                   TX stop or restart  \ from master
286 \                   --------------------\
287                     SUB   S,W           \ W = Adr_end - Adr_start = length
288                     MOV.B W,0(T)        \ store length in first byte of buffer output
289 \                   --------------------\
290 \                   insert here post RX code
291 \                   --------------------\
292 \                    BIS.B #LED1,&LED1_OUT   \ OUT high ==> switch ON LED1 to test
293 \                   display IR_RC5 command
294                     SUB   #2,PSP        \
295                     MOV   TOS,0(PSP)    \
296                     MOV.B 1(X),TOS      \ display RC6 command
297 \                   MOV.B 0(W),TOS       \ display count
298                     LO2HI               \ IP is free
299                     ['] LCD_Clear IS CR
300                     ['] LCD_WrC  IS EMIT
301                     BASE @ HEX          \ save BASE before change
302                     CR ." $" 2 U.R SPACE \ display received byte
303                     ." LPM = $" LPM_MODE ? \ display also LPM value
304                     ['] (CR) IS CR
305                     ['] (EMIT) IS EMIT
306                     BASE !              \ restore BASE
307                     HI2LO               \ nice code, right ?
308 \                   ; endof display
309 \                    BIC.B #LED1,&LED1_OUT   \ OUT low ==> switch OFF LED1 to test
310 \                   --------------------\
311                     RETI                \
312 \                   --------------------\
313                 THEN                    \ if not (stop, restart, CLTO)
314                 BIT #1,&UCB0IFG         \ UCB0IFG(RX0) = 1 ?
315             0<> UNTIL                   \ 
316             ADD #1,W                    \ reserve one byte for length first, then preincrement
317             MOV.B &UCB0RXBUF,0(W)       \ [UCB0RXBUF] = data --> +[W]
318         AGAIN                           \ loop for new received data if any
319     THEN                                \ end of I2C_Master read
320 \   ------------------------------------\
321 \   slave transmit datas variant 1      \ to loop back after bad_own_address code
322 \   ------------------------------------\
323     CALL #I2CS_TX                       \ 
324     RETI                                \
325 \   ------------------------------------\
326 \   slave transmit datas variant 2      \
327 \   ------------------------------------\
328 \         MOV T,W                         \ W = output buffer address -1
329 \         BEGIN                           \
330 \             ADD     #1,W                \ first reserve one byte for length
331 \             MOV.B   @W,&UCB0TXBUF       \ +[W] --> UCB0TXBUF
332 \ \           ----------------------------\
333 \ \           slave send byte             \
334 \ \           ----------------------------\
335 \             BEGIN                       \
336 \                 BIT.B #$0C,&UCB0IFG     \ UCB0IFG(STP,STT) = 1 ?
337 \                 0<> IF                  \
338 \ \               ------------------------\
339 \ \               RX stop or restart      \ from master
340 \ \               ------------------------\
341 \                     SUB   T,W           \ W = Adr_end - Adr_start = length
342 \                     SUB.B #1,W          \ sub #1, because char +[W] is not sent
343 \                     MOV.B W,0(T)        \ store length in first byte of buffer output
344 \                     BIC.B #UCTR,&UCB0CTLW0  \ reset UCTR R/W bit for next START
345 \                     RETI                \
346 \                 THEN                    \
347 \                 BIT.B #$02,&UCB0IFG    \ UCB0IFG(TX0) = 1 ?
348 \             0<> UNTIL                   \
349 \         AGAIN                           \
350 \   ------------------------------------\
351 \   End of slave transmit datas variants\
352 \   ------------------------------------\
353 THEN                                    \ if bad I2C address
354 \ --------------------------------------\
355 \ BAD I2C ADDRESS CaseOf                \
356 \ --------------------------------------\
357 \ insert here post BAD I2C address code \
358 \ ...that can loop back to I2CS_TX...   \
359 \ --------------------------------------\
360 BIC #UCTXACK,&UCB0CTLW0                 \ send Nack address
361 RETI                                    \
362 ENDASM
363     \
364
365
366
367
368 \ START performs a complementary initialisation of the FAST FORTH system to start your app.
369 \ START is inserted COLD and ABORT via the fragment of code : LIT RECURSE IS WARM.
370 \ --------------------------------------\
371 CODE START                              \ init I2C_slave 
372 \ --------------------------------------\
373 \ %0000 0111 1100 0001     UCB0CTLW0
374 \        -                  UCMST       = 0 : I2C_Slave
375 \         --                UCMODE      = %11 = I2C
376 \           _               USYNC       =1 (always 1)
377 \             --            UCSSEL      =SMCLK (don't care in slave mode)
378 \               -           UCTXACK     =0 not auto ACK slave address
379 \                -          UCTR        =0 : RX (for RX address)
380 \                     -     UCSWRST     =1
381 \ --------------------------------------\
382 \ %0000 0000 1101 0000     UCB0CTLW1
383 \           -               UCETXINT    =0 : UCTXIFG0 set address match UCxI2COAx and TX mode
384 \             --            UCCLTO      =%11 : SCL low time out = 34 ms
385 \                -          UCSWACK     =1 : UCTXACK must be written to continue
386 \ --------------------------------------\
387 \                           UCB0RXBUF
388 \                           UCB0TXBUF
389 \                           UCB0I2COA0 must be written ? enabled ?
390 \                           UCB0ADDRX
391 \                           UCB0ADDMSK
392 \ --------------------------------------\
393 \ %0000 0000 0000 0100     UCB0IE
394 \                   -       UCSTTIE : StartCond Interrupt only
395 \ --------------------------------------\
396 \                           UCB0IFG
397 \                           UCB0IV : write it to clear all IFG 
398
399 \ ------------------------------\
400 \ init I2C_slave                \
401 \ ------------------------------\
402 MOV #1,&UCB0CTLW0               \ set eUSCI_B in reset state, clear UCB0IE & UCB0IFG all flags
403 BIS #$07A0,&UCB0CTLW0           \
404 BIS #$10,&UCB0CTLW1             \ set software ack address (UCSWACK=1)
405 MOV #%1010,&UCB0I2COA0          \ set my own address
406 BIS #$0400,&UCB0I2COA0          \ UCOAEN=1 enable UCB0I2COA0 with address slave
407 \ MOV #0,&UCB0ADDMSK              \ enable address mask for all addresses i.e. software address 
408 BIC #1,&UCB0CTLW0               \ activate eUSCI_B
409 MOV #4,&UCB0IE                  \ enable StartCond interrupt
410 MOV #%1010,&I2CS_OWN            \ my slave address, without RW flag !
411 \ ------------------------------\
412 \ init PORT complement
413 \ ------------------------------\
414 \ notice : UCB0 I2C driver seems to control only DIR register !!!
415 BIC.B #S_BUS,&I2CS_REN          \ SDA + SCL pullup/down disable
416 BIC.B #S_BUS,&I2CS_OUT          \ OUT0 : preset output low
417 BIS.B #S_BUS,&I2CS_SEL1         \ enable I2C I/O
418 \ ------------------------------\
419 BIS.B #LCDVo,&LCDVo_DIR         \
420 BIS.B #LCDVo,&LCDVo_SEL0        \ TB0.2
421 \ ------------------------------\
422 BIS.B #LCD_CMD,&LCD_CMD_DIR     \ lcd_cmd as outputs
423 BIC.B #LCD_CMD,&LCD_CMD_REN     \ lcd_cmd pullup/down disable
424 \ ------------------------------\
425 BIS.B   #LCD_DB,&LCD_DB_DIR     \ lcd_db as output, wired to DB(4-7) LCD_Data
426 BIC.B   #LCD_DB,&LCD_DB_REN     \ lcd_db pullup/down disable
427 \ ------------------------------\
428 \ TB0CTL = %0000 0010 1001 0100\$3C0
429 \               - -             \CNTL Counter lentgh \ 00 = 16 bits
430 \                   --          \TBSSEL TimerB clock select \ 10 = SMCLK
431 \                      --       \ID input divider \ 10 = /4
432 \                        --     \MC Mode Control \ 01 = up mode
433 \                            -  \TBCLR TimerB Clear
434 \                             - \TBIE
435 \                              -\TBIFG
436 \ --------------------------------\\
437 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
438 \              --                 \CM Capture Mode
439 \                --               \CCIS
440 \                   -             \SCS
441 \                    --           \CLLD
442 \                      -          \CAP
443 \                        ---      \OUTMOD \ 011 = set/reset
444 \                           -     \CCIE
445 \                             -   \CCI
446 \                              -  \OUT
447 \                               - \COV
448 \                                -\CCIFG
449 \ TB0CCRx                         \$3D{2,4,6,8,A,C,E}
450 \ TB0EX0                          \$3E0 
451 \ ------------------------------\
452 \ set TimerB to make 50kHz PWM  \
453 \ ------------------------------\
454 \    MOV #%1000010100,&TB0CTL  \ SMCLK/1, up mode, clear timer, no int
455 \    MOV #0,&TB0EX0             \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
456 \ ------------------------------\
457 \    MOV #%1000010100,&TB0CTL  \ SMCLK/1, up mode, clear timer, no int
458 \    MOV #1,&TB0EX0             \ predivide by 2 in TB0EX0 register (4 MHZ)
459 \ ------------------------------\
460     MOV #%1010010100,&TB0CTL    \ SMCLK/4, up mode, clear timer, no int
461     MOV #0,&TB0EX0              \ predivide by 1 in TB0EX0 register (8 MHZ)
462 \ ------------------------------\
463 \    MOV #%1010010100,&TB0CTL  \ SMCLK/4, up mode, clear timer, no int
464 \    MOV #1,&TB0EX0             \ predivide by 2 in TB0EX0 register (16 MHZ)
465 \ ------------------------------\
466 \    MOV #%1010010100,&TB0CTL  \ SMCLK/4, up mode, clear timer, no int
467 \    MOV #2,&TB0EX0             \ predivide by 3 in TB0EX0 register (24 MHZ)
468 \ ------------------------------\
469     MOV #40,&TB0CCR0            \ 40*0.5us=20us (40us @ 1MHz)
470 \ ------------------------------\
471 \ set TimerB to generate LCD_V0 via TB0.2 and P1.5/P2.2
472 \ ------------------------------\
473     MOV #%1100000,&TB0CCTL2     \ output mode = set/reset \ clear CCIFG
474 \    MOV #20,&TB0CCR2           \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
475     MOV #25,&TB0CCR2            \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
476 \ ------------------------------\
477 \ WDT interval init part        \
478 \ ------------------------------\
479 \    MOV #$5A5E,&WDTCTL         \ init WDT Vloclk source 10kHz /2^9 (50 ms), interval mode
480     MOV #$5A3D,&WDTCTL          \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
481 \    MOV #$5A5D,&WDTCTL         \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
482     BIS #1,&SFRIE1              \ enable WDT interval mode interrupt in SFRIE
483 \ ------------------------------\
484 \ init interrupt vectors
485 \ ------------------------------\
486     MOV #I2C_S,&I2CS_Vec        \ eUSCIB0 interrupt vector
487     MOV #WDT_Int,&WDT_Vec       \ init WDT interval vector interrupt
488 \ ------------------------------\
489 \ define LPM mode for ACCEPT    \ LPM0 is the default mode.
490 \ ------------------------------\
491 \ MOV #LPM4,&LPM_MODE             \ with MSP430FR59xx
492 \ MOV #LPM2,&LPM_MODE             \ with MSP430FR57xx, terminal input don't work for LPMx > 2
493 \                                 \ with MSP430FR2xxx, terminal input don't work for LPMx > 0
494 \ ------------------------------\
495 \ Init LCD
496     COLON
497     $03E8 20_us             \ 1-  wait 20 ms
498     $03 TOP_LCD             \ 2- send DB5=DB4=1
499     $CD 20_us               \ 3- wait 4,1 ms
500     $03 TOP_LCD             \ 4- send again DB5=DB4=1
501     5 20_us                 \ 5- wait 0,1 ms
502     $03 TOP_LCD             \ 6- send again again DB5=DB4=1
503     2 20_us                 \    wait 40 us = LCD cycle
504     $02 TOP_LCD             \ 7- send DB5=1 DB4=0
505     2 20_us                 \    wait 40 us = LCD cycle
506     $28 LCD_WrF             \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
507     $08 LCD_WrF             \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
508     LCD_Clear               \ 10- "LCD_Clear"
509     $06 LCD_WrF             \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
510     $0C LCD_WrF             \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
511
512     ['] LCD_HOME IS CR      \ CR redirected to LCD_HOME
513     ['] LCD_WrC  IS EMIT    \ EMIT redirected to LCD_WrC
514     CR ." I love you"       \ display it on the LCD
515     ['] (EMIT) IS EMIT      \ restore EMIT
516     ['] (CR) IS CR          \ restore CR
517     ." I2C_Slave_to_LCD is running. Type STOP to quit" \ display on terminal
518 \    NOECHO                  \ uncomment to run this app without terminal connexion
519     lit RECURSE IS WARM     \ insert this starting routine between COLD and WARM...
520     (WARM) ;                \ ...and continue with (WARM)
521     \
522
523
524 : STOP                  \ stops multitasking, must to be used before downloading app
525     ['] (WARM) IS WARM  \ remove START app from FORTH init process
526     ECHO COLD           \ reset CPU, interrupt vectors, and start FORTH
527 ;
528     \
529
530 RST_HERE
531
532
533 \ START runs your App. 
534 \ when downloading this file, all lines beyond the START command are ignored. Usefull to comment.
535
536 \ driver for LCD 2x20 characters display with 4 bits data interface 
537 \ without usage of an auxiliary 5V to feed the Vo of LCD
538 \ without potentiometer to adjust the LCD contrast
539 \ LCD contrast software adjustable by 2 switches
540 \ TB0.2 current consumption ~ 500 uA
541     
542 \ layout : see config.pat file for defining I/O
543
544 \  GND  <-------+---0V0---------->  1 LCD_Vss
545 \  VCC  >------ | --3V6-----+---->  2 LCD_Vdd
546 \               |           |
547 \             |___    470n ---
548 \               ^ |        ---
549 \              / \ BAT54    |
550 \              ---          |
551 \          100n |    2k2    |
552 \ TB0.2 >---||--+--^/\/\/v--+---->  3 LCD_Vo (=0V6 without modulation)
553 \       ------------------------->  4 LCD_RW
554 \       ------------------------->  5 LCD_RW
555 \       ------------------------->  6 LCD_EN
556 \       <------------------------> 11 LCD_DB4
557 \       <------------------------> 12 LCD_DB5
558 \       <------------------------> 13 LCD_DB5
559 \       <------------------------> 14 LCD_DB7
560
561 \ Sw1   <--- LCD contrast + (finger :-)
562 \ Sw2   <--- LCD contrast - (finger \-)
563