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/lcd/tft/touchscreen.h"
53 static lcdOrientation_t lcdOrientation
= LCD_ORIENTATION_PORTRAIT
;
54 static lcdProperties_t ili9325Properties
= { 240, 320, TRUE
, TRUE
, TRUE
};
56 /*************************************************/
58 /*************************************************/
60 /**************************************************************************/
62 @brief Causes a brief delay (10 ticks per unit)
64 /**************************************************************************/
65 void ili9325Delay(unsigned int t
)
69 for ( t1
=10; t1
> 0; t1
-- )
75 /**************************************************************************/
77 @brief Writes the supplied 16-bit command using an 8-bit interface
79 /**************************************************************************/
80 void ili9325WriteCmd(uint16_t command
)
82 // Compiled with -Os on GCC 4.4 this works out to 25 cycles
83 // (versus 36 compiled with no optimisations). I'm not sure it
84 // can be improved further, so that means 25 cycles/350nS for
85 // continuous writes (cmd, data, data, data, ...) or ~150 cycles/
86 // ~2.1uS for a random pixel (Set X [cmd+data], Set Y [cmd+data],
87 // Set color [cmd+data]) (times assumes 72MHz clock).
89 CLR_CS_CD_SET_RD_WR
; // Saves 18 commands compared to "CLR_CS; CLR_CD; SET_RD; SET_WR;"
90 ILI9325_GPIO2DATA_DATA
= (command
>> (8 - ILI9325_DATA_OFFSET
));
93 ILI9325_GPIO2DATA_DATA
= command
<< ILI9325_DATA_OFFSET
;
95 SET_WR_CS
; // Saves 7 commands compared to "SET_WR; SET_CS;"
98 /**************************************************************************/
100 @brief Writes the supplied 16-bit data using an 8-bit interface
102 /**************************************************************************/
103 void ili9325WriteData(uint16_t data
)
105 CLR_CS_SET_CD_RD_WR
; // Saves 18 commands compared to SET_CD; SET_RD; SET_WR; CLR_CS"
106 ILI9325_GPIO2DATA_DATA
= (data
>> (8 - ILI9325_DATA_OFFSET
));
109 ILI9325_GPIO2DATA_DATA
= data
<< ILI9325_DATA_OFFSET
;
111 SET_WR_CS
; // Saves 7 commands compared to "SET_WR, SET_CS;"
114 /**************************************************************************/
116 @brief Reads a 16-bit value from the 8-bit data bus
118 /**************************************************************************/
119 uint16_t ili9325ReadData(void)
121 // ToDo: Optimise this method!
127 SET_CD_RD_WR
; // Saves 14 commands compared to "SET_CD; SET_RD; SET_WR"
131 ILI9325_GPIO2DATA_SETINPUT
;
134 high
= ILI9325_GPIO2DATA_DATA
;
135 high
>>= ILI9325_DATA_OFFSET
;
141 low
= ILI9325_GPIO2DATA_DATA
;
142 low
>>= ILI9325_DATA_OFFSET
;
147 ILI9325_GPIO2DATA_SETOUTPUT
;
156 /**************************************************************************/
158 @brief Reads a 16-bit value
160 /**************************************************************************/
161 uint16_t ili9325Read(uint16_t addr
)
163 ili9325WriteCmd(addr
);
164 return ili9325ReadData();
167 /**************************************************************************/
169 @brief Sends a 16-bit command + 16-bit data
171 /**************************************************************************/
172 void ili9325Command(uint16_t command
, uint16_t data
)
174 ili9325WriteCmd(command
);
175 ili9325WriteData(data
);
178 /**************************************************************************/
180 @brief Returns the 16-bit (4-hexdigit) controller code
182 /**************************************************************************/
183 uint16_t ili9325Type(void)
185 ili9325WriteCmd(ILI9325_COMMANDS_DRIVERCODEREAD
);
186 return ili9325ReadData();
189 /**************************************************************************/
191 @brief Sets the cursor to the specified X/Y position
193 /**************************************************************************/
194 void ili9325SetCursor(uint16_t x
, uint16_t y
)
198 if (lcdOrientation
== LCD_ORIENTATION_LANDSCAPE
)
209 ili9325Command(ILI9325_COMMANDS_HORIZONTALGRAMADDRESSSET
, al
);
210 ili9325Command(ILI9325_COMMANDS_VERTICALGRAMADDRESSSET
, ah
);
213 /**************************************************************************/
215 @brief Sends the initialisation sequence to the display controller
217 /**************************************************************************/
218 void ili9325InitDisplay(void)
221 GPIO_GPIO2DATA
&= ~ILI9325_DATA_MASK
;
234 ili9325Command(ILI9325_COMMANDS_DRIVEROUTPUTCONTROL1
, 0x0100); // Driver Output Control Register (R01h)
235 ili9325Command(ILI9325_COMMANDS_LCDDRIVINGCONTROL
, 0x0700); // LCD Driving Waveform Control (R02h)
236 ili9325Command(ILI9325_COMMANDS_ENTRYMODE
, 0x1030); // Entry Mode (R03h)
237 ili9325Command(ILI9325_COMMANDS_DISPLAYCONTROL2
, 0x0302);
238 ili9325Command(ILI9325_COMMANDS_DISPLAYCONTROL3
, 0x0000);
239 ili9325Command(ILI9325_COMMANDS_DISPLAYCONTROL4
, 0x0000); // Fmark On
240 ili9325Command(ILI9325_COMMANDS_POWERCONTROL1
, 0x0000); // Power Control 1 (R10h)
241 ili9325Command(ILI9325_COMMANDS_POWERCONTROL2
, 0x0007); // Power Control 2 (R11h)
242 ili9325Command(ILI9325_COMMANDS_POWERCONTROL3
, 0x0000); // Power Control 3 (R12h)
243 ili9325Command(ILI9325_COMMANDS_POWERCONTROL4
, 0x0000); // Power Control 4 (R13h)
245 ili9325Command(ILI9325_COMMANDS_POWERCONTROL1
, 0x14B0); // Power Control 1 (R10h)
247 ili9325Command(ILI9325_COMMANDS_POWERCONTROL2
, 0x0007); // Power Control 2 (R11h)
249 ili9325Command(ILI9325_COMMANDS_POWERCONTROL3
, 0x008E); // Power Control 3 (R12h)
250 ili9325Command(ILI9325_COMMANDS_POWERCONTROL4
, 0x0C00); // Power Control 4 (R13h)
251 ili9325Command(ILI9325_COMMANDS_POWERCONTROL7
, 0x0015); // NVM read data 2 (R29h)
253 ili9325Command(ILI9325_COMMANDS_GAMMACONTROL1
, 0x0000); // Gamma Control 1
254 ili9325Command(ILI9325_COMMANDS_GAMMACONTROL2
, 0x0107); // Gamma Control 2
255 ili9325Command(ILI9325_COMMANDS_GAMMACONTROL3
, 0x0000); // Gamma Control 3
256 ili9325Command(ILI9325_COMMANDS_GAMMACONTROL4
, 0x0203); // Gamma Control 4
257 ili9325Command(ILI9325_COMMANDS_GAMMACONTROL5
, 0x0402); // Gamma Control 5
258 ili9325Command(ILI9325_COMMANDS_GAMMACONTROL6
, 0x0000); // Gamma Control 6
259 ili9325Command(ILI9325_COMMANDS_GAMMACONTROL7
, 0x0207); // Gamma Control 7
260 ili9325Command(ILI9325_COMMANDS_GAMMACONTROL8
, 0x0000); // Gamma Control 8
261 ili9325Command(ILI9325_COMMANDS_GAMMACONTROL9
, 0x0203); // Gamma Control 9
262 ili9325Command(ILI9325_COMMANDS_GAMMACONTROL10
, 0x0403); // Gamma Control 10
263 ili9325Command(ILI9325_COMMANDS_HORIZONTALADDRESSSTARTPOSITION
, 0x0000); // Window Horizontal RAM Address Start (R50h)
264 ili9325Command(ILI9325_COMMANDS_HORIZONTALADDRESSENDPOSITION
, ili9325Properties
.width
- 1); // Window Horizontal RAM Address End (R51h)
265 ili9325Command(ILI9325_COMMANDS_VERTICALADDRESSSTARTPOSITION
, 0X0000); // Window Vertical RAM Address Start (R52h)
266 ili9325Command(ILI9325_COMMANDS_VERTICALADDRESSENDPOSITION
, ili9325Properties
.height
- 1); // Window Vertical RAM Address End (R53h)
267 ili9325Command(ILI9325_COMMANDS_DRIVEROUTPUTCONTROL2
, 0xa700); // Driver Output Control (R60h)
268 ili9325Command(ILI9325_COMMANDS_BASEIMAGEDISPLAYCONTROL
, 0x0003); // Driver Output Control (R61h) - enable VLE
269 ili9325Command(ILI9325_COMMANDS_PANELINTERFACECONTROL1
, 0X0010); // Panel Interface Control 1 (R90h)
272 ili9325Command(ILI9325_COMMANDS_DISPLAYCONTROL1
, 0x0133); // Display Control (R07h)
274 ili9325WriteCmd(ILI9325_COMMANDS_WRITEDATATOGRAM
);
277 /**************************************************************************/
279 @brief Sets the cursor to the home position (0,0)
281 /**************************************************************************/
282 void ili9325Home(void)
284 ili9325SetCursor(0, 0);
285 ili9325WriteCmd(ILI9325_COMMANDS_WRITEDATATOGRAM
); // Write Data to GRAM (R22h)
288 /**************************************************************************/
290 @brief Sets the window confines
292 /**************************************************************************/
293 void ili9325SetWindow(uint16_t x0
, uint16_t y0
, uint16_t x1
, uint16_t y1
)
295 ili9325Command(ILI9325_COMMANDS_HORIZONTALADDRESSSTARTPOSITION
, x0
);
296 ili9325Command(ILI9325_COMMANDS_HORIZONTALADDRESSENDPOSITION
, x1
);
297 ili9325Command(ILI9325_COMMANDS_VERTICALADDRESSSTARTPOSITION
, y0
);
298 ili9325Command(ILI9325_COMMANDS_VERTICALADDRESSENDPOSITION
, y1
);
299 ili9325SetCursor(x0
, y0
);
302 /*************************************************/
304 /*************************************************/
306 /**************************************************************************/
308 @brief Configures any pins or HW and initialises the LCD controller
310 /**************************************************************************/
313 // Set control line pins to output
314 gpioSetDir(ILI9325_CS_PORT
, ILI9325_CS_PIN
, 1);
315 gpioSetDir(ILI9325_CD_PORT
, ILI9325_CD_PIN
, 1);
316 gpioSetDir(ILI9325_WR_PORT
, ILI9325_WR_PIN
, 1);
317 gpioSetDir(ILI9325_RD_PORT
, ILI9325_RD_PIN
, 1);
319 // Set data port pins to output
320 ILI9325_GPIO2DATA_SETOUTPUT
;
323 ILI9325_DISABLEPULLUPS();
325 // Set backlight pin to output and turn it on
326 gpioSetDir(ILI9325_BL_PORT
, ILI9325_BL_PIN
, 1); // set to output
329 // Set reset pin to output
330 gpioSetDir(ILI9325_RES_PORT
, ILI9325_RES_PIN
, 1); // Set to output
331 gpioSetValue(ILI9325_RES_PORT
, ILI9325_RES_PIN
, 0); // Low to reset
333 gpioSetValue(ILI9325_RES_PORT
, ILI9325_RES_PIN
, 1); // High to exit
335 // Initialize the display
336 ili9325InitDisplay();
340 // Set lcd to default orientation
341 lcdSetOrientation(lcdOrientation
);
344 lcdFillRGB(COLOR_BLACK
);
346 // Initialise the touch screen (and calibrate if necessary)
350 /**************************************************************************/
352 @brief Enables or disables the LCD backlight
354 /**************************************************************************/
355 void lcdBacklight(bool state
)
358 gpioSetValue(ILI9325_BL_PORT
, ILI9325_BL_PIN
, state
? 0 : 1);
361 /**************************************************************************/
363 @brief Renders a simple test pattern on the LCD
365 /**************************************************************************/
375 if(i
>279)ili9325WriteData(COLOR_WHITE
);
376 else if(i
>239)ili9325WriteData(COLOR_BLUE
);
377 else if(i
>199)ili9325WriteData(COLOR_GREEN
);
378 else if(i
>159)ili9325WriteData(COLOR_CYAN
);
379 else if(i
>119)ili9325WriteData(COLOR_RED
);
380 else if(i
>79)ili9325WriteData(COLOR_MAGENTA
);
381 else if(i
>39)ili9325WriteData(COLOR_YELLOW
);
382 else ili9325WriteData(COLOR_BLACK
);
387 /**************************************************************************/
389 @brief Fills the LCD with the specified 16-bit color
391 /**************************************************************************/
392 void lcdFillRGB(uint16_t data
)
397 uint32_t pixels
= 320*240;
398 for ( i
=0; i
< pixels
; i
++ )
400 ili9325WriteData(data
);
404 /**************************************************************************/
406 @brief Draws a single pixel at the specified X/Y location
408 /**************************************************************************/
409 void lcdDrawPixel(uint16_t x
, uint16_t y
, uint16_t color
)
411 ili9325SetCursor(x
, y
);
412 ili9325WriteCmd(ILI9325_COMMANDS_WRITEDATATOGRAM
); // Write Data to GRAM (R22h)
413 ili9325WriteData(color
);
416 /**************************************************************************/
418 @brief Draws an array of consecutive RGB565 pixels (much
419 faster than addressing each pixel individually)
421 /**************************************************************************/
422 void lcdDrawPixels(uint16_t x
, uint16_t y
, uint16_t *data
, uint32_t len
)
425 ili9325SetCursor(x
, y
);
426 ili9325WriteCmd(ILI9325_COMMANDS_WRITEDATATOGRAM
);
429 ili9325WriteData(data
[i
]);
434 /**************************************************************************/
436 @brief Optimised routine to draw a horizontal line faster than
437 setting individual pixels
439 /**************************************************************************/
440 void lcdDrawHLine(uint16_t x0
, uint16_t x1
, uint16_t y
, uint16_t color
)
442 // Allows for slightly better performance than setting individual pixels
454 if (x1
>= lcdGetWidth())
456 x1
= lcdGetWidth() - 1;
458 if (x0
>= lcdGetWidth())
460 x0
= lcdGetWidth() - 1;
463 ili9325SetCursor(x0
, y
);
464 ili9325WriteCmd(ILI9325_COMMANDS_WRITEDATATOGRAM
); // Write Data to GRAM (R22h)
465 for (pixels
= 0; pixels
< x1
- x0
+ 1; pixels
++)
467 ili9325WriteData(color
);
471 /**************************************************************************/
473 @brief Optimised routine to draw a vertical line faster than
474 setting individual pixels
476 /**************************************************************************/
477 void lcdDrawVLine(uint16_t x
, uint16_t y0
, uint16_t y1
, uint16_t color
)
479 // Allows for slightly better performance than setting individual pixels
480 lcdOrientation_t orientation
= lcdOrientation
;
482 // Switch orientation
483 lcdSetOrientation(orientation
== LCD_ORIENTATION_PORTRAIT
? LCD_ORIENTATION_LANDSCAPE
: LCD_ORIENTATION_PORTRAIT
);
485 // Draw horizontal line like usual
486 lcdDrawHLine(y0
, y1
, lcdGetHeight() - (x
+ 1), color
);
488 // Switch orientation back
489 lcdSetOrientation(orientation
);
492 /**************************************************************************/
494 @brief Gets the 16-bit color of the pixel at the specified location
496 /**************************************************************************/
497 uint16_t lcdGetPixel(uint16_t x
, uint16_t y
)
499 uint16_t preFetch
= 0;
501 ili9325SetCursor(x
, y
);
502 ili9325WriteCmd(ILI9325_COMMANDS_WRITEDATATOGRAM
);
503 preFetch
= ili9325ReadData();
505 // Eeek ... why does this need to be done twice for a proper value?!?
506 ili9325SetCursor(x
, y
);
507 ili9325WriteCmd(ILI9325_COMMANDS_WRITEDATATOGRAM
);
508 return ili9325ReadData();
511 /**************************************************************************/
513 @brief Sets the LCD orientation to horizontal and vertical
515 /**************************************************************************/
516 void lcdSetOrientation(lcdOrientation_t orientation
)
518 uint16_t entryMode
= 0x1030;
519 uint16_t outputControl
= 0x0100;
523 case LCD_ORIENTATION_PORTRAIT
:
525 outputControl
= 0x0100;
527 case LCD_ORIENTATION_LANDSCAPE
:
529 outputControl
= 0x0000;
533 ili9325Command(ILI9325_COMMANDS_ENTRYMODE
, entryMode
);
534 ili9325Command(ILI9325_COMMANDS_DRIVEROUTPUTCONTROL1
, outputControl
);
535 lcdOrientation
= orientation
;
537 ili9325SetCursor(0, 0);
540 /**************************************************************************/
542 @brief Gets the current screen orientation (horizontal or vertical)
544 /**************************************************************************/
545 lcdOrientation_t
lcdGetOrientation(void)
547 return lcdOrientation
;
550 /**************************************************************************/
552 @brief Gets the width in pixels of the LCD screen (varies depending
553 on the current screen orientation)
555 /**************************************************************************/
556 uint16_t lcdGetWidth(void)
558 switch (lcdOrientation
)
560 case LCD_ORIENTATION_PORTRAIT
:
561 return ili9325Properties
.width
;
563 case LCD_ORIENTATION_LANDSCAPE
:
565 return ili9325Properties
.height
;
569 /**************************************************************************/
571 @brief Gets the height in pixels of the LCD screen (varies depending
572 on the current screen orientation)
574 /**************************************************************************/
575 uint16_t lcdGetHeight(void)
577 switch (lcdOrientation
)
579 case LCD_ORIENTATION_PORTRAIT
:
580 return ili9325Properties
.height
;
582 case LCD_ORIENTATION_LANDSCAPE
:
584 return ili9325Properties
.width
;
588 /**************************************************************************/
590 @brief Scrolls the contents of the LCD screen vertically the
591 specified number of pixels using a HW optimised routine
593 /**************************************************************************/
594 void lcdScroll(int16_t pixels
, uint16_t fillColor
)
601 ili9325WriteCmd(ILI9325_COMMANDS_VERTICALSCROLLCONTROL
);
605 /**************************************************************************/
607 @brief Gets the controller's 16-bit (4 hexdigit) ID
609 /**************************************************************************/
610 uint16_t lcdGetControllerID(void)
612 return ili9325Type();
615 /**************************************************************************/
617 @brief Returns the LCDs 'lcdProperties_t' that describes the LCDs
618 generic capabilities and dimensions
620 /**************************************************************************/
621 lcdProperties_t
lcdGetProperties(void)
623 return ili9325Properties
;