OSDN Git Service

raz
[fast-forth/master.git] / MSP430-FORTH / lib / LCD_2x20.f
1 \ ------------------------------
2 \ MSP430FR5xxx_LCD_20.f
3 \ ------------------------------
4 RST_STATE
5 \ NOECHO
6 \ Copyright (C) <2014>  <J.M. THOORENS>
7 \
8 \ This program is free software: you can redistribute it and/or modify
9 \ it under the terms of the GNU General Public License as published by
10 \ the Free Software Foundation, either version 3 of the License, or
11 \ (at your option) any later version.
12 \
13 \ This program is distributed in the hope that it will be useful,
14 \ but WITHOUT ANY WARRANTY\ without even the implied warranty of
15 \ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 \ GNU General Public License for more details.
17 \
18 \ You should have received a copy of the GNU General Public License
19 \ along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
21
22  
23 \ driver for LCD 2x20 characters display with 4 bits data interface 
24 \ without usage of an auxiliary 5V to feed the Vo of LCD
25 \ without potentiometer to adjust the LCD contrast
26 \ LCD contrast software adjustable by 2 switches
27 \ TB0.2 current consumption ~ 500 uA
28     
29 \ layout : see config.pat file for defining I/O
30
31 \  GND  <-------+---0V0---------->  1 LCD_Vss
32 \  VCC  >------ | --3V6-----+---->  2 LCD_Vdd
33 \               |           |
34 \             |___    470n ---
35 \               ^ |        ---
36 \              / \ BAT54    |
37 \              ---          |
38 \          100n |    2k2    |
39 \ TB0.2 >---||--+--^/\/\/v--+---->  3 LCD_Vo (=0V6 without modulation)
40 \       ------------------------->  4 LCD_RW
41 \       ------------------------->  5 LCD_RW
42 \       ------------------------->  6 LCD_EN
43 \       <------------------------> 11 LCD_DB4
44 \       <------------------------> 12 LCD_DB5
45 \       <------------------------> 13 LCD_DB5
46 \       <------------------------> 14 LCD_DB7
47
48 \ Sw1   <--- LCD contrast + (finger :-)
49 \ Sw2   <--- LCD contrast - (finger \-)
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 \ ------------------------------\
73 CODE TOP_LCD                    \ LCD Sample
74 \ ------------------------------\ if write : %xxxxWWWW --
75 \                               \ if read  : -- %0000RRRR
76     BIS.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 0-->1
77     BIT.B #LCD_RW,&LCD_CMD_IN   \ lcd_rw test
78 0= IF                           \ write LCD bits pattern
79     AND #LCD_DB,TOS             \ 
80     MOV.B TOS,&LCD_DB_OUT       \ send LCD_Data
81     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
82     MOV @PSP+,TOS               \
83     MOV @IP+,PC
84 THEN                            \ read LCD bits pattern
85     SUB #2,PSP
86     MOV TOS,0(PSP)
87     BIC.B #LCD_EN,&LCD_CMD_OUT  \ lcd_en 1-->0 ==> strobe data
88     MOV.B &LCD_DB_IN,TOS        \ get LCD_Data
89     AND.B #LCD_DB,TOS           \
90     MOV @IP+,PC
91 ENDCODE
92     \
93
94 \ ------------------------------\
95 CODE LCD_W                      \ byte --       write byte 
96 \ ------------------------------\
97     SUB #2,PSP                  \
98     MOV TOS,0(PSP)              \ -- %xxxxLLLL %HHHHLLLL
99     RRUM #4,TOS                 \ -- %xxxxLLLL %xxxxHHHH
100     BIC.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=0
101     BIS.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as output
102     COLON
103     TOP_LCD 2 20_us             \ write high nibble first
104     TOP_LCD 2 20_us ;
105     \
106
107 \ ------------------------------\
108 CODE LCD_R                      \ -- byte       read byte
109 \ ------------------------------\
110     BIC.B #LCD_DB,&LCD_DB_DIR   \ LCD_Data as intput
111     BIS.B #LCD_RW,&LCD_CMD_OUT  \ lcd_rw=1
112     COLON
113     TOP_LCD 2 20_us             \ read high nibble first
114     TOP_LCD 2 20_us
115     HI2LO                       \ -- %0000HHHH %0000LLLL
116     MOV @RSP+,IP
117     MOV @PSP+,W                 \ W = high nibble
118     RLAM #4,W                   \ -- %0000LLLL     W = %HHHH0000 
119     ADD.B W,TOS
120     MOV @IP+,PC
121 ENDCODE
122     \
123 \ ------------------------------\
124 CODE LCD_WrF                    \ func --         Write Fonction
125 \ ------------------------------\
126     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
127     JMP LCD_W
128 ENDCODE
129     \
130 \ ------------------------------\
131 CODE LCD_RdS                    \ -- status       Read Status
132 \ ------------------------------\
133     BIC.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=0
134     JMP LCD_R
135 ENDCODE
136     \
137 \ ------------------------------\
138 CODE LCD_WrC                    \ char --         Write Char
139 \ ------------------------------\
140     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
141     JMP LCD_W
142 ENDCODE
143     \
144 \ ------------------------------\
145 CODE LCD_RdC                    \ -- char         Read Char
146 \ ------------------------------\
147     BIS.B #LCD_RS,&LCD_CMD_OUT  \ lcd_rs=1
148     JMP LCD_R
149 ENDCODE
150     \
151 \ ------------------------------\
152 \  : LCD_Clear $01 LCD_WrF 80 20_us ; \ bad init !
153 : LCD_Clear $01 LCD_WrF 100 20_us ;
154     \
155 \ ------------------------------\
156 : LCD_Home $02 LCD_WrF 80 20_us ;
157     \
158 \ ------------------------------\
159 \ : LCD_Entry_set       $04 OR LCD_WrF ;
160 \ : LCD_Display_Ctrl    $08 OR LCD_WrF ;
161 \ : LCD_Display_Shift   $10 OR LCD_WrF ;
162 \ : LCD_Fn_Set          $20 OR LCD_WrF ;
163 \ : LCD_CGRAM_Set       $40 OR LCD_WrF ;
164 \ : LCD_Goto            $80 OR LCD_WrF ;
165
166 \ -------------+------+------+------+------++---+---+---+---+---------+
167 \ SR(low byte) | SCG1 | SCG0 |OSCOFF|CPUOFF||GIE| N | Z | C | current |
168 \ -------------+------+------+------+------++---+---+---+---+---------+
169 \ LPM0 = $18  |  0   |  0   |  0   |  1   || 1 | x | x | x |  180uA  | default mode
170 \ LPM1 = $58  |  0   |  1   |  0   |  1   || 1 | x | x | x |         | same mode as LPM0
171 \ LPM2 = $98  |  1   |  0   |  0   |  1   || 1 | x | x | x |   60uA  |
172 \ LPM3 = $D8  |  1   |  1   |  0   |  1   || 1 | x | x | x |   10uA  | 32768Hz XTAL is running
173 \ LPM4 = $F8  |  1   |  1   |  1   |  1   || 1 | x | x | x |    6uA  |
174 \ -------------+------+------+------+------++---+---+---+---+---------+
175
176 \ ******************************\
177 ASM WDT_Int                     \ Watchdog interrupt routine, warning : not FORTH executable !
178 \ ******************************\
179 BIC #$F8,0(RSP)                 \ set CPU ON and GIE OFF in retiSR
180 \ ------------------------------\
181 \ define LPM mode for ACCEPT    \
182 \ ------------------------------\
183 \ MOV #LPM4,&LPM_MODE             \ with MSP430FR59xx
184 \ MOV #LPM2,&LPM_MODE             \ with MSP430FR57xx, terminal input don't work for LPMx > 2
185 \                                 \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
186 \ ------------------------------\
187 BIT.B #SW2,&SW2_IN              \ test switch S2
188 0= IF                           \ case of switch S2 pressed
189   CMP #34,&TB0CCR2              \ maxi Ton = 34/40 & VDD=3V6 ==> LCD_Vo = -2V2
190   U< IF
191     ADD #1,&TB0CCR2             \ action for switch S2 (P2.5) : 78 mV / increment
192   THEN
193 ELSE
194     BIT.B #SW1,&SW1_IN          \ test switch S1 input
195     0= IF                       \ case of Switch S1 pressed
196         CMP #7,&TB0CCR2         \ mini Ton = 6/40 & VDD=3V6 ==> LCD_Vo = 0V
197         U>= IF                  \
198         SUB #1,&TB0CCR2         \ action for switch S1 (P2.6) : -78 mV / decrement
199         THEN                    \
200     THEN                        \
201 THEN                            \
202 RETI                            \ CPU is ON, GIE is OFF
203 ENDASM                          \
204     \
205
206
207 \ ------------------------------\
208 CODE START                      \
209 \ ------------------------------\
210 \ TB0CTL = %0000 0010 1001 0100\$3C0
211 \               - -             \CNTL Counter lentgh \ 00 = 16 bits
212 \                   --          \TBSSEL TimerB clock select \ 10 = SMCLK
213 \                      --       \ID input divider \ 10 = /4
214 \                        --     \MC Mode Control \ 01 = up mode
215 \                            -  \TBCLR TimerB Clear
216 \                             - \TBIE
217 \                              -\TBIFG
218 \ --------------------------------\\
219 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
220 \              --                 \CM Capture Mode
221 \                --               \CCIS
222 \                   -             \SCS
223 \                    --           \CLLD
224 \                      -          \CAP
225 \                        ---      \OUTMOD \ 011 = set/reset
226 \                           -     \CCIE
227 \                             -   \CCI
228 \                              -  \OUT
229 \                               - \COV
230 \                                -\CCIFG
231 \ TB0CCRx                         \$3D{2,4,6,8,A,C,E}
232 \ TB0EX0                          \$3E0 
233 \ ------------------------------\
234 \ set TimerB to make 50kHz PWM  \
235 \ ------------------------------\
236 \    MOV #%1000010100,&TB0CTL   \ SMCLK/1, up mode, clear timer, no int
237 \    MOV #0,&TB0EX0             \ predivide by 1 in TB0EX0 register (1 MHZ) (25 kHz PWM)
238 \ ------------------------------\
239 \    MOV #%1000010100,&TB0CTL   \ SMCLK/1, up mode, clear timer, no int
240 \    MOV #1,&TB0EX0             \ predivide by 2 in TB0EX0 register (4 MHZ)
241 \ ------------------------------\
242     MOV #%1010010100,&TB0CTL    \ SMCLK/4, up mode, clear timer, no int
243     MOV #0,&TB0EX0              \ predivide by 1 in TB0EX0 register (8 MHZ)
244 \ ------------------------------\
245 \    MOV #%1010010100,&TB0CTL   \ SMCLK/4, up mode, clear timer, no int
246 \    MOV #1,&TB0EX0             \ predivide by 2 in TB0EX0 register (16 MHZ)
247 \ ------------------------------\
248 \    MOV #%1010010100,&TB0CTL   \ SMCLK/4, up mode, clear timer, no int
249 \    MOV #2,&TB0EX0             \ predivide by 3 in TB0EX0 register (24 MHZ)
250 \ ------------------------------\
251     MOV #40,&TB0CCR0            \ 40*0.5us=20us (40us @ 1MHz)
252 \ ------------------------------\
253 \ set TimerB to generate LCD_V0 via TB0.2 and P1.5/P2.2
254 \ ------------------------------\
255     MOV #%1100000,&TB0CCTL2     \ output mode = set/reset \ clear CCIFG
256 \    MOV #20,&TB0CCR2            \ contrast adjust : 20/40 ==> LCD_Vo = -1V1|+3V6 (Vcc=3V6)
257     MOV #25,&TB0CCR2            \ contrast adjust : 25/40 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
258 \ ------------------------------\
259 \ ------------------------------\
260 \ WDT interval init part        \
261 \ ------------------------------\
262 \    MOV #$5A5E,&WDTCTL          \ init WDT Vloclk source 10kHz /2^9 (50 ms), interval mode
263     MOV #$5A3D,&WDTCTL          \ init WDT ACLK source 32.768kHz /2^13 (250 ms), interval mode
264 \    MOV #$5A5D,&WDTCTL          \ init WDT Vloclk source 10kHz /2^13 (800 ms), interval mode
265     BIS #1,&SFRIE1              \ enable WDT interval mode interrupt in SFRIE
266 \ ------------------------------\
267 \ init interrupt vectors
268 \ ------------------------------\
269     MOV #WDT_Int,&WDT_Vec       \ init WDT interval vector interrupt
270 \ ------------------------------\
271 \ init PORTA (P2:P1) (complement)
272     BIS.B #LCDVo,&LCDVo_DIR     \
273     BIS.B #LCDVo,&LCDVo_SEL0    \ SEL0.2 TB0.2
274 \ ------------------------------\
275 \ init PORTB (P4:P3) (complement)
276     BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
277     BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
278 \ ------------------------------\
279 \ init PORTJ (PJ) (complement)
280     BIS.B   #LCD_DB,&LCD_DB_DIR \ PJDIR.(0-3) as output, wired to DB(4-7) LCD_Data
281     BIC.B   #LCD_DB,&LCD_DB_REN \ PJREN.(0-3) LCD_Data pullup/down disable
282 \ ------------------------------\
283 \ define LPM mode for ACCEPT    \
284 \ ------------------------------\
285 \ MOV #LPM4,&LPM_MODE             \ with MSP430FR59xx
286 \ MOV #LPM2,&LPM_MODE             \ with MSP430FR57xx, terminal input don't work for LPMx > 2
287 \                                 \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
288 \ ------------------------------\
289 \ Init LCD
290     LO2HI
291     $3E8 20_us              \ 1-  wait 20 ms
292     $03 TOP_LCD             \ 2- send DB5=DB4=1
293     $CD 20_us               \ 3- wait 4,1 ms
294     $03 TOP_LCD             \ 4- send again DB5=DB4=1
295     5 20_us                 \ 5- wait 0,1 ms
296     $03 TOP_LCD             \ 6- send again again DB5=DB4=1
297     2 20_us                 \    wait 40 us = LCD cycle
298     $02 TOP_LCD             \ 7- send DB5=1 DB4=0
299     2 20_us                 \    wait 40 us = LCD cycle
300     $28 LCD_WrF             \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
301     $08 LCD_WrF             \ 9- %1DCB   "DisplayControl" : Display off, Cursor off, Blink off. 
302     LCD_Clear               \ 10- "LCD_Clear"
303     $06 LCD_WrF             \ 11- %01xx   "LCD_EntrySet" : address and cursor shift after writing in RAM
304     $0C LCD_WrF             \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off. 
305     ['] LCD_HOME IS CR      \ ' CR redirected to LCD_HOME
306     ['] LCD_WrC  IS EMIT    \ ' EMIT redirected to LCD_WrC
307     CR ." I love you"   
308     ['] (CR) IS CR          \ ' (CR) is CR
309     ['] (EMIT) IS EMIT      \ ' (EMIT) is EMIT
310     ."    xxxx_to_LCD is running. Type STOP to quit"
311     LIT recurse is WARM     \ insert this starting routine between COLD and WARM...
312 \    NOECHO                      \ uncomment to run this app without terminal connexion
313     (WARM) ;                \ ...and continue with WARM
314     \
315
316 : STOP                  \ stops multitasking, must to be used before downloading app
317     ['] (WARM) IS WARM  \ remove START app from FORTH init process
318     ECHO COLD           \ reset CPU, interrupt vectors, and start FORTH
319 ;
320     \
321
322 PWR_HERE               \ set here the power_on dictionnary