1 /**************************************************************************/
4 @author K. Townsend (microBuilder.eu)
8 Driver for ILI9328 240x320 pixel TFT LCD displays.
10 This driver uses an 8-bit interface and a 16-bit RGB565 colour palette.
14 Software License Agreement (BSD License)
16 Copyright (c) 2010, microBuilder SARL
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.
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.
41 /**************************************************************************/
43 #include "core/systick/systick.h"
44 #include "drivers/lcd/tft/touchscreen.h"
46 static volatile lcdOrientation_t lcdOrientation
= LCD_ORIENTATION_PORTRAIT
;
47 static lcdProperties_t ili9328Properties
= { 240, 320, TRUE
, TRUE
, TRUE
};
49 /*************************************************/
51 /*************************************************/
53 /**************************************************************************/
55 @brief Causes a brief delay (10 ticks per unit)
57 /**************************************************************************/
58 void ili9328Delay(unsigned int t
)
62 for ( t1
=10; t1
> 0; t1
-- )
68 /**************************************************************************/
70 @brief Writes the supplied 16-bit command using an 8-bit interface
72 /**************************************************************************/
73 void ili9328WriteCmd(uint16_t command
)
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).
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
));
86 ILI9328_GPIO2DATA_DATA
= command
<< ILI9328_DATA_OFFSET
;
88 SET_WR_CS
; // Saves 7 commands compared to "SET_WR; SET_CS;"
91 /**************************************************************************/
93 @brief Writes the supplied 16-bit data using an 8-bit interface
95 /**************************************************************************/
96 void ili9328WriteData(uint16_t data
)
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
));
102 ILI9328_GPIO2DATA_DATA
= data
<< ILI9328_DATA_OFFSET
;
104 SET_WR_CS
; // Saves 7 commands compared to "SET_WR, SET_CS;"
107 /**************************************************************************/
109 @brief Reads a 16-bit value from the 8-bit data bus
111 /**************************************************************************/
112 uint16_t ili9328ReadData(void)
114 // ToDo: Optimise this method!
120 SET_CD_RD_WR
; // Saves 14 commands compared to "SET_CD; SET_RD; SET_WR"
124 ILI9328_GPIO2DATA_SETINPUT
;
127 high
= ILI9328_GPIO2DATA_DATA
;
128 high
>>= ILI9328_DATA_OFFSET
;
134 low
= ILI9328_GPIO2DATA_DATA
;
135 low
>>= ILI9328_DATA_OFFSET
;
140 ILI9328_GPIO2DATA_SETOUTPUT
;
149 /**************************************************************************/
151 @brief Reads a 16-bit value
153 /**************************************************************************/
154 uint16_t ili9328Read(uint16_t addr
)
156 ili9328WriteCmd(addr
);
157 return ili9328ReadData();
160 /**************************************************************************/
162 @brief Sends a 16-bit command + 16-bit data
164 /**************************************************************************/
165 void ili9328Command(uint16_t command
, uint16_t data
)
167 ili9328WriteCmd(command
);
168 ili9328WriteData(data
);
171 /**************************************************************************/
173 @brief Returns the 16-bit (4-hexdigit) controller code
175 /**************************************************************************/
176 uint16_t ili9328Type(void)
178 ili9328WriteCmd(ILI9328_COMMANDS_DRIVERCODEREAD
);
179 return ili9328ReadData();
182 /**************************************************************************/
184 @brief Sets the cursor to the specified X/Y position
186 /**************************************************************************/
187 void ili9328SetCursor(uint16_t x
, uint16_t y
)
191 if (lcdOrientation
== LCD_ORIENTATION_LANDSCAPE
)
202 ili9328Command(ILI9328_COMMANDS_HORIZONTALGRAMADDRESSSET
, al
);
203 ili9328Command(ILI9328_COMMANDS_VERTICALGRAMADDRESSSET
, ah
);
206 /**************************************************************************/
208 @brief Sends the initialisation sequence to the display controller
210 /**************************************************************************/
211 void ili9328InitDisplay(void)
214 GPIO_GPIO2DATA
&= ~ILI9328_DATA_MASK
;
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)
238 ili9328Command(ILI9328_COMMANDS_POWERCONTROL1
, 0x14B0); // Power Control 1 (R10h)
240 ili9328Command(ILI9328_COMMANDS_POWERCONTROL2
, 0x0007); // Power Control 2 (R11h)
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)
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)
265 ili9328Command(ILI9328_COMMANDS_DISPLAYCONTROL1
, 0x0133); // Display Control (R07h)
267 ili9328WriteCmd(ILI9328_COMMANDS_WRITEDATATOGRAM
);
270 /**************************************************************************/
272 @brief Sets the cursor to the home position (0,0)
274 /**************************************************************************/
275 void ili9328Home(void)
277 ili9328SetCursor(0, 0);
278 ili9328WriteCmd(ILI9328_COMMANDS_WRITEDATATOGRAM
); // Write Data to GRAM (R22h)
281 /**************************************************************************/
283 @brief Sets the window confines
285 /**************************************************************************/
286 void ili9328SetWindow(uint16_t x0
, uint16_t y0
, uint16_t x1
, uint16_t y1
)
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
);
295 /*************************************************/
297 /*************************************************/
299 /**************************************************************************/
301 @brief Configures any pins or HW and initialises the LCD controller
303 /**************************************************************************/
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);
312 // Set data port pins to output
313 ILI9328_GPIO2DATA_SETOUTPUT
;
316 ILI9328_DISABLEPULLUPS();
318 // Set backlight pin to output and turn it on
319 gpioSetDir(ILI9328_BL_PORT
, ILI9328_BL_PIN
, 1); // set to output
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
326 gpioSetValue(ILI9328_RES_PORT
, ILI9328_RES_PIN
, 1); // High to exit
328 // Initialize the display
329 ili9328InitDisplay();
333 // Set lcd to default orientation
334 lcdSetOrientation(lcdOrientation
);
337 lcdFillRGB(COLOR_BLACK
);
339 // Initialise the touch screen (and calibrate if necessary)
343 /**************************************************************************/
345 @brief Enables or disables the LCD backlight
347 /**************************************************************************/
348 void lcdBacklight(bool state
)
351 gpioSetValue(ILI9328_BL_PORT
, ILI9328_BL_PIN
, state
? 0 : 1);
354 /**************************************************************************/
356 @brief Renders a simple test pattern on the LCD
358 /**************************************************************************/
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
);
380 /**************************************************************************/
382 @brief Fills the LCD with the specified 16-bit color
384 /**************************************************************************/
385 void lcdFillRGB(uint16_t data
)
390 uint32_t pixels
= 320*240;
391 for ( i
=0; i
< pixels
; i
++ )
393 ili9328WriteData(data
);
397 /**************************************************************************/
399 @brief Draws a single pixel at the specified X/Y location
401 /**************************************************************************/
402 void lcdDrawPixel(uint16_t x
, uint16_t y
, uint16_t color
)
404 ili9328SetCursor(x
, y
);
405 ili9328WriteCmd(ILI9328_COMMANDS_WRITEDATATOGRAM
); // Write Data to GRAM (R22h)
406 ili9328WriteData(color
);
409 /**************************************************************************/
411 @brief Draws an array of consecutive RGB565 pixels (much
412 faster than addressing each pixel individually)
414 /**************************************************************************/
415 void lcdDrawPixels(uint16_t x
, uint16_t y
, uint16_t *data
, uint32_t len
)
418 ili9328SetCursor(x
, y
);
419 ili9328WriteCmd(ILI9328_COMMANDS_WRITEDATATOGRAM
);
422 ili9328WriteData(data
[i
]);
427 /**************************************************************************/
429 @brief Optimised routine to draw a horizontal line faster than
430 setting individual pixels
432 /**************************************************************************/
433 void lcdDrawHLine(uint16_t x0
, uint16_t x1
, uint16_t y
, uint16_t color
)
435 // Allows for slightly better performance than setting individual pixels
447 if (x1
>= lcdGetWidth())
449 x1
= lcdGetWidth() - 1;
451 if (x0
>= lcdGetWidth())
453 x0
= lcdGetWidth() - 1;
456 ili9328SetCursor(x0
, y
);
457 ili9328WriteCmd(ILI9328_COMMANDS_WRITEDATATOGRAM
); // Write Data to GRAM (R22h)
458 for (pixels
= 0; pixels
< x1
- x0
+ 1; pixels
++)
460 ili9328WriteData(color
);
464 /**************************************************************************/
466 @brief Optimised routine to draw a vertical line faster than
467 setting individual pixels
469 /**************************************************************************/
470 void lcdDrawVLine(uint16_t x
, uint16_t y0
, uint16_t y1
, uint16_t color
)
472 lcdOrientation_t orientation
= lcdOrientation
;
474 // Switch orientation
475 lcdSetOrientation(orientation
== LCD_ORIENTATION_PORTRAIT
? LCD_ORIENTATION_LANDSCAPE
: LCD_ORIENTATION_PORTRAIT
);
477 // Draw horizontal line like usual
478 lcdDrawHLine(y0
, y1
, lcdGetHeight() - (x
+ 1), color
);
480 // Switch orientation back
481 lcdSetOrientation(orientation
);
484 /**************************************************************************/
486 @brief Gets the 16-bit color of the pixel at the specified location
488 /**************************************************************************/
489 uint16_t lcdGetPixel(uint16_t x
, uint16_t y
)
491 uint16_t preFetch
= 0;
493 ili9328SetCursor(x
, y
);
494 ili9328WriteCmd(ILI9328_COMMANDS_WRITEDATATOGRAM
);
495 preFetch
= ili9328ReadData();
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();
503 /**************************************************************************/
505 @brief Sets the LCD orientation to horizontal and vertical
507 /**************************************************************************/
508 void lcdSetOrientation(lcdOrientation_t orientation
)
510 uint16_t entryMode
= 0x1030;
511 uint16_t outputControl
= 0x0100;
515 case LCD_ORIENTATION_PORTRAIT
:
517 outputControl
= 0x0100;
519 case LCD_ORIENTATION_LANDSCAPE
:
521 outputControl
= 0x0000;
525 ili9328Command(ILI9328_COMMANDS_ENTRYMODE
, entryMode
);
526 ili9328Command(ILI9328_COMMANDS_DRIVEROUTPUTCONTROL1
, outputControl
);
527 lcdOrientation
= orientation
;
529 ili9328SetCursor(0, 0);
532 /**************************************************************************/
534 @brief Gets the current screen orientation (horizontal or vertical)
536 /**************************************************************************/
537 lcdOrientation_t
lcdGetOrientation(void)
539 return lcdOrientation
;
542 /**************************************************************************/
544 @brief Gets the width in pixels of the LCD screen (varies depending
545 on the current screen orientation)
547 /**************************************************************************/
548 uint16_t lcdGetWidth(void)
550 switch (lcdOrientation
)
552 case LCD_ORIENTATION_PORTRAIT
:
553 return ili9328Properties
.width
;
555 case LCD_ORIENTATION_LANDSCAPE
:
557 return ili9328Properties
.height
;
561 /**************************************************************************/
563 @brief Gets the height in pixels of the LCD screen (varies depending
564 on the current screen orientation)
566 /**************************************************************************/
567 uint16_t lcdGetHeight(void)
569 switch (lcdOrientation
)
571 case LCD_ORIENTATION_PORTRAIT
:
572 return ili9328Properties
.height
;
574 case LCD_ORIENTATION_LANDSCAPE
:
576 return ili9328Properties
.width
;
580 /**************************************************************************/
582 @brief Scrolls the contents of the LCD screen vertically the
583 specified number of pixels using a HW optimised routine
585 /**************************************************************************/
586 void lcdScroll(int16_t pixels
, uint16_t fillColor
)
593 ili9328WriteCmd(ILI9328_COMMANDS_VERTICALSCROLLCONTROL
);
597 /**************************************************************************/
599 @brief Gets the controller's 16-bit (4 hexdigit) ID
601 /**************************************************************************/
602 uint16_t lcdGetControllerID(void)
604 return ili9328Type();
607 /**************************************************************************/
609 @brief Returns the LCDs 'lcdProperties_t' that describes the LCDs
610 generic capabilities and dimensions
612 /**************************************************************************/
613 lcdProperties_t
lcdGetProperties(void)
615 return ili9328Properties
;