1 \ ------------------------------
2 \ MSP430FR5xxx_LCD_20.f
3 \ ------------------------------
6 \ Copyright (C) <2014> <J.M. THOORENS>
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.
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.
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/>.
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
29 \ layout : see config.pat file for defining I/O
31 \ GND <-------+---0V0----------> 1 LCD_Vss
32 \ VCC >------ | --3V6-----+----> 2 LCD_Vdd
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
48 \ Sw1 <--- LCD contrast + (finger :-)
49 \ Sw2 <--- LCD contrast - (finger \-)
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
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
80 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
81 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
84 THEN \ read LCD bits pattern
87 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
88 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
94 \ ------------------------------\
95 CODE LCD_W \ byte -- write byte
96 \ ------------------------------\
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
103 TOP_LCD 2 20_us \ write high nibble first
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
113 TOP_LCD 2 20_us \ read high nibble first
115 HI2LO \ -- %0000HHHH %0000LLLL
117 MOV @PSP+,W \ W = high nibble
118 RLAM #4,W \ -- %0000LLLL W = %HHHH0000
123 \ ------------------------------\
124 CODE LCD_WrF \ func -- Write Fonction
125 \ ------------------------------\
126 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
130 \ ------------------------------\
131 CODE LCD_RdS \ -- status Read Status
132 \ ------------------------------\
133 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
137 \ ------------------------------\
138 CODE LCD_WrC \ char -- Write Char
139 \ ------------------------------\
140 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
144 \ ------------------------------\
145 CODE LCD_RdC \ -- char Read Char
146 \ ------------------------------\
147 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
151 \ ------------------------------\
152 \ : LCD_Clear $01 LCD_WrF 80 20_us ; \ bad init !
153 : LCD_Clear $01 LCD_WrF 100 20_us ;
155 \ ------------------------------\
156 : LCD_Home $02 LCD_WrF 80 20_us ;
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 ;
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 \ -------------+------+------+------+------++---+---+---+---+---------+
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
191 ADD #1,&TB0CCR2 \ action for switch S2 (P2.5) : 78 mV / increment
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
198 SUB #1,&TB0CCR2 \ action for switch S1 (P2.6) : -78 mV / decrement
202 RETI \ CPU is ON, GIE is OFF
207 \ ------------------------------\
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
218 \ --------------------------------\\
219 \ TB0CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
220 \ -- \CM Capture Mode
225 \ --- \OUTMOD \ 011 = set/reset
231 \ TB0CCRx \$3D{2,4,6,8,A,C,E}
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 \ ------------------------------\
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
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
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
322 PWR_HERE \ set here the power_on dictionnary