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