]> git.sur5r.net Git - freertos/blob - Demo/dsPIC_MPLAB/lcd.c
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@261 1d2547de-c912-0410...
[freertos] / Demo / dsPIC_MPLAB / lcd.c
1 /*\r
2         FreeRTOS.org V4.7.2 - Copyright (C) 2003-2008 Richard Barry.\r
3 \r
4         This file is part of the FreeRTOS.org distribution.\r
5 \r
6         FreeRTOS.org is free software; you can redistribute it and/or modify\r
7         it under the terms of the GNU General Public License as published by\r
8         the Free Software Foundation; either version 2 of the License, or\r
9         (at your option) any later version.\r
10 \r
11         FreeRTOS.org is distributed in the hope that it will be useful,\r
12         but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14         GNU General Public License for more details.\r
15 \r
16         You should have received a copy of the GNU General Public License\r
17         along with FreeRTOS.org; if not, write to the Free Software\r
18         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
19 \r
20         A special exception to the GPL can be applied should you wish to distribute\r
21         a combined work that includes FreeRTOS.org, without being obliged to provide\r
22         the source code for any proprietary components.  See the licensing section \r
23         of http://www.FreeRTOS.org for full details of how and when the exception\r
24         can be applied.\r
25 \r
26         ***************************************************************************\r
27 \r
28         Please ensure to read the configuration and relevant port sections of the \r
29         online documentation.\r
30 \r
31         +++ http://www.FreeRTOS.org +++\r
32         Documentation, latest information, license and contact details.  \r
33 \r
34         +++ http://www.SafeRTOS.com +++\r
35         A version that is certified for use in safety critical systems.\r
36 \r
37         +++ http://www.OpenRTOS.com +++\r
38         Commercial support, development, porting, licensing and training services.\r
39 \r
40         ***************************************************************************\r
41 */\r
42 \r
43 /* Scheduler includes. */\r
44 #include "FreeRTOS.h"\r
45 #include "task.h"\r
46 #include "queue.h"\r
47 \r
48 /* Demo includes. */\r
49 #include "lcd.h"\r
50 \r
51 /*\r
52  * The LCD is written to by more than one task so is controlled by this\r
53  * 'gatekeeper' task.  This is the only task that is actually permitted to\r
54  * access the LCD directly.  Other tasks wanting to display a message send\r
55  * the message to the gatekeeper.\r
56  */\r
57 static void vLCDTask( void *pvParameters );\r
58 \r
59 /*\r
60  * Setup the peripherals required to communicate with the LCD.\r
61  */\r
62 static void prvSetupLCD( void );\r
63 \r
64 /* \r
65  * Move to the first (0) or second (1) row of the LCD. \r
66  */\r
67 static void prvLCDGotoRow( unsigned portSHORT usRow );\r
68 \r
69 /* \r
70  * Write a string of text to the LCD. \r
71  */\r
72 static void prvLCDPutString( portCHAR *pcString );\r
73 \r
74 /* \r
75  * Clear the LCD. \r
76  */\r
77 static void prvLCDClear( void );\r
78 \r
79 /*-----------------------------------------------------------*/\r
80 \r
81 /* Brief delay to permit the LCD to catch up with commands. */\r
82 #define lcdVERY_SHORT_DELAY     ( 1 )\r
83 #define lcdSHORT_DELAY          ( 4 / portTICK_RATE_MS )\r
84 #define lcdLONG_DELAY           ( 15 / portTICK_RATE_MS )\r
85 \r
86 /* LCD commands. */\r
87 #define lcdCLEAR                        ( 0x01 )\r
88 #define lcdHOME                         ( 0x02 )\r
89 #define lcdLINE2                        ( 0xc0 )\r
90 \r
91 /* SFR that seems to be missing from the standard header files. */\r
92 #define PMAEN                           *( ( unsigned short * ) 0x60c )\r
93 \r
94 /* LCD R/W signal. */\r
95 #define  lcdRW  LATDbits.LATD5       \r
96 \r
97 /* LCD lcdRS signal. */\r
98 #define  lcdRS  LATBbits.LATB15      \r
99 \r
100 /* LCD lcdE signal . */\r
101 #define  lcdE   LATDbits.LATD4       \r
102 \r
103 /* Control signal pin direction. */\r
104 #define  RW_TRIS        TRISDbits.TRISD5 \r
105 #define  RS_TRIS        TRISBbits.TRISB15\r
106 #define  E_TRIS         TRISDbits.TRISD4\r
107 \r
108 /* Port for LCD data */\r
109 #define  lcdDATA      LATE           \r
110 #define  lcdDATAPORT  PORTE\r
111 \r
112 /* I/O setup for data Port. */\r
113 #define  TRISDATA  TRISE          \r
114 \r
115 /* The length of the queue used to send messages to the LCD gatekeeper task. */\r
116 #define lcdQUEUE_SIZE           3\r
117 /*-----------------------------------------------------------*/\r
118 \r
119 /* The queue used to send messages to the LCD task. */\r
120 xQueueHandle xLCDQueue;\r
121 \r
122 static void prvLCDCommand( portCHAR cCommand );\r
123 static void prvLCDData( portCHAR cChar );\r
124 \r
125 /*-----------------------------------------------------------*/\r
126 \r
127 xQueueHandle xStartLCDTask( void )\r
128 {\r
129         /* Create the queue used by the LCD task.  Messages for display on the LCD\r
130         are received via this queue. */\r
131         xLCDQueue = xQueueCreate( lcdQUEUE_SIZE, sizeof( xLCDMessage ) );\r
132 \r
133         /* Start the task that will write to the LCD.  The LCD hardware is\r
134         initialised from within the task itself so delays can be used. */\r
135         xTaskCreate( vLCDTask, ( signed portCHAR * ) "LCD", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL );\r
136 \r
137         return xLCDQueue;\r
138 }\r
139 /*-----------------------------------------------------------*/\r
140 \r
141 static void prvLCDGotoRow( unsigned portSHORT usRow )\r
142 {\r
143         if( usRow == 0 )\r
144         {\r
145                 prvLCDCommand( lcdHOME );\r
146         }\r
147         else\r
148         {\r
149                 prvLCDCommand( lcdLINE2 );\r
150         }\r
151 }\r
152 /*-----------------------------------------------------------*/\r
153 \r
154 static void prvLCDCommand( portCHAR cCommand ) \r
155 {\r
156         /* Prepare RD0 - RD7. */\r
157         lcdDATA &= 0xFF00;               \r
158 \r
159         /* Command byte to lcd. */\r
160     lcdDATA |= cCommand;                  \r
161 \r
162         /* Ensure lcdRW is 0. */\r
163         lcdRW = 0;                       \r
164     lcdRS = 0;\r
165 \r
166         /* Toggle lcdE line. */\r
167     lcdE = 1;                        \r
168     vTaskDelay( lcdVERY_SHORT_DELAY );\r
169     lcdE = 0;\r
170 \r
171         vTaskDelay( lcdSHORT_DELAY );\r
172 }\r
173 /*-----------------------------------------------------------*/\r
174 \r
175 static void prvLCDData( portCHAR cChar )\r
176 {\r
177         /* ensure lcdRW is 0. */\r
178         lcdRW = 0;                                       \r
179 \r
180         /* Assert register select to 1. */\r
181     lcdRS = 1;                       \r
182 \r
183         /* Prepare RD0 - RD7. */\r
184         lcdDATA &= 0xFF00;               \r
185 \r
186         /* Data byte to lcd. */\r
187     lcdDATA |= cChar;                 \r
188     lcdE = 1;                           \r
189         Nop();\r
190     Nop();\r
191     Nop();\r
192 \r
193         /* Toggle lcdE signal. */\r
194     lcdE = 0;                       \r
195 \r
196         /* Negate register select to 0. */\r
197     lcdRS = 0;                      \r
198 \r
199         vTaskDelay( lcdVERY_SHORT_DELAY );\r
200 }\r
201 /*-----------------------------------------------------------*/\r
202 \r
203 static void prvLCDPutString( portCHAR *pcString )\r
204 {\r
205         /* Write out each character with appropriate delay between each. */\r
206         while( *pcString )\r
207         {\r
208                 prvLCDData( *pcString );\r
209                 pcString++;\r
210                 vTaskDelay( lcdSHORT_DELAY );\r
211         }\r
212 }\r
213 /*-----------------------------------------------------------*/\r
214 \r
215 static void prvLCDClear( void )\r
216 {\r
217         prvLCDCommand( lcdCLEAR );\r
218 }\r
219 /*-----------------------------------------------------------*/\r
220 \r
221 static void prvSetupLCD( void )\r
222 {\r
223         /* Wait for proper power up. */\r
224         vTaskDelay( lcdLONG_DELAY );\r
225                         \r
226         /* Set initial states for the data and control pins */\r
227         LATE &= 0xFF00; \r
228 \r
229         /* R/W state set low. */\r
230     lcdRW = 0;                       \r
231 \r
232         /* lcdRS state set low. */\r
233         lcdRS = 0;                       \r
234 \r
235         /* lcdE state set low. */\r
236         lcdE = 0;                        \r
237 \r
238         /* Set data and control pins to outputs */\r
239         TRISE &= 0xFF00;\r
240 \r
241         /* lcdRW pin set as output. */\r
242         RW_TRIS = 0;                  \r
243 \r
244         /* lcdRS pin set as output. */\r
245         RS_TRIS = 0;                  \r
246 \r
247         /* lcdE pin set as output. */\r
248         E_TRIS = 0;                   \r
249 \r
250         /* 1st LCD initialization sequence */\r
251         lcdDATA &= 0xFF00;\r
252     lcdDATA |= 0x0038;\r
253     lcdE = 1;   \r
254     Nop();\r
255     Nop();\r
256     Nop();\r
257 \r
258         /* Toggle lcdE signal. */\r
259     lcdE = 0;                        \r
260 \r
261         vTaskDelay( lcdSHORT_DELAY );\r
262         vTaskDelay( lcdSHORT_DELAY );\r
263         vTaskDelay( lcdSHORT_DELAY );\r
264       \r
265         /* 2nd LCD initialization sequence */\r
266         lcdDATA &= 0xFF00;\r
267     lcdDATA |= 0x0038;\r
268     lcdE = 1;   \r
269     Nop();\r
270     Nop();\r
271     Nop();      \r
272 \r
273         /* Toggle lcdE signal. */\r
274     lcdE = 0;                        \r
275 \r
276     vTaskDelay( lcdSHORT_DELAY );\r
277 \r
278         /* 3rd LCD initialization sequence */\r
279         lcdDATA &= 0xFF00;\r
280     lcdDATA |= 0x0038;\r
281     lcdE = 1;           \r
282     Nop();\r
283     Nop();\r
284     Nop();      \r
285 \r
286         /* Toggle lcdE signal. */\r
287     lcdE = 0;                        \r
288 \r
289         vTaskDelay( lcdSHORT_DELAY );\r
290 \r
291 \r
292         /* Function set. */\r
293     prvLCDCommand( 0x38 );              \r
294 \r
295         /* Display on/off control, cursor blink off (0x0C). */\r
296     prvLCDCommand( 0x0C );              \r
297 \r
298         /* Entry mode set (0x06). */\r
299     prvLCDCommand( 0x06 );              \r
300 \r
301         prvLCDCommand( lcdCLEAR );        \r
302 }\r
303 /*-----------------------------------------------------------*/\r
304 \r
305 static void vLCDTask( void *pvParameters )\r
306 {\r
307 xLCDMessage xMessage;\r
308 unsigned portSHORT usRow = 0;\r
309 \r
310         /* Initialise the hardware.  This uses delays so must not be called prior\r
311         to the scheduler being started. */\r
312         prvSetupLCD();\r
313 \r
314         /* Welcome message. */\r
315         prvLCDPutString( "www.FreeRTOS.org" );\r
316 \r
317         for( ;; )\r
318         {\r
319                 /* Wait for a message to arrive that requires displaying. */\r
320                 while( xQueueReceive( xLCDQueue, &xMessage, portMAX_DELAY ) != pdPASS );\r
321 \r
322                 /* Clear the current display value. */\r
323                 prvLCDClear();\r
324 \r
325                 /* Switch rows each time so we can see that the display is still being\r
326                 updated. */\r
327                 prvLCDGotoRow( usRow & 0x01 );\r
328                 usRow++;\r
329                 prvLCDPutString( xMessage.pcMessage );\r
330 \r
331                 /* Delay the requested amount of time to ensure the text just written \r
332                 to the LCD is not overwritten. */\r
333                 vTaskDelay( xMessage.xMinDisplayTime );         \r
334         }\r
335 }\r
336 \r
337 \r
338 \r
339 \r