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