]> git.sur5r.net Git - freertos/blob - Demo/PIC24_MPLAB/lcd.c
Ready for V5.2.0 release.
[freertos] / Demo / PIC24_MPLAB / lcd.c
1 /*\r
2         FreeRTOS.org V5.2.0 - Copyright (C) 2003-2009 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 it \r
7         under the terms of the GNU General Public License (version 2) as published\r
8         by the Free Software Foundation and modified by the FreeRTOS exception.\r
9 \r
10         FreeRTOS.org is distributed in the hope that it will be useful, but WITHOUT\r
11         ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or \r
12         FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for \r
13         more details.\r
14 \r
15         You should have received a copy of the GNU General Public License along \r
16         with FreeRTOS.org; if not, write to the Free Software Foundation, Inc., 59 \r
17         Temple Place, Suite 330, Boston, MA  02111-1307  USA.\r
18 \r
19         A special exception to the GPL is included to allow you to distribute a \r
20         combined work that includes FreeRTOS.org without being obliged to provide\r
21         the source code for any proprietary components.  See the licensing section\r
22         of http://www.FreeRTOS.org for full details.\r
23 \r
24 \r
25         ***************************************************************************\r
26         *                                                                         *\r
27         * Get the FreeRTOS eBook!  See http://www.FreeRTOS.org/Documentation      *\r
28         *                                                                         *\r
29         * This is a concise, step by step, 'hands on' guide that describes both   *\r
30         * general multitasking concepts and FreeRTOS specifics. It presents and   *\r
31         * explains numerous examples that are written using the FreeRTOS API.     *\r
32         * Full source code for all the examples is provided in an accompanying    *\r
33         * .zip file.                                                              *\r
34         *                                                                         *\r
35         ***************************************************************************\r
36 \r
37         1 tab == 4 spaces!\r
38 \r
39         Please ensure to read the configuration and relevant port sections of the\r
40         online documentation.\r
41 \r
42         http://www.FreeRTOS.org - Documentation, latest information, license and\r
43         contact details.\r
44 \r
45         http://www.SafeRTOS.com - A version that is certified for use in safety\r
46         critical systems.\r
47 \r
48         http://www.OpenRTOS.com - Commercial support, development, porting,\r
49         licensing and training services.\r
50 */\r
51 \r
52 /* Scheduler includes. */\r
53 #include "FreeRTOS.h"\r
54 #include "task.h"\r
55 #include "queue.h"\r
56 \r
57 /* Demo includes. */\r
58 #include "lcd.h"\r
59 \r
60 /*\r
61  * The LCD is written to by more than one task so is controlled by this\r
62  * 'gatekeeper' task.  This is the only task that is actually permitted to\r
63  * access the LCD directly.  Other tasks wanting to display a message send\r
64  * the message to the gatekeeper.\r
65  */\r
66 static void vLCDTask( void *pvParameters );\r
67 \r
68 /*\r
69  * Setup the peripherals required to communicate with the LCD.\r
70  */\r
71 static void prvSetupLCD( void );\r
72 \r
73 /* \r
74  * Move to the first (0) or second (1) row of the LCD. \r
75  */\r
76 static void prvLCDGotoRow( unsigned portSHORT usRow );\r
77 \r
78 /* \r
79  * Write a string of text to the LCD. \r
80  */\r
81 static void prvLCDPutString( portCHAR *pcString );\r
82 \r
83 /* \r
84  * Clear the LCD. \r
85  */\r
86 static void prvLCDClear( void );\r
87 \r
88 /*-----------------------------------------------------------*/\r
89 \r
90 /* Brief delay to permit the LCD to catch up with commands. */\r
91 #define lcdSHORT_DELAY          3\r
92 \r
93 /* SFR that seems to be missing from the standard header files. */\r
94 #define PMAEN                           *( ( unsigned short * ) 0x60c )\r
95 \r
96 /* LCD commands. */\r
97 #define lcdDEFAULT_FUNCTION     0x3c\r
98 #define lcdDISPLAY_CONTROL      0x0c\r
99 #define lcdCLEAR_DISPLAY        0x01\r
100 #define lcdENTRY_MODE           0x06\r
101 \r
102 /* The length of the queue used to send messages to the LCD gatekeeper task. */\r
103 #define lcdQUEUE_SIZE           3\r
104 /*-----------------------------------------------------------*/\r
105 \r
106 /* The queue used to send messages to the LCD task. */\r
107 xQueueHandle xLCDQueue;\r
108 \r
109 \r
110 /*-----------------------------------------------------------*/\r
111 \r
112 xQueueHandle xStartLCDTask( void )\r
113 {\r
114         /* Create the queue used by the LCD task.  Messages for display on the LCD\r
115         are received via this queue. */\r
116         xLCDQueue = xQueueCreate( lcdQUEUE_SIZE, sizeof( xLCDMessage ) );\r
117 \r
118         /* Start the task that will write to the LCD.  The LCD hardware is\r
119         initialised from within the task itself so delays can be used. */\r
120         xTaskCreate( vLCDTask, ( signed portCHAR * ) "LCD", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL );\r
121 \r
122         return xLCDQueue;\r
123 }\r
124 /*-----------------------------------------------------------*/\r
125 \r
126 static void prvLCDGotoRow( unsigned portSHORT usRow )\r
127 {\r
128         if( usRow == 0 )\r
129         {\r
130                 PMADDR = 0x0000;\r
131                 PMDIN1 = 0x02;\r
132         }\r
133         else\r
134         {\r
135                 PMADDR = 0x0000;\r
136                 PMDIN1 = 0xc0;\r
137         }\r
138 \r
139         vTaskDelay( lcdSHORT_DELAY );\r
140 }\r
141 /*-----------------------------------------------------------*/\r
142 \r
143 static void prvLCDPutString( portCHAR *pcString )\r
144 {\r
145         /* Write out each character with appropriate delay between each. */\r
146         while( *pcString )\r
147         {\r
148                 PMADDR = 0x0001;\r
149                 PMDIN1 = *pcString;\r
150                 pcString++;\r
151                 vTaskDelay( lcdSHORT_DELAY );\r
152         }\r
153 }\r
154 /*-----------------------------------------------------------*/\r
155 \r
156 static void prvLCDClear( void )\r
157 {\r
158         /* Clear the display. */\r
159         PMADDR = 0x0000;\r
160         PMDIN1 = lcdCLEAR_DISPLAY;\r
161         vTaskDelay( lcdSHORT_DELAY );   \r
162 }\r
163 /*-----------------------------------------------------------*/\r
164 \r
165 static void prvSetupLCD( void )\r
166 {\r
167         /* Setup the PMP. */\r
168         PMCON = 0x83BF;\r
169         PMMODE = 0x3FF;\r
170         PMAEN = 1;\r
171         PMADDR = 0x0000;\r
172         vTaskDelay( lcdSHORT_DELAY );\r
173 \r
174         /* Set the default function. */\r
175         PMDIN1 = lcdDEFAULT_FUNCTION;\r
176         vTaskDelay( lcdSHORT_DELAY );\r
177 \r
178         /* Set the display control. */\r
179         PMDIN1 = lcdDISPLAY_CONTROL;\r
180         vTaskDelay( lcdSHORT_DELAY );\r
181 \r
182         /* Clear the display. */\r
183         PMDIN1 = lcdCLEAR_DISPLAY;\r
184         vTaskDelay( lcdSHORT_DELAY );\r
185 \r
186         /* Set the entry mode. */\r
187         PMDIN1 = lcdENTRY_MODE;\r
188         vTaskDelay( lcdSHORT_DELAY );\r
189 }\r
190 /*-----------------------------------------------------------*/\r
191 \r
192 static void vLCDTask( void *pvParameters )\r
193 {\r
194 xLCDMessage xMessage;\r
195 unsigned portSHORT usRow = 0;\r
196 \r
197         /* Initialise the hardware.  This uses delays so must not be called prior\r
198         to the scheduler being started. */\r
199         prvSetupLCD();\r
200 \r
201         /* Welcome message. */\r
202         prvLCDPutString( "www.FreeRTOS.org" );\r
203 \r
204         for( ;; )\r
205         {\r
206                 /* Wait for a message to arrive that requires displaying. */\r
207                 while( xQueueReceive( xLCDQueue, &xMessage, portMAX_DELAY ) != pdPASS );\r
208 \r
209                 /* Clear the current display value. */\r
210                 prvLCDClear();\r
211 \r
212                 /* Switch rows each time so we can see that the display is still being\r
213                 updated. */\r
214                 prvLCDGotoRow( usRow & 0x01 );\r
215                 usRow++;\r
216                 prvLCDPutString( xMessage.pcMessage );\r
217 \r
218                 /* Delay the requested amount of time to ensure the text just written \r
219                 to the LCD is not overwritten. */\r
220                 vTaskDelay( xMessage.xMinDisplayTime );         \r
221         }\r
222 }\r
223 \r
224 \r
225 \r
226 \r