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/displays/tft/touchscreen.h"
46 // Uncomment this to use faster inline methods, but requires more flash
47 #define ILI9238_USE_INLINE_METHODS (1)
49 static volatile lcdOrientation_t lcdOrientation
= LCD_ORIENTATION_PORTRAIT
;
50 static lcdProperties_t ili9328Properties
= { 240, 320, true, true, true, true, true };
52 /*************************************************/
54 /*************************************************/
56 /**************************************************************************/
58 @brief Causes a brief delay (10 ticks per unit)
60 /**************************************************************************/
61 #if !defined ILI9238_USE_INLINE_METHODS
62 void ili9328Delay(unsigned int t
)
66 for ( t1
=10; t1
> 0; t1
-- )
72 static inline void ili9328Delay(unsigned int t
) { unsigned char t1
; while(t
--) for ( t1
=10; t1
> 0; t1
-- ) { __asm("nop"); } }
75 /**************************************************************************/
77 @brief Writes the supplied 16-bit command using an 8-bit interface
79 /**************************************************************************/
80 #if !defined ILI9238_USE_INLINE_METHODS
81 void ili9328WriteCmd(uint16_t command
)
83 // Compiled with -Os on GCC 4.4 this works out to 25 cycles
84 // (versus 36 compiled with no optimisations). I'm not sure it
85 // can be improved further, so that means 25 cycles/350nS for
86 // continuous writes (cmd, data, data, data, ...) or ~150 cycles/
87 // ~2.1uS for a random pixel (Set X [cmd+data], Set Y [cmd+data],
88 // Set color [cmd+data]) (times assumes 72MHz clock).
90 CLR_CS_CD_SET_RD_WR
; // Saves 18 commands compared to "CLR_CS; CLR_CD; SET_RD; SET_WR;"
91 ILI9328_GPIO2DATA_DATA
= (command
>> (8 - ILI9328_DATA_OFFSET
));
94 ILI9328_GPIO2DATA_DATA
= command
<< ILI9328_DATA_OFFSET
;
96 SET_WR_CS
; // Saves 7 commands compared to "SET_WR; SET_CS;"
99 static inline void ili9328WriteCmd(uint16_t command
) { CLR_CS_CD_SET_RD_WR
; ILI9328_GPIO2DATA_DATA
= (command
>> (8 - ILI9328_DATA_OFFSET
)); CLR_WR
; SET_WR
; ILI9328_GPIO2DATA_DATA
= command
<< ILI9328_DATA_OFFSET
; CLR_WR
; SET_WR_CS
; }
102 /**************************************************************************/
104 @brief Writes the supplied 16-bit data using an 8-bit interface
106 /**************************************************************************/
107 #if !defined ILI9238_USE_INLINE_METHODS
108 void ili9328WriteData(uint16_t data
)
110 CLR_CS_SET_CD_RD_WR
; // Saves 18 commands compared to SET_CD; SET_RD; SET_WR; CLR_CS"
111 ILI9328_GPIO2DATA_DATA
= (data
>> (8 - ILI9328_DATA_OFFSET
));
114 ILI9328_GPIO2DATA_DATA
= data
<< ILI9328_DATA_OFFSET
;
116 SET_WR_CS
; // Saves 7 commands compared to "SET_WR, SET_CS;"
119 static inline void ili9328WriteData(uint16_t data
) { CLR_CS_SET_CD_RD_WR
; ILI9328_GPIO2DATA_DATA
= (data
>> (8 - ILI9328_DATA_OFFSET
)); CLR_WR
; SET_WR
; ILI9328_GPIO2DATA_DATA
= data
<< ILI9328_DATA_OFFSET
; CLR_WR
; SET_WR_CS
; }
122 /**************************************************************************/
124 @brief Reads a 16-bit value from the 8-bit data bus
126 /**************************************************************************/
127 uint16_t ili9328ReadData(void)
129 // ToDo: Optimise this method!
135 SET_CD_RD_WR
; // Saves 14 commands compared to "SET_CD; SET_RD; SET_WR"
139 ILI9328_GPIO2DATA_SETINPUT
;
142 high
= ILI9328_GPIO2DATA_DATA
;
143 high
>>= ILI9328_DATA_OFFSET
;
149 low
= ILI9328_GPIO2DATA_DATA
;
150 low
>>= ILI9328_DATA_OFFSET
;
155 ILI9328_GPIO2DATA_SETOUTPUT
;
164 /**************************************************************************/
166 @brief Reads a 16-bit value
168 /**************************************************************************/
169 uint16_t ili9328Read(uint16_t addr
)
171 ili9328WriteCmd(addr
);
172 return ili9328ReadData();
175 /**************************************************************************/
177 @brief Sends a 16-bit command + 16-bit data
179 /**************************************************************************/
180 void ili9328Command(uint16_t command
, uint16_t data
)
182 ili9328WriteCmd(command
);
183 ili9328WriteData(data
);
186 /**************************************************************************/
188 @brief Returns the 16-bit (4-hexdigit) controller code
190 /**************************************************************************/
191 uint16_t ili9328Type(void)
193 ili9328WriteCmd(ILI9328_COMMANDS_DRIVERCODEREAD
);
194 return ili9328ReadData();
197 /**************************************************************************/
199 @brief Sets the cursor to the specified X/Y position
201 /**************************************************************************/
202 #if !defined ILI9238_USE_INLINE_METHODS
203 void ili9328SetCursor(uint16_t x
, uint16_t y
)
207 if (lcdOrientation
== LCD_ORIENTATION_LANDSCAPE
)
218 ili9328Command(ILI9328_COMMANDS_HORIZONTALGRAMADDRESSSET
, al
);
219 ili9328Command(ILI9328_COMMANDS_VERTICALGRAMADDRESSSET
, ah
);
222 static inline void ili9328SetCursor(uint16_t x
, uint16_t y
) { uint16_t al
, ah
; if (lcdOrientation
== LCD_ORIENTATION_LANDSCAPE
) { al
= y
; ah
= x
; } else { al
= x
; ah
= y
; }; ili9328WriteCmd(ILI9328_COMMANDS_HORIZONTALGRAMADDRESSSET
); ili9328WriteData(al
); ili9328WriteCmd(ILI9328_COMMANDS_VERTICALGRAMADDRESSSET
); ili9328WriteData(ah
); }
225 /**************************************************************************/
227 @brief Sends the initialisation sequence to the display controller
229 /**************************************************************************/
230 void ili9328InitDisplay(void)
233 GPIO_GPIO2DATA
&= ~ILI9328_DATA_MASK
;
246 ili9328Command(ILI9328_COMMANDS_DRIVEROUTPUTCONTROL1
, 0x0100); // Driver Output Control Register (R01h)
247 ili9328Command(ILI9328_COMMANDS_LCDDRIVINGCONTROL
, 0x0700); // LCD Driving Waveform Control (R02h)
248 ili9328Command(ILI9328_COMMANDS_ENTRYMODE
, 0x1030); // Entry Mode (R03h)
249 ili9328Command(ILI9328_COMMANDS_DISPLAYCONTROL2
, 0x0302);
250 ili9328Command(ILI9328_COMMANDS_DISPLAYCONTROL3
, 0x0000);
251 ili9328Command(ILI9328_COMMANDS_DISPLAYCONTROL4
, 0x0000); // Fmark On
252 ili9328Command(ILI9328_COMMANDS_POWERCONTROL1
, 0x0000); // Power Control 1 (R10h)
253 ili9328Command(ILI9328_COMMANDS_POWERCONTROL2
, 0x0007); // Power Control 2 (R11h)
254 ili9328Command(ILI9328_COMMANDS_POWERCONTROL3
, 0x0000); // Power Control 3 (R12h)
255 ili9328Command(ILI9328_COMMANDS_POWERCONTROL4
, 0x0000); // Power Control 4 (R13h)
257 ili9328Command(ILI9328_COMMANDS_POWERCONTROL1
, 0x14B0); // Power Control 1 (R10h)
259 ili9328Command(ILI9328_COMMANDS_POWERCONTROL2
, 0x0007); // Power Control 2 (R11h)
261 ili9328Command(ILI9328_COMMANDS_POWERCONTROL3
, 0x008E); // Power Control 3 (R12h)
262 ili9328Command(ILI9328_COMMANDS_POWERCONTROL4
, 0x0C00); // Power Control 4 (R13h)
263 ili9328Command(ILI9328_COMMANDS_POWERCONTROL7
, 0x0015); // NVM read data 2 (R29h)
265 ili9328Command(ILI9328_COMMANDS_GAMMACONTROL1
, 0x0000); // Gamma Control 1
266 ili9328Command(ILI9328_COMMANDS_GAMMACONTROL2
, 0x0107); // Gamma Control 2
267 ili9328Command(ILI9328_COMMANDS_GAMMACONTROL3
, 0x0000); // Gamma Control 3
268 ili9328Command(ILI9328_COMMANDS_GAMMACONTROL4
, 0x0203); // Gamma Control 4
269 ili9328Command(ILI9328_COMMANDS_GAMMACONTROL5
, 0x0402); // Gamma Control 5
270 ili9328Command(ILI9328_COMMANDS_GAMMACONTROL6
, 0x0000); // Gamma Control 6
271 ili9328Command(ILI9328_COMMANDS_GAMMACONTROL7
, 0x0207); // Gamma Control 7
272 ili9328Command(ILI9328_COMMANDS_GAMMACONTROL8
, 0x0000); // Gamma Control 8
273 ili9328Command(ILI9328_COMMANDS_GAMMACONTROL9
, 0x0203); // Gamma Control 9
274 ili9328Command(ILI9328_COMMANDS_GAMMACONTROL10
, 0x0403); // Gamma Control 10
275 ili9328Command(ILI9328_COMMANDS_HORIZONTALADDRESSSTARTPOSITION
, 0x0000); // Window Horizontal RAM Address Start (R50h)
276 ili9328Command(ILI9328_COMMANDS_HORIZONTALADDRESSENDPOSITION
, ili9328Properties
.width
- 1); // Window Horizontal RAM Address End (R51h)
277 ili9328Command(ILI9328_COMMANDS_VERTICALADDRESSSTARTPOSITION
, 0X0000); // Window Vertical RAM Address Start (R52h)
278 ili9328Command(ILI9328_COMMANDS_VERTICALADDRESSENDPOSITION
, ili9328Properties
.height
- 1); // Window Vertical RAM Address End (R53h)
279 ili9328Command(ILI9328_COMMANDS_DRIVEROUTPUTCONTROL2
, 0xa700); // Driver Output Control (R60h)
280 ili9328Command(ILI9328_COMMANDS_BASEIMAGEDISPLAYCONTROL
, 0x0003); // Driver Output Control (R61h) - enable VLE
281 ili9328Command(ILI9328_COMMANDS_PANELINTERFACECONTROL1
, 0X0010); // Panel Interface Control 1 (R90h)
284 ili9328Command(ILI9328_COMMANDS_DISPLAYCONTROL1
, 0x0133); // Display Control (R07h)
286 ili9328WriteCmd(ILI9328_COMMANDS_WRITEDATATOGRAM
);
289 /**************************************************************************/
291 @brief Sets the cursor to the home position (0,0)
293 /**************************************************************************/
294 void ili9328Home(void)
296 ili9328SetCursor(0, 0);
297 ili9328WriteCmd(ILI9328_COMMANDS_WRITEDATATOGRAM
); // Write Data to GRAM (R22h)
300 /**************************************************************************/
302 @brief Sets the window confines
304 /**************************************************************************/
305 void ili9328SetWindow(uint16_t x0
, uint16_t y0
, uint16_t x1
, uint16_t y1
)
307 ili9328Command(ILI9328_COMMANDS_HORIZONTALADDRESSSTARTPOSITION
, x0
);
308 ili9328Command(ILI9328_COMMANDS_HORIZONTALADDRESSENDPOSITION
, x1
);
309 ili9328Command(ILI9328_COMMANDS_VERTICALADDRESSSTARTPOSITION
, y0
);
310 ili9328Command(ILI9328_COMMANDS_VERTICALADDRESSENDPOSITION
, y1
);
311 ili9328SetCursor(x0
, y0
);
314 /*************************************************/
316 /*************************************************/
318 /**************************************************************************/
320 @brief Configures any pins or HW and initialises the LCD controller
322 /**************************************************************************/
325 // Set control line pins to output
326 gpioSetDir(ILI9328_CS_PORT
, ILI9328_CS_PIN
, 1);
327 gpioSetDir(ILI9328_CD_PORT
, ILI9328_CD_PIN
, 1);
328 gpioSetDir(ILI9328_WR_PORT
, ILI9328_WR_PIN
, 1);
329 gpioSetDir(ILI9328_RD_PORT
, ILI9328_RD_PIN
, 1);
331 // Set data port pins to output
332 ILI9328_GPIO2DATA_SETOUTPUT
;
335 ILI9328_DISABLEPULLUPS();
337 // Set backlight pin to output and turn it on
338 gpioSetDir(ILI9328_BL_PORT
, ILI9328_BL_PIN
, 1); // set to output
341 // Set reset pin to output
342 gpioSetDir(ILI9328_RES_PORT
, ILI9328_RES_PIN
, 1); // Set to output
343 gpioSetValue(ILI9328_RES_PORT
, ILI9328_RES_PIN
, 0); // Low to reset
345 gpioSetValue(ILI9328_RES_PORT
, ILI9328_RES_PIN
, 1); // High to exit
347 // Initialize the display
348 ili9328InitDisplay();
352 // Set lcd to default orientation
353 lcdSetOrientation(lcdOrientation
);
356 lcdFillRGB(COLOR_BLACK
);
358 // Initialise the touch screen (and calibrate if necessary)
362 /**************************************************************************/
364 @brief Enables or disables the LCD backlight
366 /**************************************************************************/
367 void lcdBacklight(bool state
)
370 gpioSetValue(ILI9328_BL_PORT
, ILI9328_BL_PIN
, state
? 0 : 1);
373 /**************************************************************************/
375 @brief Renders a simple test pattern on the LCD
377 /**************************************************************************/
387 if(i
>279)ili9328WriteData(COLOR_WHITE
);
388 else if(i
>239)ili9328WriteData(COLOR_BLUE
);
389 else if(i
>199)ili9328WriteData(COLOR_GREEN
);
390 else if(i
>159)ili9328WriteData(COLOR_CYAN
);
391 else if(i
>119)ili9328WriteData(COLOR_RED
);
392 else if(i
>79)ili9328WriteData(COLOR_MAGENTA
);
393 else if(i
>39)ili9328WriteData(COLOR_YELLOW
);
394 else ili9328WriteData(COLOR_BLACK
);
399 /**************************************************************************/
401 @brief Fills the LCD with the specified 16-bit color
403 /**************************************************************************/
404 void lcdFillRGB(uint16_t data
)
409 uint32_t pixels
= 320*240;
410 for ( i
=0; i
< pixels
; i
++ )
412 ili9328WriteData(data
);
416 /**************************************************************************/
418 @brief Draws a single pixel at the specified X/Y location
420 /**************************************************************************/
421 void lcdDrawPixel(uint16_t x
, uint16_t y
, uint16_t color
)
423 ili9328SetCursor(x
, y
);
424 ili9328WriteCmd(ILI9328_COMMANDS_WRITEDATATOGRAM
); // Write Data to GRAM (R22h)
425 ili9328WriteData(color
);
428 /**************************************************************************/
430 @brief Draws an array of consecutive RGB565 pixels (much
431 faster than addressing each pixel individually)
433 /**************************************************************************/
434 void lcdDrawPixels(uint16_t x
, uint16_t y
, uint16_t *data
, uint32_t len
)
437 ili9328SetCursor(x
, y
);
438 ili9328WriteCmd(ILI9328_COMMANDS_WRITEDATATOGRAM
);
441 ili9328WriteData(data
[i
]);
446 /**************************************************************************/
448 @brief Optimised routine to draw a horizontal line faster than
449 setting individual pixels
451 /**************************************************************************/
452 void lcdDrawHLine(uint16_t x0
, uint16_t x1
, uint16_t y
, uint16_t color
)
454 // Allows for slightly better performance than setting individual pixels
466 if (x1
>= lcdGetWidth())
468 x1
= lcdGetWidth() - 1;
470 if (x0
>= lcdGetWidth())
472 x0
= lcdGetWidth() - 1;
475 ili9328SetCursor(x0
, y
);
476 ili9328WriteCmd(ILI9328_COMMANDS_WRITEDATATOGRAM
); // Write Data to GRAM (R22h)
477 for (pixels
= 0; pixels
< x1
- x0
+ 1; pixels
++)
479 ili9328WriteData(color
);
483 /**************************************************************************/
485 @brief Optimised routine to draw a vertical line faster than
486 setting individual pixels
488 /**************************************************************************/
489 void lcdDrawVLine(uint16_t x
, uint16_t y0
, uint16_t y1
, uint16_t color
)
491 lcdOrientation_t oldOrientation
= lcdOrientation
;
493 if (oldOrientation
== LCD_ORIENTATION_PORTRAIT
)
495 lcdSetOrientation(LCD_ORIENTATION_LANDSCAPE
);
496 lcdDrawHLine(y0
, y1
, lcdGetHeight() - (x
+ 1), color
);
500 lcdSetOrientation(LCD_ORIENTATION_PORTRAIT
);
501 lcdDrawHLine(lcdGetWidth() - (y0
+ 1), lcdGetWidth() - (y1
+ 1), x
, color
);
504 // Switch orientation back
505 lcdSetOrientation(oldOrientation
);
508 /**************************************************************************/
510 @brief Gets the 16-bit color of the pixel at the specified location
512 /**************************************************************************/
513 uint16_t lcdGetPixel(uint16_t x
, uint16_t y
)
515 ili9328SetCursor(x
, y
);
516 ili9328WriteCmd(ILI9328_COMMANDS_WRITEDATATOGRAM
);
520 // Eeek ... why does this need to be done twice for a proper value?!?
521 ili9328SetCursor(x
, y
);
522 ili9328WriteCmd(ILI9328_COMMANDS_WRITEDATATOGRAM
);
523 return ili9328ReadData();
526 /**************************************************************************/
528 @brief Sets the LCD orientation to horizontal and vertical
530 /**************************************************************************/
531 void lcdSetOrientation(lcdOrientation_t orientation
)
533 uint16_t entryMode
= 0x1030;
534 uint16_t outputControl
= 0x0100;
538 case LCD_ORIENTATION_PORTRAIT
:
540 outputControl
= 0x0100;
542 case LCD_ORIENTATION_LANDSCAPE
:
544 outputControl
= 0x0000;
548 ili9328Command(ILI9328_COMMANDS_ENTRYMODE
, entryMode
);
549 ili9328Command(ILI9328_COMMANDS_DRIVEROUTPUTCONTROL1
, outputControl
);
550 lcdOrientation
= orientation
;
552 ili9328SetCursor(0, 0);
555 /**************************************************************************/
557 @brief Gets the current screen orientation (horizontal or vertical)
559 /**************************************************************************/
560 lcdOrientation_t
lcdGetOrientation(void)
562 return lcdOrientation
;
565 /**************************************************************************/
567 @brief Gets the width in pixels of the LCD screen (varies depending
568 on the current screen orientation)
570 /**************************************************************************/
571 uint16_t lcdGetWidth(void)
573 switch (lcdOrientation
)
575 case LCD_ORIENTATION_PORTRAIT
:
576 return ili9328Properties
.width
;
578 case LCD_ORIENTATION_LANDSCAPE
:
580 return ili9328Properties
.height
;
584 /**************************************************************************/
586 @brief Gets the height in pixels of the LCD screen (varies depending
587 on the current screen orientation)
589 /**************************************************************************/
590 uint16_t lcdGetHeight(void)
592 switch (lcdOrientation
)
594 case LCD_ORIENTATION_PORTRAIT
:
595 return ili9328Properties
.height
;
597 case LCD_ORIENTATION_LANDSCAPE
:
599 return ili9328Properties
.width
;
603 /**************************************************************************/
605 @brief Scrolls the contents of the LCD screen vertically the
606 specified number of pixels using a HW optimised routine
608 /**************************************************************************/
609 void lcdScroll(int16_t pixels
, uint16_t fillColor
)
616 ili9328WriteCmd(ILI9328_COMMANDS_VERTICALSCROLLCONTROL
);
620 /**************************************************************************/
622 @brief Gets the controller's 16-bit (4 hexdigit) ID
624 /**************************************************************************/
625 uint16_t lcdGetControllerID(void)
627 return ili9328Type();
630 /**************************************************************************/
632 @brief Returns the LCDs 'lcdProperties_t' that describes the LCDs
633 generic capabilities and dimensions
635 /**************************************************************************/
636 lcdProperties_t
lcdGetProperties(void)
638 return ili9328Properties
;