Various changes for smartlcd boards
[hackover2013-badge-firmware.git] / drivers / lcd / tft / hw / ILI9328.c
1 /**************************************************************************/
2 /*!
3 @file ILI9328.c
4 @author K. Townsend (microBuilder.eu)
5
6 @section DESCRIPTION
7
8 Driver for ILI9328 240x320 pixel TFT LCD displays.
9
10 This driver uses an 8-bit interface and a 16-bit RGB565 colour palette.
11
12 @section LICENSE
13
14 Software License Agreement (BSD License)
15
16 Copyright (c) 2010, microBuilder SARL
17 All rights reserved.
18
19 Redistribution and use in source and binary forms, with or without
20 modification, are permitted provided that the following conditions are met:
21 1. Redistributions of source code must retain the above copyright
22 notice, this list of conditions and the following disclaimer.
23 2. Redistributions in binary form must reproduce the above copyright
24 notice, this list of conditions and the following disclaimer in the
25 documentation and/or other materials provided with the distribution.
26 3. Neither the name of the copyright holders nor the
27 names of its contributors may be used to endorse or promote products
28 derived from this software without specific prior written permission.
29
30 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
31 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
32 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
33 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
34 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
35 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
36 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
37 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
39 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 */
41 /**************************************************************************/
42 #include "ILI9328.h"
43 #include "core/systick/systick.h"
44 #include "drivers/lcd/tft/touchscreen.h"
45
46 static volatile lcdOrientation_t lcdOrientation = LCD_ORIENTATION_PORTRAIT;
47 static lcdProperties_t ili9328Properties = { 240, 320, TRUE, TRUE, TRUE };
48
49 /*************************************************/
50 /* Private Methods */
51 /*************************************************/
52
53 /**************************************************************************/
54 /*!
55 @brief Causes a brief delay (10 ticks per unit)
56 */
57 /**************************************************************************/
58 void ili9328Delay(unsigned int t)
59 {
60 unsigned char t1;
61 while(t--)
62 for ( t1=10; t1 > 0; t1-- )
63 {
64 __asm("nop");
65 }
66 }
67
68 /**************************************************************************/
69 /*!
70 @brief Writes the supplied 16-bit command using an 8-bit interface
71 */
72 /**************************************************************************/
73 void ili9328WriteCmd(uint16_t command)
74 {
75 // Compiled with -Os on GCC 4.4 this works out to 25 cycles
76 // (versus 36 compiled with no optimisations). I'm not sure it
77 // can be improved further, so that means 25 cycles/350nS for
78 // continuous writes (cmd, data, data, data, ...) or ~150 cycles/
79 // ~2.1uS for a random pixel (Set X [cmd+data], Set Y [cmd+data],
80 // Set color [cmd+data]) (times assumes 72MHz clock).
81
82 CLR_CS_CD_SET_RD_WR; // Saves 18 commands compared to "CLR_CS; CLR_CD; SET_RD; SET_WR;"
83 ILI9328_GPIO2DATA_DATA = (command >> (8 - ILI9328_DATA_OFFSET));
84 CLR_WR;
85 SET_WR;
86 ILI9328_GPIO2DATA_DATA = command << ILI9328_DATA_OFFSET;
87 CLR_WR;
88 SET_WR_CS; // Saves 7 commands compared to "SET_WR; SET_CS;"
89 }
90
91 /**************************************************************************/
92 /*!
93 @brief Writes the supplied 16-bit data using an 8-bit interface
94 */
95 /**************************************************************************/
96 void ili9328WriteData(uint16_t data)
97 {
98 CLR_CS_SET_CD_RD_WR; // Saves 18 commands compared to SET_CD; SET_RD; SET_WR; CLR_CS"
99 ILI9328_GPIO2DATA_DATA = (data >> (8 - ILI9328_DATA_OFFSET));
100 CLR_WR;
101 SET_WR;
102 ILI9328_GPIO2DATA_DATA = data << ILI9328_DATA_OFFSET;
103 CLR_WR;
104 SET_WR_CS; // Saves 7 commands compared to "SET_WR, SET_CS;"
105 }
106
107 /**************************************************************************/
108 /*!
109 @brief Reads a 16-bit value from the 8-bit data bus
110 */
111 /**************************************************************************/
112 uint16_t ili9328ReadData(void)
113 {
114 // ToDo: Optimise this method!
115
116 uint16_t high, low;
117 high = low = 0;
118 uint16_t d;
119
120 SET_CD_RD_WR; // Saves 14 commands compared to "SET_CD; SET_RD; SET_WR"
121 CLR_CS;
122
123 // set inputs
124 ILI9328_GPIO2DATA_SETINPUT;
125 CLR_RD;
126 ili9328Delay(100);
127 high = ILI9328_GPIO2DATA_DATA;
128 high >>= ILI9328_DATA_OFFSET;
129 high &= 0xFF;
130 SET_RD;
131
132 CLR_RD;
133 ili9328Delay(100);
134 low = ILI9328_GPIO2DATA_DATA;
135 low >>= ILI9328_DATA_OFFSET;
136 low &=0xFF;
137 SET_RD;
138
139 SET_CS;
140 ILI9328_GPIO2DATA_SETOUTPUT;
141
142 d = high;
143 d <<= 8;
144 d |= low;
145
146 return d;
147 }
148
149 /**************************************************************************/
150 /*!
151 @brief Reads a 16-bit value
152 */
153 /**************************************************************************/
154 uint16_t ili9328Read(uint16_t addr)
155 {
156 ili9328WriteCmd(addr);
157 return ili9328ReadData();
158 }
159
160 /**************************************************************************/
161 /*!
162 @brief Sends a 16-bit command + 16-bit data
163 */
164 /**************************************************************************/
165 void ili9328Command(uint16_t command, uint16_t data)
166 {
167 ili9328WriteCmd(command);
168 ili9328WriteData(data);
169 }
170
171 /**************************************************************************/
172 /*!
173 @brief Returns the 16-bit (4-hexdigit) controller code
174 */
175 /**************************************************************************/
176 uint16_t ili9328Type(void)
177 {
178 ili9328WriteCmd(ILI9328_COMMANDS_DRIVERCODEREAD);
179 return ili9328ReadData();
180 }
181
182 /**************************************************************************/
183 /*!
184 @brief Sets the cursor to the specified X/Y position
185 */
186 /**************************************************************************/
187 void ili9328SetCursor(uint16_t x, uint16_t y)
188 {
189 uint16_t al, ah;
190
191 if (lcdOrientation == LCD_ORIENTATION_LANDSCAPE)
192 {
193 al = y;
194 ah = x;
195 }
196 else
197 {
198 al = x;
199 ah = y;
200 }
201
202 ili9328Command(ILI9328_COMMANDS_HORIZONTALGRAMADDRESSSET, al);
203 ili9328Command(ILI9328_COMMANDS_VERTICALGRAMADDRESSSET, ah);
204 }
205
206 /**************************************************************************/
207 /*!
208 @brief Sends the initialisation sequence to the display controller
209 */
210 /**************************************************************************/
211 void ili9328InitDisplay(void)
212 {
213 // Clear data line
214 GPIO_GPIO2DATA &= ~ILI9328_DATA_MASK;
215
216 SET_RD;
217 SET_WR;
218 SET_CS;
219 SET_CD;
220
221 // Reset display
222 CLR_RESET;
223 ili9328Delay(100);
224 SET_RESET;
225 ili9328Delay(1000);
226
227 ili9328Command(ILI9328_COMMANDS_DRIVEROUTPUTCONTROL1, 0x0100); // Driver Output Control Register (R01h)
228 ili9328Command(ILI9328_COMMANDS_LCDDRIVINGCONTROL, 0x0700); // LCD Driving Waveform Control (R02h)
229 ili9328Command(ILI9328_COMMANDS_ENTRYMODE, 0x1030); // Entry Mode (R03h)
230 ili9328Command(ILI9328_COMMANDS_DISPLAYCONTROL2, 0x0302);
231 ili9328Command(ILI9328_COMMANDS_DISPLAYCONTROL3, 0x0000);
232 ili9328Command(ILI9328_COMMANDS_DISPLAYCONTROL4, 0x0000); // Fmark On
233 ili9328Command(ILI9328_COMMANDS_POWERCONTROL1, 0x0000); // Power Control 1 (R10h)
234 ili9328Command(ILI9328_COMMANDS_POWERCONTROL2, 0x0007); // Power Control 2 (R11h)
235 ili9328Command(ILI9328_COMMANDS_POWERCONTROL3, 0x0000); // Power Control 3 (R12h)
236 ili9328Command(ILI9328_COMMANDS_POWERCONTROL4, 0x0000); // Power Control 4 (R13h)
237 ili9328Delay(1000);
238 ili9328Command(ILI9328_COMMANDS_POWERCONTROL1, 0x14B0); // Power Control 1 (R10h)
239 ili9328Delay(500);
240 ili9328Command(ILI9328_COMMANDS_POWERCONTROL2, 0x0007); // Power Control 2 (R11h)
241 ili9328Delay(500);
242 ili9328Command(ILI9328_COMMANDS_POWERCONTROL3, 0x008E); // Power Control 3 (R12h)
243 ili9328Command(ILI9328_COMMANDS_POWERCONTROL4, 0x0C00); // Power Control 4 (R13h)
244 ili9328Command(ILI9328_COMMANDS_POWERCONTROL7, 0x0015); // NVM read data 2 (R29h)
245 ili9328Delay(500);
246 ili9328Command(ILI9328_COMMANDS_GAMMACONTROL1, 0x0000); // Gamma Control 1
247 ili9328Command(ILI9328_COMMANDS_GAMMACONTROL2, 0x0107); // Gamma Control 2
248 ili9328Command(ILI9328_COMMANDS_GAMMACONTROL3, 0x0000); // Gamma Control 3
249 ili9328Command(ILI9328_COMMANDS_GAMMACONTROL4, 0x0203); // Gamma Control 4
250 ili9328Command(ILI9328_COMMANDS_GAMMACONTROL5, 0x0402); // Gamma Control 5
251 ili9328Command(ILI9328_COMMANDS_GAMMACONTROL6, 0x0000); // Gamma Control 6
252 ili9328Command(ILI9328_COMMANDS_GAMMACONTROL7, 0x0207); // Gamma Control 7
253 ili9328Command(ILI9328_COMMANDS_GAMMACONTROL8, 0x0000); // Gamma Control 8
254 ili9328Command(ILI9328_COMMANDS_GAMMACONTROL9, 0x0203); // Gamma Control 9
255 ili9328Command(ILI9328_COMMANDS_GAMMACONTROL10, 0x0403); // Gamma Control 10
256 ili9328Command(ILI9328_COMMANDS_HORIZONTALADDRESSSTARTPOSITION, 0x0000); // Window Horizontal RAM Address Start (R50h)
257 ili9328Command(ILI9328_COMMANDS_HORIZONTALADDRESSENDPOSITION, ili9328Properties.width - 1); // Window Horizontal RAM Address End (R51h)
258 ili9328Command(ILI9328_COMMANDS_VERTICALADDRESSSTARTPOSITION, 0X0000); // Window Vertical RAM Address Start (R52h)
259 ili9328Command(ILI9328_COMMANDS_VERTICALADDRESSENDPOSITION, ili9328Properties.height - 1); // Window Vertical RAM Address End (R53h)
260 ili9328Command(ILI9328_COMMANDS_DRIVEROUTPUTCONTROL2, 0xa700); // Driver Output Control (R60h)
261 ili9328Command(ILI9328_COMMANDS_BASEIMAGEDISPLAYCONTROL, 0x0003); // Driver Output Control (R61h) - enable VLE
262 ili9328Command(ILI9328_COMMANDS_PANELINTERFACECONTROL1, 0X0010); // Panel Interface Control 1 (R90h)
263
264 // Display On
265 ili9328Command(ILI9328_COMMANDS_DISPLAYCONTROL1, 0x0133); // Display Control (R07h)
266 ili9328Delay(500);
267 ili9328WriteCmd(ILI9328_COMMANDS_WRITEDATATOGRAM);
268 }
269
270 /**************************************************************************/
271 /*!
272 @brief Sets the cursor to the home position (0,0)
273 */
274 /**************************************************************************/
275 void ili9328Home(void)
276 {
277 ili9328SetCursor(0, 0);
278 ili9328WriteCmd(ILI9328_COMMANDS_WRITEDATATOGRAM); // Write Data to GRAM (R22h)
279 }
280
281 /**************************************************************************/
282 /*!
283 @brief Sets the window confines
284 */
285 /**************************************************************************/
286 void ili9328SetWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
287 {
288 ili9328Command(ILI9328_COMMANDS_HORIZONTALADDRESSSTARTPOSITION, x0);
289 ili9328Command(ILI9328_COMMANDS_HORIZONTALADDRESSENDPOSITION, x1);
290 ili9328Command(ILI9328_COMMANDS_VERTICALADDRESSSTARTPOSITION, y0);
291 ili9328Command(ILI9328_COMMANDS_VERTICALADDRESSENDPOSITION, y1);
292 ili9328SetCursor(x0, y0);
293 }
294
295 /*************************************************/
296 /* Public Methods */
297 /*************************************************/
298
299 /**************************************************************************/
300 /*!
301 @brief Configures any pins or HW and initialises the LCD controller
302 */
303 /**************************************************************************/
304 void lcdInit(void)
305 {
306 // Set control line pins to output
307 gpioSetDir(ILI9328_CS_PORT, ILI9328_CS_PIN, 1);
308 gpioSetDir(ILI9328_CD_PORT, ILI9328_CD_PIN, 1);
309 gpioSetDir(ILI9328_WR_PORT, ILI9328_WR_PIN, 1);
310 gpioSetDir(ILI9328_RD_PORT, ILI9328_RD_PIN, 1);
311
312 // Set data port pins to output
313 ILI9328_GPIO2DATA_SETOUTPUT;
314
315 // Disable pullups
316 ILI9328_DISABLEPULLUPS();
317
318 // Set backlight pin to output and turn it on
319 gpioSetDir(ILI9328_BL_PORT, ILI9328_BL_PIN, 1); // set to output
320 lcdBacklight(TRUE);
321
322 // Set reset pin to output
323 gpioSetDir(ILI9328_RES_PORT, ILI9328_RES_PIN, 1); // Set to output
324 gpioSetValue(ILI9328_RES_PORT, ILI9328_RES_PIN, 0); // Low to reset
325 systickDelay(50);
326 gpioSetValue(ILI9328_RES_PORT, ILI9328_RES_PIN, 1); // High to exit
327
328 // Initialize the display
329 ili9328InitDisplay();
330
331 systickDelay(50);
332
333 // Set lcd to default orientation
334 lcdSetOrientation(lcdOrientation);
335
336 // Fill black
337 lcdFillRGB(COLOR_BLACK);
338
339 // Initialise the touch screen (and calibrate if necessary)
340 tsInit();
341 }
342
343 /**************************************************************************/
344 /*!
345 @brief Enables or disables the LCD backlight
346 */
347 /**************************************************************************/
348 void lcdBacklight(bool state)
349 {
350 // Set the backlight
351 gpioSetValue(ILI9328_BL_PORT, ILI9328_BL_PIN, state ? 0 : 1);
352 }
353
354 /**************************************************************************/
355 /*!
356 @brief Renders a simple test pattern on the LCD
357 */
358 /**************************************************************************/
359 void lcdTest(void)
360 {
361 uint32_t i,j;
362 ili9328Home();
363
364 for(i=0;i<320;i++)
365 {
366 for(j=0;j<240;j++)
367 {
368 if(i>279)ili9328WriteData(COLOR_WHITE);
369 else if(i>239)ili9328WriteData(COLOR_BLUE);
370 else if(i>199)ili9328WriteData(COLOR_GREEN);
371 else if(i>159)ili9328WriteData(COLOR_CYAN);
372 else if(i>119)ili9328WriteData(COLOR_RED);
373 else if(i>79)ili9328WriteData(COLOR_MAGENTA);
374 else if(i>39)ili9328WriteData(COLOR_YELLOW);
375 else ili9328WriteData(COLOR_BLACK);
376 }
377 }
378 }
379
380 /**************************************************************************/
381 /*!
382 @brief Fills the LCD with the specified 16-bit color
383 */
384 /**************************************************************************/
385 void lcdFillRGB(uint16_t data)
386 {
387 unsigned int i;
388 ili9328Home();
389
390 uint32_t pixels = 320*240;
391 for ( i=0; i < pixels; i++ )
392 {
393 ili9328WriteData(data);
394 }
395 }
396
397 /**************************************************************************/
398 /*!
399 @brief Draws a single pixel at the specified X/Y location
400 */
401 /**************************************************************************/
402 void lcdDrawPixel(uint16_t x, uint16_t y, uint16_t color)
403 {
404 ili9328SetCursor(x, y);
405 ili9328WriteCmd(ILI9328_COMMANDS_WRITEDATATOGRAM); // Write Data to GRAM (R22h)
406 ili9328WriteData(color);
407 }
408
409 /**************************************************************************/
410 /*!
411 @brief Draws an array of consecutive RGB565 pixels (much
412 faster than addressing each pixel individually)
413 */
414 /**************************************************************************/
415 void lcdDrawPixels(uint16_t x, uint16_t y, uint16_t *data, uint32_t len)
416 {
417 uint32_t i = 0;
418 ili9328SetCursor(x, y);
419 ili9328WriteCmd(ILI9328_COMMANDS_WRITEDATATOGRAM);
420 do
421 {
422 ili9328WriteData(data[i]);
423 i++;
424 } while (i<len);
425 }
426
427 /**************************************************************************/
428 /*!
429 @brief Optimised routine to draw a horizontal line faster than
430 setting individual pixels
431 */
432 /**************************************************************************/
433 void lcdDrawHLine(uint16_t x0, uint16_t x1, uint16_t y, uint16_t color)
434 {
435 // Allows for slightly better performance than setting individual pixels
436 uint16_t x, pixels;
437
438 if (x1 < x0)
439 {
440 // Switch x1 and x0
441 x = x1;
442 x1 = x0;
443 x0 = x;
444 }
445
446 // Check limits
447 if (x1 >= lcdGetWidth())
448 {
449 x1 = lcdGetWidth() - 1;
450 }
451 if (x0 >= lcdGetWidth())
452 {
453 x0 = lcdGetWidth() - 1;
454 }
455
456 ili9328SetCursor(x0, y);
457 ili9328WriteCmd(ILI9328_COMMANDS_WRITEDATATOGRAM); // Write Data to GRAM (R22h)
458 for (pixels = 0; pixels < x1 - x0 + 1; pixels++)
459 {
460 ili9328WriteData(color);
461 }
462 }
463
464 /**************************************************************************/
465 /*!
466 @brief Optimised routine to draw a vertical line faster than
467 setting individual pixels
468 */
469 /**************************************************************************/
470 void lcdDrawVLine(uint16_t x, uint16_t y0, uint16_t y1, uint16_t color)
471 {
472 lcdOrientation_t orientation = lcdOrientation;
473
474 // Switch orientation
475 lcdSetOrientation(orientation == LCD_ORIENTATION_PORTRAIT ? LCD_ORIENTATION_LANDSCAPE : LCD_ORIENTATION_PORTRAIT);
476
477 // Draw horizontal line like usual
478 lcdDrawHLine(y0, y1, lcdGetHeight() - (x + 1), color);
479
480 // Switch orientation back
481 lcdSetOrientation(orientation);
482 }
483
484 /**************************************************************************/
485 /*!
486 @brief Gets the 16-bit color of the pixel at the specified location
487 */
488 /**************************************************************************/
489 uint16_t lcdGetPixel(uint16_t x, uint16_t y)
490 {
491 uint16_t preFetch = 0;
492
493 ili9328SetCursor(x, y);
494 ili9328WriteCmd(ILI9328_COMMANDS_WRITEDATATOGRAM);
495 preFetch = ili9328ReadData();
496
497 // Eeek ... why does this need to be done twice for a proper value?!?
498 ili9328SetCursor(x, y);
499 ili9328WriteCmd(ILI9328_COMMANDS_WRITEDATATOGRAM);
500 return ili9328ReadData();
501 }
502
503 /**************************************************************************/
504 /*!
505 @brief Sets the LCD orientation to horizontal and vertical
506 */
507 /**************************************************************************/
508 void lcdSetOrientation(lcdOrientation_t orientation)
509 {
510 uint16_t entryMode = 0x1030;
511 uint16_t outputControl = 0x0100;
512
513 switch (orientation)
514 {
515 case LCD_ORIENTATION_PORTRAIT:
516 entryMode = 0x1030;
517 outputControl = 0x0100;
518 break;
519 case LCD_ORIENTATION_LANDSCAPE:
520 entryMode = 0x1028;
521 outputControl = 0x0000;
522 break;
523 }
524
525 ili9328Command(ILI9328_COMMANDS_ENTRYMODE, entryMode);
526 ili9328Command(ILI9328_COMMANDS_DRIVEROUTPUTCONTROL1, outputControl);
527 lcdOrientation = orientation;
528
529 ili9328SetCursor(0, 0);
530 }
531
532 /**************************************************************************/
533 /*!
534 @brief Gets the current screen orientation (horizontal or vertical)
535 */
536 /**************************************************************************/
537 lcdOrientation_t lcdGetOrientation(void)
538 {
539 return lcdOrientation;
540 }
541
542 /**************************************************************************/
543 /*!
544 @brief Gets the width in pixels of the LCD screen (varies depending
545 on the current screen orientation)
546 */
547 /**************************************************************************/
548 uint16_t lcdGetWidth(void)
549 {
550 switch (lcdOrientation)
551 {
552 case LCD_ORIENTATION_PORTRAIT:
553 return ili9328Properties.width;
554 break;
555 case LCD_ORIENTATION_LANDSCAPE:
556 default:
557 return ili9328Properties.height;
558 }
559 }
560
561 /**************************************************************************/
562 /*!
563 @brief Gets the height in pixels of the LCD screen (varies depending
564 on the current screen orientation)
565 */
566 /**************************************************************************/
567 uint16_t lcdGetHeight(void)
568 {
569 switch (lcdOrientation)
570 {
571 case LCD_ORIENTATION_PORTRAIT:
572 return ili9328Properties.height;
573 break;
574 case LCD_ORIENTATION_LANDSCAPE:
575 default:
576 return ili9328Properties.width;
577 }
578 }
579
580 /**************************************************************************/
581 /*!
582 @brief Scrolls the contents of the LCD screen vertically the
583 specified number of pixels using a HW optimised routine
584 */
585 /**************************************************************************/
586 void lcdScroll(int16_t pixels, uint16_t fillColor)
587 {
588 int16_t y = pixels;
589 while (y < 0)
590 y += 320;
591 while (y >= 320)
592 y -= 320;
593 ili9328WriteCmd(ILI9328_COMMANDS_VERTICALSCROLLCONTROL);
594 ili9328WriteData(y);
595 }
596
597 /**************************************************************************/
598 /*!
599 @brief Gets the controller's 16-bit (4 hexdigit) ID
600 */
601 /**************************************************************************/
602 uint16_t lcdGetControllerID(void)
603 {
604 return ili9328Type();
605 }
606
607 /**************************************************************************/
608 /*!
609 @brief Returns the LCDs 'lcdProperties_t' that describes the LCDs
610 generic capabilities and dimensions
611 */
612 /**************************************************************************/
613 lcdProperties_t lcdGetProperties(void)
614 {
615 return ili9328Properties;
616 }
This page took 0.106893 seconds and 5 git commands to generate.