]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/PIC32MX_MPLAB/lcd.c
Update to MIT licensed FreeRTOS V10.0.0 - see https://www.freertos.org/History.txt
[freertos] / FreeRTOS / Demo / PIC32MX_MPLAB / lcd.c
1 /*\r
2  * FreeRTOS Kernel V10.0.0\r
3  * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
6  * this software and associated documentation files (the "Software"), to deal in\r
7  * the Software without restriction, including without limitation the rights to\r
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
9  * the Software, and to permit persons to whom the Software is furnished to do so,\r
10  * subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be included in all\r
13  * copies or substantial portions of the Software. If you wish to use our Amazon\r
14  * FreeRTOS name, please do so in a fair use way that does not cause confusion.\r
15  *\r
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
18  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
19  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
20  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
22  *\r
23  * http://www.FreeRTOS.org\r
24  * http://aws.amazon.com/freertos\r
25  *\r
26  * 1 tab == 4 spaces!\r
27  */\r
28 \r
29 /* peripheral library include */\r
30 #include <plib.h>\r
31 \r
32 /* Scheduler includes. */\r
33 #include "FreeRTOS.h"\r
34 #include "task.h"\r
35 #include "queue.h"\r
36 \r
37 /* Demo includes. */\r
38 #include "lcd.h"\r
39 \r
40 /*\r
41  * The LCD is written to by more than one task so is controlled by this\r
42  * 'gatekeeper' task.  This is the only task that is actually permitted to\r
43  * access the LCD directly.  Other tasks wanting to display a message send\r
44  * the message to the gatekeeper.\r
45  */\r
46 static void vLCDTask( void *pvParameters );\r
47 \r
48 /*\r
49  * Setup the peripherals required to communicate with the LCD.\r
50  */\r
51 static void prvSetupLCD( void );\r
52 \r
53 /* \r
54  * Move to the first (0) or second (1) row of the LCD. \r
55  */\r
56 static void prvLCDGotoRow( unsigned short usRow );\r
57 \r
58 /* \r
59  * Write a string of text to the LCD. \r
60  */\r
61 static void prvLCDPutString( char *pcString );\r
62 \r
63 /* \r
64  * Clear the LCD. \r
65  */\r
66 static void prvLCDClear( void );\r
67 \r
68 /*-----------------------------------------------------------*/\r
69 \r
70 /* Brief delay to permit the LCD to catch up with commands. */\r
71 #define lcdVERY_SHORT_DELAY     ( 1 )\r
72 #define lcdSHORT_DELAY          ( 8 / portTICK_PERIOD_MS )\r
73 #define lcdLONG_DELAY           ( 15 / portTICK_PERIOD_MS )\r
74 \r
75 /* LCD specific definitions. */\r
76 #define LCD_CLEAR_DISPLAY_CMD                   0x01\r
77 #define LCD_CURSOR_HOME_CMD                             0x02\r
78 #define LCD_ENTRY_MODE_CMD                              0x04\r
79 #define LCD_ENTRY_MODE_INCREASE                 0x02\r
80 #define LCD_DISPLAY_CTRL_CMD                    0x08\r
81 #define LCD_DISPLAY_CTRL_DISPLAY_ON             0x04\r
82 #define LCD_FUNCTION_SET_CMD                    0x20\r
83 #define LCD_FUNCTION_SET_8_BITS                 0x10\r
84 #define LCD_FUNCTION_SET_2_LINES                0x08\r
85 #define LCD_FUNCTION_SET_LRG_FONT               0x04\r
86 #define LCD_NEW_LINE                                    0xC0\r
87 #define LCD_COMMAND_ADDRESS                             0x00\r
88 #define LCD_DATA_ADDRESS                                0x01\r
89 \r
90 /* The length of the queue used to send messages to the LCD gatekeeper task. */\r
91 #define lcdQUEUE_SIZE           3\r
92 \r
93 /*-----------------------------------------------------------*/\r
94 \r
95 /* The queue used to send messages to the LCD task. */\r
96 QueueHandle_t xLCDQueue;\r
97 \r
98 /* LCD access functions. */\r
99 static void prvLCDCommand( char cCommand );\r
100 static void prvLCDData( char cChar );\r
101 \r
102 /*-----------------------------------------------------------*/\r
103 \r
104 QueueHandle_t xStartLCDTask( void )\r
105 {\r
106         /* Create the queue used by the LCD task.  Messages for display on the LCD\r
107         are received via this queue. */\r
108         xLCDQueue = xQueueCreate( lcdQUEUE_SIZE, sizeof( xLCDMessage ));\r
109 \r
110         /* Start the task that will write to the LCD.  The LCD hardware is\r
111         initialised from within the task itself so delays can be used. */\r
112         xTaskCreate( vLCDTask, "LCD", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL );\r
113 \r
114         return xLCDQueue;\r
115 }\r
116 /*-----------------------------------------------------------*/\r
117 \r
118 static void prvLCDGotoRow( unsigned short usRow )\r
119 {\r
120         if(usRow == 0) \r
121         {\r
122                 prvLCDCommand( LCD_CURSOR_HOME_CMD );\r
123         } \r
124         else \r
125         {\r
126                 prvLCDCommand( LCD_NEW_LINE );\r
127         }\r
128 }\r
129 /*-----------------------------------------------------------*/\r
130 \r
131 static void prvLCDCommand( char cCommand ) \r
132 {\r
133         PMPSetAddress( LCD_COMMAND_ADDRESS );\r
134         PMPMasterWrite( cCommand );\r
135         vTaskDelay( lcdSHORT_DELAY );\r
136 }\r
137 /*-----------------------------------------------------------*/\r
138 \r
139 static void prvLCDData( char cChar )\r
140 {\r
141         PMPSetAddress( LCD_DATA_ADDRESS );\r
142         PMPMasterWrite( cChar );\r
143         vTaskDelay( lcdVERY_SHORT_DELAY );\r
144 }\r
145 /*-----------------------------------------------------------*/\r
146 \r
147 static void prvLCDPutString( char *pcString )\r
148 {\r
149         /* Write out each character with appropriate delay between each. */\r
150         while(*pcString)\r
151         {\r
152                 prvLCDData(*pcString);\r
153                 pcString++;\r
154                 vTaskDelay(lcdSHORT_DELAY);\r
155         }\r
156 }\r
157 /*-----------------------------------------------------------*/\r
158 \r
159 static void prvLCDClear(void)\r
160 {\r
161         prvLCDCommand(LCD_CLEAR_DISPLAY_CMD);\r
162 }\r
163 /*-----------------------------------------------------------*/\r
164 \r
165 static void prvSetupLCD(void)\r
166 {\r
167         /* Wait for proper power up. */\r
168         vTaskDelay( lcdLONG_DELAY );\r
169         \r
170         /* Open the PMP port */\r
171         mPMPOpen((PMP_ON | PMP_READ_WRITE_EN | PMP_CS2_CS1_EN |\r
172                           PMP_LATCH_POL_HI | PMP_CS2_POL_HI | PMP_CS1_POL_HI |\r
173                           PMP_WRITE_POL_HI | PMP_READ_POL_HI),\r
174                          (PMP_MODE_MASTER1 | PMP_WAIT_BEG_4 | PMP_WAIT_MID_15 |\r
175                           PMP_WAIT_END_4),\r
176                           PMP_PEN_0, 0);\r
177                          \r
178         /* Wait for the LCD to power up correctly. */\r
179         vTaskDelay( lcdLONG_DELAY );\r
180         vTaskDelay( lcdLONG_DELAY );\r
181         vTaskDelay( lcdLONG_DELAY );\r
182 \r
183         /* Set up the LCD function. */\r
184         prvLCDCommand( LCD_FUNCTION_SET_CMD | LCD_FUNCTION_SET_8_BITS | LCD_FUNCTION_SET_2_LINES | LCD_FUNCTION_SET_LRG_FONT );\r
185         \r
186         /* Turn the display on. */\r
187         prvLCDCommand( LCD_DISPLAY_CTRL_CMD | LCD_DISPLAY_CTRL_DISPLAY_ON );\r
188         \r
189         /* Clear the display. */\r
190         prvLCDCommand( LCD_CLEAR_DISPLAY_CMD );\r
191         vTaskDelay( lcdLONG_DELAY );    \r
192         \r
193         /* Increase the cursor. */\r
194         prvLCDCommand( LCD_ENTRY_MODE_CMD | LCD_ENTRY_MODE_INCREASE );\r
195         vTaskDelay( lcdLONG_DELAY );                    \r
196         vTaskDelay( lcdLONG_DELAY );                    \r
197         vTaskDelay( lcdLONG_DELAY );\r
198 }\r
199 /*-----------------------------------------------------------*/\r
200 \r
201 static void vLCDTask(void *pvParameters)\r
202 {\r
203 xLCDMessage xMessage;\r
204 unsigned short usRow = 0;\r
205 \r
206         /* Initialise the hardware.  This uses delays so must not be called prior\r
207         to the scheduler being started. */\r
208         prvSetupLCD();\r
209 \r
210         /* Welcome message. */\r
211         prvLCDPutString( "www.FreeRTOS.org" );\r
212 \r
213         for(;;)\r
214         {\r
215                 /* Wait for a message to arrive that requires displaying. */\r
216                 while( xQueueReceive( xLCDQueue, &xMessage, portMAX_DELAY ) != pdPASS );\r
217 \r
218                 /* Clear the current display value. */\r
219                 prvLCDClear();\r
220 \r
221                 /* Switch rows each time so we can see that the display is still being\r
222                 updated. */\r
223                 prvLCDGotoRow( usRow & 0x01 );\r
224                 usRow++;\r
225                 prvLCDPutString( xMessage.pcMessage );\r
226 \r
227                 /* Delay the requested amount of time to ensure the text just written \r
228                 to the LCD is not overwritten. */\r
229                 vTaskDelay( xMessage.xMinDisplayTime );         \r
230         }\r
231 }\r
232 \r
233 \r
234 \r
235 \r