1 /**************************************************************************/
4 @author K. Townsend (microBuilder.eu)
8 Driver for ILI9325 240x320 pixel TFT LCD displays.
10 This driver uses an 8-bit interface and a 16-bit RGB565 colour palette.
11 Should also work with SPFD5408B or OTM3225A-based LCDs, though
12 there are sometimes minor differences (for example vertical scrolling
13 via register 0x6A isn't supported on all controllers).
17 26-11-2010: ili9325ReadData contributed by Adafruit Industries
21 Software License Agreement (BSD License)
23 Copyright (c) 2010, microBuilder SARL
26 Redistribution and use in source and binary forms, with or without
27 modification, are permitted provided that the following conditions are met:
28 1. Redistributions of source code must retain the above copyright
29 notice, this list of conditions and the following disclaimer.
30 2. Redistributions in binary form must reproduce the above copyright
31 notice, this list of conditions and the following disclaimer in the
32 documentation and/or other materials provided with the distribution.
33 3. Neither the name of the copyright holders nor the
34 names of its contributors may be used to endorse or promote products
35 derived from this software without specific prior written permission.
37 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
38 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
39 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
41 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
42 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
46 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48 /**************************************************************************/
50 #include "core/systick/systick.h"
51 #include "drivers/displays/tft/touchscreen.h"
53 // Uncomment this to use faster inline methods, but requires more flash
54 // #define ILI9235_USE_INLINE_METHODS (1)
56 static lcdOrientation_t lcdOrientation
= LCD_ORIENTATION_PORTRAIT
;
57 static lcdProperties_t ili9325Properties
= { 240, 320, TRUE
, TRUE
, TRUE
};
59 /*************************************************/
61 /*************************************************/
63 /**************************************************************************/
65 @brief Causes a brief delay (10 ticks per unit)
67 /**************************************************************************/
68 #if !defined ILI9235_USE_INLINE_METHODS
69 void ili9325Delay(unsigned int t
)
73 for ( t1
=10; t1
> 0; t1
-- )
79 static inline uint32_t ili9325Delay(unsigned int t
) { unsigned char t1
; while(t
--) for ( t1
=10; t1
> 0; t1
-- ) { __asm("nop"); } }
82 /**************************************************************************/
84 @brief Writes the supplied 16-bit command using an 8-bit interface
86 /**************************************************************************/
87 #if !defined ILI9238_USE_INLINE_METHODS
88 void ili9325WriteCmd(uint16_t command
)
90 // Compiled with -Os on GCC 4.4 this works out to 25 cycles
91 // (versus 36 compiled with no optimisations). I'm not sure it
92 // can be improved further, so that means 25 cycles/350nS for
93 // continuous writes (cmd, data, data, data, ...) or ~150 cycles/
94 // ~2.1uS for a random pixel (Set X [cmd+data], Set Y [cmd+data],
95 // Set color [cmd+data]) (times assumes 72MHz clock).
97 CLR_CS_CD_SET_RD_WR
; // Saves 18 commands compared to "CLR_CS; CLR_CD; SET_RD; SET_WR;"
98 ILI9325_GPIO2DATA_DATA
= (command
>> (8 - ILI9325_DATA_OFFSET
));
101 ILI9325_GPIO2DATA_DATA
= command
<< ILI9325_DATA_OFFSET
;
103 SET_WR_CS
; // Saves 7 commands compared to "SET_WR; SET_CS;"
106 static inline void ili9325WriteCmd(uint16_t command
) { CLR_CS_CD_SET_RD_WR
; ILI9325_GPIO2DATA_DATA
= (command
>> (8 - ILI9325_DATA_OFFSET
)); CLR_WR
; SET_WR
; ILI9325_GPIO2DATA_DATA
= command
<< ILI9325_DATA_OFFSET
; CLR_WR
; SET_WR_CS
; }
109 /**************************************************************************/
111 @brief Writes the supplied 16-bit data using an 8-bit interface
113 /**************************************************************************/
114 #if !defined ILI9238_USE_INLINE_METHODS
115 void ili9325WriteData(uint16_t data
)
117 CLR_CS_SET_CD_RD_WR
; // Saves 18 commands compared to SET_CD; SET_RD; SET_WR; CLR_CS"
118 ILI9325_GPIO2DATA_DATA
= (data
>> (8 - ILI9325_DATA_OFFSET
));
121 ILI9325_GPIO2DATA_DATA
= data
<< ILI9325_DATA_OFFSET
;
123 SET_WR_CS
; // Saves 7 commands compared to "SET_WR, SET_CS;"
126 static inline void ili9325WriteData(uint16_t data
) { CLR_CS_SET_CD_RD_WR
; ILI9325_GPIO2DATA_DATA
= (data
>> (8 - ILI9325_DATA_OFFSET
)); CLR_WR
; SET_WR
; ILI9325_GPIO2DATA_DATA
= data
<< ILI9325_DATA_OFFSET
; CLR_WR
; SET_WR_CS
; }
129 /**************************************************************************/
131 @brief Reads a 16-bit value from the 8-bit data bus
133 /**************************************************************************/
134 uint16_t ili9325ReadData(void)
136 // ToDo: Optimise this method!
142 SET_CD_RD_WR
; // Saves 14 commands compared to "SET_CD; SET_RD; SET_WR"
146 ILI9325_GPIO2DATA_SETINPUT
;
149 high
= ILI9325_GPIO2DATA_DATA
;
150 high
>>= ILI9325_DATA_OFFSET
;
156 low
= ILI9325_GPIO2DATA_DATA
;
157 low
>>= ILI9325_DATA_OFFSET
;
162 ILI9325_GPIO2DATA_SETOUTPUT
;
171 /**************************************************************************/
173 @brief Reads a 16-bit value
175 /**************************************************************************/
176 uint16_t ili9325Read(uint16_t addr
)
178 ili9325WriteCmd(addr
);
179 return ili9325ReadData();
182 /**************************************************************************/
184 @brief Sends a 16-bit command + 16-bit data
186 /**************************************************************************/
187 void ili9325Command(uint16_t command
, uint16_t data
)
189 ili9325WriteCmd(command
);
190 ili9325WriteData(data
);
193 /**************************************************************************/
195 @brief Returns the 16-bit (4-hexdigit) controller code
197 /**************************************************************************/
198 uint16_t ili9325Type(void)
200 ili9325WriteCmd(ILI9325_COMMANDS_DRIVERCODEREAD
);
201 return ili9325ReadData();
204 /**************************************************************************/
206 @brief Sets the cursor to the specified X/Y position
208 /**************************************************************************/
209 #if !defined ILI9238_USE_INLINE_METHODS
210 void ili9325SetCursor(uint16_t x
, uint16_t y
)
214 if (lcdOrientation
== LCD_ORIENTATION_LANDSCAPE
)
225 ili9325Command(ILI9325_COMMANDS_HORIZONTALGRAMADDRESSSET
, al
);
226 ili9325Command(ILI9325_COMMANDS_VERTICALGRAMADDRESSSET
, ah
);
229 static inline void ili9325SetCursor(uint16_t x
, uint16_t y
) { uint16_t al
, ah
; if (lcdOrientation
== LCD_ORIENTATION_LANDSCAPE
) { al
= y
; ah
= x
; } else { al
= x
; ah
= y
; }; ili9325WriteCmd(ILI9325_COMMANDS_HORIZONTALGRAMADDRESSSET
); ili9325WriteData(al
); ili9325WriteCmd(ILI9325_COMMANDS_VERTICALGRAMADDRESSSET
); ili9325WriteData(ah
); }
232 /**************************************************************************/
234 @brief Sends the initialisation sequence to the display controller
236 /**************************************************************************/
237 void ili9325InitDisplay(void)
240 GPIO_GPIO2DATA
&= ~ILI9325_DATA_MASK
;
253 ili9325Command(ILI9325_COMMANDS_DRIVEROUTPUTCONTROL1
, 0x0100); // Driver Output Control Register (R01h)
254 ili9325Command(ILI9325_COMMANDS_LCDDRIVINGCONTROL
, 0x0700); // LCD Driving Waveform Control (R02h)
255 ili9325Command(ILI9325_COMMANDS_ENTRYMODE
, 0x1030); // Entry Mode (R03h)
256 ili9325Command(ILI9325_COMMANDS_DISPLAYCONTROL2
, 0x0302);
257 ili9325Command(ILI9325_COMMANDS_DISPLAYCONTROL3
, 0x0000);
258 ili9325Command(ILI9325_COMMANDS_DISPLAYCONTROL4
, 0x0000); // Fmark On
259 ili9325Command(ILI9325_COMMANDS_POWERCONTROL1
, 0x0000); // Power Control 1 (R10h)
260 ili9325Command(ILI9325_COMMANDS_POWERCONTROL2
, 0x0007); // Power Control 2 (R11h)
261 ili9325Command(ILI9325_COMMANDS_POWERCONTROL3
, 0x0000); // Power Control 3 (R12h)
262 ili9325Command(ILI9325_COMMANDS_POWERCONTROL4
, 0x0000); // Power Control 4 (R13h)
264 ili9325Command(ILI9325_COMMANDS_POWERCONTROL1
, 0x14B0); // Power Control 1 (R10h)
266 ili9325Command(ILI9325_COMMANDS_POWERCONTROL2
, 0x0007); // Power Control 2 (R11h)
268 ili9325Command(ILI9325_COMMANDS_POWERCONTROL3
, 0x008E); // Power Control 3 (R12h)
269 ili9325Command(ILI9325_COMMANDS_POWERCONTROL4
, 0x0C00); // Power Control 4 (R13h)
270 ili9325Command(ILI9325_COMMANDS_POWERCONTROL7
, 0x0015); // NVM read data 2 (R29h)
272 ili9325Command(ILI9325_COMMANDS_GAMMACONTROL1
, 0x0000); // Gamma Control 1
273 ili9325Command(ILI9325_COMMANDS_GAMMACONTROL2
, 0x0107); // Gamma Control 2
274 ili9325Command(ILI9325_COMMANDS_GAMMACONTROL3
, 0x0000); // Gamma Control 3
275 ili9325Command(ILI9325_COMMANDS_GAMMACONTROL4
, 0x0203); // Gamma Control 4
276 ili9325Command(ILI9325_COMMANDS_GAMMACONTROL5
, 0x0402); // Gamma Control 5
277 ili9325Command(ILI9325_COMMANDS_GAMMACONTROL6
, 0x0000); // Gamma Control 6
278 ili9325Command(ILI9325_COMMANDS_GAMMACONTROL7
, 0x0207); // Gamma Control 7
279 ili9325Command(ILI9325_COMMANDS_GAMMACONTROL8
, 0x0000); // Gamma Control 8
280 ili9325Command(ILI9325_COMMANDS_GAMMACONTROL9
, 0x0203); // Gamma Control 9
281 ili9325Command(ILI9325_COMMANDS_GAMMACONTROL10
, 0x0403); // Gamma Control 10
282 ili9325Command(ILI9325_COMMANDS_HORIZONTALADDRESSSTARTPOSITION
, 0x0000); // Window Horizontal RAM Address Start (R50h)
283 ili9325Command(ILI9325_COMMANDS_HORIZONTALADDRESSENDPOSITION
, ili9325Properties
.width
- 1); // Window Horizontal RAM Address End (R51h)
284 ili9325Command(ILI9325_COMMANDS_VERTICALADDRESSSTARTPOSITION
, 0X0000); // Window Vertical RAM Address Start (R52h)
285 ili9325Command(ILI9325_COMMANDS_VERTICALADDRESSENDPOSITION
, ili9325Properties
.height
- 1); // Window Vertical RAM Address End (R53h)
286 ili9325Command(ILI9325_COMMANDS_DRIVEROUTPUTCONTROL2
, 0xa700); // Driver Output Control (R60h)
287 ili9325Command(ILI9325_COMMANDS_BASEIMAGEDISPLAYCONTROL
, 0x0003); // Driver Output Control (R61h) - enable VLE
288 ili9325Command(ILI9325_COMMANDS_PANELINTERFACECONTROL1
, 0X0010); // Panel Interface Control 1 (R90h)
291 ili9325Command(ILI9325_COMMANDS_DISPLAYCONTROL1
, 0x0133); // Display Control (R07h)
293 ili9325WriteCmd(ILI9325_COMMANDS_WRITEDATATOGRAM
);
296 /**************************************************************************/
298 @brief Sets the cursor to the home position (0,0)
300 /**************************************************************************/
301 void ili9325Home(void)
303 ili9325SetCursor(0, 0);
304 ili9325WriteCmd(ILI9325_COMMANDS_WRITEDATATOGRAM
); // Write Data to GRAM (R22h)
307 /**************************************************************************/
309 @brief Sets the window confines
311 /**************************************************************************/
312 void ili9325SetWindow(uint16_t x0
, uint16_t y0
, uint16_t x1
, uint16_t y1
)
314 ili9325Command(ILI9325_COMMANDS_HORIZONTALADDRESSSTARTPOSITION
, x0
);
315 ili9325Command(ILI9325_COMMANDS_HORIZONTALADDRESSENDPOSITION
, x1
);
316 ili9325Command(ILI9325_COMMANDS_VERTICALADDRESSSTARTPOSITION
, y0
);
317 ili9325Command(ILI9325_COMMANDS_VERTICALADDRESSENDPOSITION
, y1
);
318 ili9325SetCursor(x0
, y0
);
321 /*************************************************/
323 /*************************************************/
325 /**************************************************************************/
327 @brief Configures any pins or HW and initialises the LCD controller
329 /**************************************************************************/
332 // Set control line pins to output
333 gpioSetDir(ILI9325_CS_PORT
, ILI9325_CS_PIN
, 1);
334 gpioSetDir(ILI9325_CD_PORT
, ILI9325_CD_PIN
, 1);
335 gpioSetDir(ILI9325_WR_PORT
, ILI9325_WR_PIN
, 1);
336 gpioSetDir(ILI9325_RD_PORT
, ILI9325_RD_PIN
, 1);
338 // Set data port pins to output
339 ILI9325_GPIO2DATA_SETOUTPUT
;
342 ILI9325_DISABLEPULLUPS();
344 // Set backlight pin to output and turn it on
345 gpioSetDir(ILI9325_BL_PORT
, ILI9325_BL_PIN
, 1); // set to output
348 // Set reset pin to output
349 gpioSetDir(ILI9325_RES_PORT
, ILI9325_RES_PIN
, 1); // Set to output
350 gpioSetValue(ILI9325_RES_PORT
, ILI9325_RES_PIN
, 0); // Low to reset
352 gpioSetValue(ILI9325_RES_PORT
, ILI9325_RES_PIN
, 1); // High to exit
354 // Initialize the display
355 ili9325InitDisplay();
359 // Set lcd to default orientation
360 lcdSetOrientation(lcdOrientation
);
363 lcdFillRGB(COLOR_BLACK
);
365 // Initialise the touch screen (and calibrate if necessary)
369 /**************************************************************************/
371 @brief Enables or disables the LCD backlight
373 /**************************************************************************/
374 void lcdBacklight(bool state
)
377 gpioSetValue(ILI9325_BL_PORT
, ILI9325_BL_PIN
, state
? 0 : 1);
380 /**************************************************************************/
382 @brief Renders a simple test pattern on the LCD
384 /**************************************************************************/
394 if(i
>279)ili9325WriteData(COLOR_WHITE
);
395 else if(i
>239)ili9325WriteData(COLOR_BLUE
);
396 else if(i
>199)ili9325WriteData(COLOR_GREEN
);
397 else if(i
>159)ili9325WriteData(COLOR_CYAN
);
398 else if(i
>119)ili9325WriteData(COLOR_RED
);
399 else if(i
>79)ili9325WriteData(COLOR_MAGENTA
);
400 else if(i
>39)ili9325WriteData(COLOR_YELLOW
);
401 else ili9325WriteData(COLOR_BLACK
);
406 /**************************************************************************/
408 @brief Fills the LCD with the specified 16-bit color
410 /**************************************************************************/
411 void lcdFillRGB(uint16_t data
)
416 uint32_t pixels
= 320*240;
417 for ( i
=0; i
< pixels
; i
++ )
419 ili9325WriteData(data
);
423 /**************************************************************************/
425 @brief Draws a single pixel at the specified X/Y location
427 /**************************************************************************/
428 void lcdDrawPixel(uint16_t x
, uint16_t y
, uint16_t color
)
430 ili9325SetCursor(x
, y
);
431 ili9325WriteCmd(ILI9325_COMMANDS_WRITEDATATOGRAM
); // Write Data to GRAM (R22h)
432 ili9325WriteData(color
);
435 /**************************************************************************/
437 @brief Draws an array of consecutive RGB565 pixels (much
438 faster than addressing each pixel individually)
440 /**************************************************************************/
441 void lcdDrawPixels(uint16_t x
, uint16_t y
, uint16_t *data
, uint32_t len
)
444 ili9325SetCursor(x
, y
);
445 ili9325WriteCmd(ILI9325_COMMANDS_WRITEDATATOGRAM
);
448 ili9325WriteData(data
[i
]);
453 /**************************************************************************/
455 @brief Optimised routine to draw a horizontal line faster than
456 setting individual pixels
458 /**************************************************************************/
459 void lcdDrawHLine(uint16_t x0
, uint16_t x1
, uint16_t y
, uint16_t color
)
461 // Allows for slightly better performance than setting individual pixels
473 if (x1
>= lcdGetWidth())
475 x1
= lcdGetWidth() - 1;
477 if (x0
>= lcdGetWidth())
479 x0
= lcdGetWidth() - 1;
482 ili9325SetCursor(x0
, y
);
483 ili9325WriteCmd(ILI9325_COMMANDS_WRITEDATATOGRAM
); // Write Data to GRAM (R22h)
484 for (pixels
= 0; pixels
< x1
- x0
+ 1; pixels
++)
486 ili9325WriteData(color
);
490 /**************************************************************************/
492 @brief Optimised routine to draw a vertical line faster than
493 setting individual pixels
495 /**************************************************************************/
496 void lcdDrawVLine(uint16_t x
, uint16_t y0
, uint16_t y1
, uint16_t color
)
498 lcdOrientation_t oldOrientation
= lcdOrientation
;
500 if (oldOrientation
== LCD_ORIENTATION_PORTRAIT
)
502 lcdSetOrientation(LCD_ORIENTATION_LANDSCAPE
);
503 lcdDrawHLine(y0
, y1
, lcdGetHeight() - (x
+ 1), color
);
507 lcdSetOrientation(LCD_ORIENTATION_PORTRAIT
);
508 lcdDrawHLine(lcdGetWidth() - (y0
+ 1), lcdGetWidth() - (y1
+ 1), x
, color
);
511 // Switch orientation back
512 lcdSetOrientation(oldOrientation
);
515 /**************************************************************************/
517 @brief Gets the 16-bit color of the pixel at the specified location
519 /**************************************************************************/
520 uint16_t lcdGetPixel(uint16_t x
, uint16_t y
)
522 uint16_t preFetch
= 0;
524 ili9325SetCursor(x
, y
);
525 ili9325WriteCmd(ILI9325_COMMANDS_WRITEDATATOGRAM
);
526 preFetch
= ili9325ReadData();
528 // Eeek ... why does this need to be done twice for a proper value?!?
529 ili9325SetCursor(x
, y
);
530 ili9325WriteCmd(ILI9325_COMMANDS_WRITEDATATOGRAM
);
531 return ili9325ReadData();
534 /**************************************************************************/
536 @brief Sets the LCD orientation to horizontal and vertical
538 /**************************************************************************/
539 void lcdSetOrientation(lcdOrientation_t orientation
)
541 uint16_t entryMode
= 0x1030;
542 uint16_t outputControl
= 0x0100;
546 case LCD_ORIENTATION_PORTRAIT
:
548 outputControl
= 0x0100;
550 case LCD_ORIENTATION_LANDSCAPE
:
552 outputControl
= 0x0000;
556 ili9325Command(ILI9325_COMMANDS_ENTRYMODE
, entryMode
);
557 ili9325Command(ILI9325_COMMANDS_DRIVEROUTPUTCONTROL1
, outputControl
);
558 lcdOrientation
= orientation
;
560 ili9325SetCursor(0, 0);
563 /**************************************************************************/
565 @brief Gets the current screen orientation (horizontal or vertical)
567 /**************************************************************************/
568 lcdOrientation_t
lcdGetOrientation(void)
570 return lcdOrientation
;
573 /**************************************************************************/
575 @brief Gets the width in pixels of the LCD screen (varies depending
576 on the current screen orientation)
578 /**************************************************************************/
579 uint16_t lcdGetWidth(void)
581 switch (lcdOrientation
)
583 case LCD_ORIENTATION_PORTRAIT
:
584 return ili9325Properties
.width
;
586 case LCD_ORIENTATION_LANDSCAPE
:
588 return ili9325Properties
.height
;
592 /**************************************************************************/
594 @brief Gets the height in pixels of the LCD screen (varies depending
595 on the current screen orientation)
597 /**************************************************************************/
598 uint16_t lcdGetHeight(void)
600 switch (lcdOrientation
)
602 case LCD_ORIENTATION_PORTRAIT
:
603 return ili9325Properties
.height
;
605 case LCD_ORIENTATION_LANDSCAPE
:
607 return ili9325Properties
.width
;
611 /**************************************************************************/
613 @brief Scrolls the contents of the LCD screen vertically the
614 specified number of pixels using a HW optimised routine
616 /**************************************************************************/
617 void lcdScroll(int16_t pixels
, uint16_t fillColor
)
624 ili9325WriteCmd(ILI9325_COMMANDS_VERTICALSCROLLCONTROL
);
628 /**************************************************************************/
630 @brief Gets the controller's 16-bit (4 hexdigit) ID
632 /**************************************************************************/
633 uint16_t lcdGetControllerID(void)
635 return ili9325Type();
638 /**************************************************************************/
640 @brief Returns the LCDs 'lcdProperties_t' that describes the LCDs
641 generic capabilities and dimensions
643 /**************************************************************************/
644 lcdProperties_t
lcdGetProperties(void)
646 return ili9325Properties
;