Added backlight, reset, triangle and corner commands
[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 oldOrientation = lcdOrientation;
473
474 if (oldOrientation == LCD_ORIENTATION_PORTRAIT)
475 {
476 lcdSetOrientation(LCD_ORIENTATION_LANDSCAPE);
477 lcdDrawHLine(y0, y1, lcdGetHeight() - (x + 1), color);
478 }
479 else
480 {
481 lcdSetOrientation(LCD_ORIENTATION_PORTRAIT);
482 lcdDrawHLine(lcdGetWidth() - (y0 + 1), lcdGetWidth() - (y1 + 1), x, color);
483 }
484
485 // Switch orientation back
486 lcdSetOrientation(oldOrientation);
487 }
488
489 /**************************************************************************/
490 /*!
491 @brief Gets the 16-bit color of the pixel at the specified location
492 */
493 /**************************************************************************/
494 uint16_t lcdGetPixel(uint16_t x, uint16_t y)
495 {
496 ili9328SetCursor(x, y);
497 ili9328WriteCmd(ILI9328_COMMANDS_WRITEDATATOGRAM);
498 // prefetch
499 ili9328ReadData();
500
501 // Eeek ... why does this need to be done twice for a proper value?!?
502 ili9328SetCursor(x, y);
503 ili9328WriteCmd(ILI9328_COMMANDS_WRITEDATATOGRAM);
504 return ili9328ReadData();
505 }
506
507 /**************************************************************************/
508 /*!
509 @brief Sets the LCD orientation to horizontal and vertical
510 */
511 /**************************************************************************/
512 void lcdSetOrientation(lcdOrientation_t orientation)
513 {
514 uint16_t entryMode = 0x1030;
515 uint16_t outputControl = 0x0100;
516
517 switch (orientation)
518 {
519 case LCD_ORIENTATION_PORTRAIT:
520 entryMode = 0x1030;
521 outputControl = 0x0100;
522 break;
523 case LCD_ORIENTATION_LANDSCAPE:
524 entryMode = 0x1028;
525 outputControl = 0x0000;
526 break;
527 }
528
529 ili9328Command(ILI9328_COMMANDS_ENTRYMODE, entryMode);
530 ili9328Command(ILI9328_COMMANDS_DRIVEROUTPUTCONTROL1, outputControl);
531 lcdOrientation = orientation;
532
533 ili9328SetCursor(0, 0);
534 }
535
536 /**************************************************************************/
537 /*!
538 @brief Gets the current screen orientation (horizontal or vertical)
539 */
540 /**************************************************************************/
541 lcdOrientation_t lcdGetOrientation(void)
542 {
543 return lcdOrientation;
544 }
545
546 /**************************************************************************/
547 /*!
548 @brief Gets the width in pixels of the LCD screen (varies depending
549 on the current screen orientation)
550 */
551 /**************************************************************************/
552 uint16_t lcdGetWidth(void)
553 {
554 switch (lcdOrientation)
555 {
556 case LCD_ORIENTATION_PORTRAIT:
557 return ili9328Properties.width;
558 break;
559 case LCD_ORIENTATION_LANDSCAPE:
560 default:
561 return ili9328Properties.height;
562 }
563 }
564
565 /**************************************************************************/
566 /*!
567 @brief Gets the height in pixels of the LCD screen (varies depending
568 on the current screen orientation)
569 */
570 /**************************************************************************/
571 uint16_t lcdGetHeight(void)
572 {
573 switch (lcdOrientation)
574 {
575 case LCD_ORIENTATION_PORTRAIT:
576 return ili9328Properties.height;
577 break;
578 case LCD_ORIENTATION_LANDSCAPE:
579 default:
580 return ili9328Properties.width;
581 }
582 }
583
584 /**************************************************************************/
585 /*!
586 @brief Scrolls the contents of the LCD screen vertically the
587 specified number of pixels using a HW optimised routine
588 */
589 /**************************************************************************/
590 void lcdScroll(int16_t pixels, uint16_t fillColor)
591 {
592 int16_t y = pixels;
593 while (y < 0)
594 y += 320;
595 while (y >= 320)
596 y -= 320;
597 ili9328WriteCmd(ILI9328_COMMANDS_VERTICALSCROLLCONTROL);
598 ili9328WriteData(y);
599 }
600
601 /**************************************************************************/
602 /*!
603 @brief Gets the controller's 16-bit (4 hexdigit) ID
604 */
605 /**************************************************************************/
606 uint16_t lcdGetControllerID(void)
607 {
608 return ili9328Type();
609 }
610
611 /**************************************************************************/
612 /*!
613 @brief Returns the LCDs 'lcdProperties_t' that describes the LCDs
614 generic capabilities and dimensions
615 */
616 /**************************************************************************/
617 lcdProperties_t lcdGetProperties(void)
618 {
619 return ili9328Properties;
620 }
This page took 0.079008 seconds and 5 git commands to generate.