4 * \brief API driver for ILI93XX TFT display component.
\r
6 * Copyright (c) 2013 Atmel Corporation. All rights reserved.
\r
12 * Redistribution and use in source and binary forms, with or without
\r
13 * modification, are permitted provided that the following conditions are met:
\r
15 * 1. Redistributions of source code must retain the above copyright notice,
\r
16 * this list of conditions and the following disclaimer.
\r
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
\r
19 * this list of conditions and the following disclaimer in the documentation
\r
20 * and/or other materials provided with the distribution.
\r
22 * 3. The name of Atmel may not be used to endorse or promote products derived
\r
23 * from this software without specific prior written permission.
\r
25 * 4. This software may only be redistributed and used in connection with an
\r
26 * Atmel microcontroller product.
\r
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
\r
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
\r
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
\r
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
\r
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
\r
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
\r
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
\r
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
\r
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
\r
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
\r
38 * POSSIBILITY OF SUCH DAMAGE.
\r
45 * \defgroup ili93xx_display_group Display - ILI93XX Controller
\r
47 * Low-level driver for the ILI93XX LCD controller. This driver provides access
\r
48 * to the main features of the ILI93XX controller.
\r
49 * Now ILI9325 and ILI9341 are supported.
\r
58 #include "ili93xx.h"
\r
59 #include "ili9341_regs.h"
\r
60 #include "ili9325_regs.h"
\r
63 static uint8_t g_uc_device_type = 0;
\r
65 /** Pixel cache used to speed up communication */
\r
66 #define LCD_DATA_CACHE_SIZE ILI93XX_LCD_WIDTH
\r
68 /** LCD X-axis and Y-axis length */
\r
69 static uint32_t g_ul_lcd_x_length = ILI93XX_LCD_WIDTH;
\r
70 static uint32_t g_ul_lcd_y_length = ILI93XX_LCD_HEIGHT;
\r
72 static ili93xx_color_t g_ul_pixel_cache[LCD_DATA_CACHE_SIZE];
\r
74 static volatile ili93xx_coord_t limit_start_x, limit_start_y;
\r
75 static volatile ili93xx_coord_t limit_end_x, limit_end_y;
\r
77 /** Global variable describing the font size used by the driver */
\r
78 const struct ili93xx_font gfont = {10, 14};
\r
81 * Character set table for font 10x14
\r
83 * Char height is 14 bits, which is coded using 2 bytes per column
\r
85 * Char width is 10 bits.
\r
87 const uint8_t p_uc_charset10x14[] = {
\r
88 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
89 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
90 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xCC,
\r
91 0xFF, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
92 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x00, 0x00,
\r
93 0x00, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
94 0x0C, 0xC0, 0x0C, 0xC0, 0xFF, 0xFC, 0xFF, 0xFC, 0x0C, 0xC0,
\r
95 0x0C, 0xC0, 0xFF, 0xFC, 0xFF, 0xFC, 0x0C, 0xC0, 0x0C, 0xC0,
\r
96 0x0C, 0x60, 0x1E, 0x70, 0x3F, 0x30, 0x33, 0x30, 0xFF, 0xFC,
\r
97 0xFF, 0xFC, 0x33, 0x30, 0x33, 0xF0, 0x39, 0xE0, 0x18, 0xC0,
\r
98 0x60, 0x00, 0xF0, 0x0C, 0xF0, 0x3C, 0x60, 0xF0, 0x03, 0xC0,
\r
99 0x0F, 0x00, 0x3C, 0x18, 0xF0, 0x3C, 0xC0, 0x3C, 0x00, 0x18,
\r
100 0x3C, 0xF0, 0x7F, 0xF8, 0xC3, 0x1C, 0xC7, 0x8C, 0xCF, 0xCC,
\r
101 0xDC, 0xEC, 0x78, 0x78, 0x30, 0x30, 0x00, 0xFC, 0x00, 0xCC,
\r
102 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0xEC, 0x00,
\r
103 0xF8, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
104 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC0, 0x3F, 0xF0, 0x78, 0x78,
\r
105 0x60, 0x18, 0xC0, 0x0C, 0xC0, 0x0C, 0x00, 0x00, 0x00, 0x00,
\r
106 0x00, 0x00, 0x00, 0x00, 0xC0, 0x0C, 0xC0, 0x0C, 0x60, 0x18,
\r
107 0x78, 0x78, 0x3F, 0xF0, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00,
\r
108 0x0C, 0x60, 0x0E, 0xE0, 0x07, 0xC0, 0x03, 0x80, 0x3F, 0xF8,
\r
109 0x3F, 0xF8, 0x03, 0x80, 0x07, 0xC0, 0x0E, 0xE0, 0x0C, 0x60,
\r
110 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x3F, 0xF0,
\r
111 0x3F, 0xF0, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00,
\r
112 0x00, 0x44, 0x00, 0xEC, 0x00, 0xF8, 0x00, 0x70, 0x00, 0x00,
\r
113 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
114 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00,
\r
115 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00,
\r
116 0x00, 0x18, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x18, 0x00, 0x00,
\r
117 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
118 0x00, 0x00, 0x00, 0x0C, 0x00, 0x3C, 0x00, 0xF0, 0x03, 0xC0,
\r
119 0x0F, 0x00, 0x3C, 0x00, 0xF0, 0x00, 0xC0, 0x00, 0x00, 0x00,
\r
120 0x3F, 0xF0, 0x7F, 0xF8, 0xE0, 0xFC, 0xC1, 0xCC, 0xC3, 0x8C,
\r
121 0xC7, 0x0C, 0xCE, 0x0C, 0xFC, 0x1C, 0x7F, 0xF8, 0x3F, 0xF0,
\r
122 0x00, 0x00, 0x00, 0x00, 0x30, 0x0C, 0x70, 0x0C, 0xFF, 0xFC,
\r
123 0xFF, 0xFC, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
\r
124 0x30, 0x0C, 0x70, 0x1C, 0xE0, 0x3C, 0xC0, 0x7C, 0xC0, 0xEC,
\r
125 0xC1, 0xCC, 0xC3, 0x8C, 0xE7, 0x0C, 0x7E, 0x0C, 0x3C, 0x0C,
\r
126 0x30, 0x30, 0x70, 0x38, 0xE0, 0x1C, 0xC0, 0x0C, 0xC0, 0x0C,
\r
127 0xC3, 0x0C, 0xC3, 0x0C, 0xE3, 0x1C, 0x7F, 0xF8, 0x3C, 0xF0,
\r
128 0x03, 0xC0, 0x07, 0xC0, 0x0E, 0xC0, 0x1C, 0xC0, 0x38, 0xC0,
\r
129 0x70, 0xC0, 0xFF, 0xFC, 0xFF, 0xFC, 0x00, 0xC0, 0x00, 0xC0,
\r
130 0xFC, 0x30, 0xFC, 0x38, 0xCC, 0x1C, 0xCC, 0x0C, 0xCC, 0x0C,
\r
131 0xCC, 0x0C, 0xCC, 0x0C, 0xCE, 0x1C, 0xC7, 0xF8, 0xC3, 0xF0,
\r
132 0x3F, 0xF0, 0x7F, 0xF8, 0xE3, 0x1C, 0xC3, 0x0C, 0xC3, 0x0C,
\r
133 0xC3, 0x0C, 0xC3, 0x0C, 0xE3, 0x9C, 0x71, 0xF8, 0x30, 0xF0,
\r
134 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC3, 0xFC,
\r
135 0xC7, 0xFC, 0xCE, 0x00, 0xDC, 0x00, 0xF8, 0x00, 0xF0, 0x00,
\r
136 0x3C, 0xF0, 0x7F, 0xF8, 0xE7, 0x9C, 0xC3, 0x0C, 0xC3, 0x0C,
\r
137 0xC3, 0x0C, 0xC3, 0x0C, 0xE7, 0x9C, 0x7F, 0xF8, 0x3C, 0xF0,
\r
138 0x3C, 0x00, 0x7E, 0x00, 0xE7, 0x0C, 0xC3, 0x0C, 0xC3, 0x1C,
\r
139 0xC3, 0x38, 0xC3, 0x70, 0xE7, 0xE0, 0x7F, 0xC0, 0x3F, 0x80,
\r
140 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x60, 0x3C, 0xF0,
\r
141 0x3C, 0xF0, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x44, 0x3C, 0xEC,
\r
143 0x3C, 0xF8, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
144 0x00, 0x00, 0x03, 0x00, 0x07, 0x80, 0x0F, 0xC0, 0x1C, 0xE0,
\r
145 0x38, 0x70, 0x70, 0x38, 0xE0, 0x1C, 0xC0, 0x0C, 0x00, 0x00,
\r
146 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0,
\r
147 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0,
\r
148 0x00, 0x00, 0xC0, 0x0C, 0xE0, 0x1C, 0x70, 0x38, 0x38, 0x70,
\r
149 0x1C, 0xE0, 0x0F, 0xC0, 0x07, 0x80, 0x03, 0x00, 0x00, 0x00,
\r
150 0x30, 0x00, 0x70, 0x00, 0xE0, 0x00, 0xC0, 0x00, 0xC1, 0xEC,
\r
151 0xC3, 0xEC, 0xC3, 0x00, 0xE6, 0x00, 0x7E, 0x00, 0x3C, 0x00,
\r
152 0x30, 0xF0, 0x71, 0xF8, 0xE3, 0x9C, 0xC3, 0x0C, 0xC3, 0xFC,
\r
153 0xC3, 0xFC, 0xC0, 0x0C, 0xE0, 0x1C, 0x7F, 0xF8, 0x3F, 0xF0,
\r
154 0x3F, 0xFC, 0x7F, 0xFC, 0xE0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
\r
155 0xC0, 0xC0, 0xC0, 0xC0, 0xE0, 0xC0, 0x7F, 0xFC, 0x3F, 0xFC,
\r
156 0xFF, 0xFC, 0xFF, 0xFC, 0xC3, 0x0C, 0xC3, 0x0C, 0xC3, 0x0C,
\r
157 0xC3, 0x0C, 0xC3, 0x0C, 0xE7, 0x9C, 0x7F, 0xF8, 0x3C, 0xF0,
\r
158 0x3F, 0xF0, 0x7F, 0xF8, 0xE0, 0x1C, 0xC0, 0x0C, 0xC0, 0x0C,
\r
159 0xC0, 0x0C, 0xC0, 0x0C, 0xE0, 0x1C, 0x70, 0x38, 0x30, 0x30,
\r
160 0xFF, 0xFC, 0xFF, 0xFC, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C,
\r
161 0xC0, 0x0C, 0xC0, 0x0C, 0xE0, 0x1C, 0x7F, 0xF8, 0x3F, 0xF0,
\r
162 0xFF, 0xFC, 0xFF, 0xFC, 0xC3, 0x0C, 0xC3, 0x0C, 0xC3, 0x0C,
\r
163 0xC3, 0x0C, 0xC3, 0x0C, 0xC3, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C,
\r
164 0xFF, 0xFC, 0xFF, 0xFC, 0xC3, 0x00, 0xC3, 0x00, 0xC3, 0x00,
\r
165 0xC3, 0x00, 0xC3, 0x00, 0xC3, 0x00, 0xC0, 0x00, 0xC0, 0x00,
\r
166 0x3F, 0xF0, 0x7F, 0xF8, 0xE0, 0x1C, 0xC0, 0x0C, 0xC0, 0x0C,
\r
167 0xC3, 0x0C, 0xC3, 0x0C, 0xE3, 0x1C, 0x73, 0xF8, 0x33, 0xF0,
\r
168 0xFF, 0xFC, 0xFF, 0xFC, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00,
\r
169 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xFF, 0xFC, 0xFF, 0xFC,
\r
170 0x00, 0x00, 0x00, 0x00, 0xC0, 0x0C, 0xC0, 0x0C, 0xFF, 0xFC,
\r
171 0xFF, 0xFC, 0xC0, 0x0C, 0xC0, 0x0C, 0x00, 0x00, 0x00, 0x00,
\r
172 0x00, 0x30, 0x00, 0x38, 0xC0, 0x1C, 0xC0, 0x0C, 0xC0, 0x0C,
\r
173 0xC0, 0x1C, 0xFF, 0xF8, 0xFF, 0xF0, 0xC0, 0x00, 0xC0, 0x00,
\r
174 0xFF, 0xFC, 0xFF, 0xFC, 0x07, 0x80, 0x07, 0x80, 0x0F, 0xC0,
\r
175 0x1C, 0xE0, 0x38, 0x70, 0x70, 0x38, 0xE0, 0x1C, 0xC0, 0x0C,
\r
176 0xFF, 0xFC, 0xFF, 0xFC, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C,
\r
177 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C,
\r
178 0xFF, 0xFC, 0xFF, 0xFC, 0x70, 0x00, 0x38, 0x00, 0x1F, 0x00,
\r
179 0x1F, 0x00, 0x38, 0x00, 0x70, 0x00, 0xFF, 0xFC, 0xFF, 0xFC,
\r
180 0xFF, 0xFC, 0xFF, 0xFC, 0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00,
\r
181 0x03, 0x80, 0x01, 0xC0, 0x00, 0xE0, 0xFF, 0xFC, 0xFF, 0xFC,
\r
182 0x3F, 0xF0, 0x7F, 0xF8, 0xE0, 0x1C, 0xC0, 0x0C, 0xC0, 0x0C,
\r
183 0xC0, 0x0C, 0xC0, 0x0C, 0xE0, 0x1C, 0x7F, 0xF8, 0x3F, 0xF0,
\r
184 0xFF, 0xFC, 0xFF, 0xFC, 0xC3, 0x00, 0xC3, 0x00, 0xC3, 0x00,
\r
185 0xC3, 0x00, 0xC3, 0x00, 0xE7, 0x00, 0x7E, 0x00, 0x3C, 0x00,
\r
186 0x3F, 0xF0, 0x7F, 0xF8, 0xE0, 0x1C, 0xC0, 0x0C, 0xC0, 0xCC,
\r
187 0xC0, 0xEC, 0xC0, 0x7C, 0xE0, 0x38, 0x7F, 0xFC, 0x3F, 0xEC,
\r
188 0xFF, 0xFC, 0xFF, 0xFC, 0xC3, 0x00, 0xC3, 0x80, 0xC3, 0x80,
\r
189 0xC3, 0xC0, 0xC3, 0xC0, 0xE7, 0x70, 0x7E, 0x3C, 0x3C, 0x1C,
\r
190 0x3C, 0x18, 0x7E, 0x1C, 0xE7, 0x0C, 0xC3, 0x0C, 0xC3, 0x0C,
\r
191 0xC3, 0x0C, 0xC3, 0x0C, 0xC3, 0x9C, 0xE1, 0xF8, 0x60, 0xF0,
\r
192 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xFF, 0xFC,
\r
193 0xFF, 0xFC, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00,
\r
194 0xFF, 0xF0, 0xFF, 0xF8, 0x00, 0x1C, 0x00, 0x0C, 0x00, 0x0C,
\r
195 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x1C, 0xFF, 0xF8, 0xFF, 0xF0,
\r
196 0xFF, 0xC0, 0xFF, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C,
\r
197 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0xFF, 0xE0, 0xFF, 0xC0,
\r
198 0xFF, 0xF0, 0xFF, 0xF8, 0x00, 0x1C, 0x00, 0x3C, 0x00, 0xF8,
\r
199 0x00, 0xF8, 0x00, 0x3C, 0x00, 0x1C, 0xFF, 0xF8, 0xFF, 0xF0,
\r
200 0xF0, 0x3C, 0xF8, 0x7C, 0x1C, 0xE0, 0x0F, 0xC0, 0x07, 0x80,
\r
201 0x07, 0x80, 0x0F, 0xC0, 0x1C, 0xE0, 0xF8, 0x7C, 0xF0, 0x3C,
\r
202 0xFC, 0x00, 0xFE, 0x00, 0x07, 0x00, 0x03, 0x80, 0x01, 0xFC,
\r
203 0x01, 0xFC, 0x03, 0x80, 0x07, 0x00, 0xFE, 0x00, 0xFC, 0x00,
\r
204 0xC0, 0x3C, 0xC0, 0x7C, 0xC0, 0xEC, 0xC1, 0xCC, 0xC3, 0x8C,
\r
205 0xC7, 0x0C, 0xCE, 0x0C, 0xDC, 0x0C, 0xF8, 0x0C, 0xF0, 0x0C,
\r
206 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0xFF, 0xFC, 0xC0, 0x0C,
\r
207 0xC0, 0x0C, 0xC0, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
208 0x30, 0x00, 0x30, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x03, 0x00,
\r
209 0x03, 0x00, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0x30, 0x00, 0x30,
\r
210 0x00, 0x00, 0x00, 0x00, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C,
\r
211 0xFF, 0xFC, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
212 0x0C, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x00, 0xE0, 0x00,
\r
213 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x0C, 0x00,
\r
214 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C,
\r
215 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C,
\r
216 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00,
\r
217 0x38, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
218 0x00, 0x30, 0x06, 0x78, 0x0E, 0xFC, 0x0C, 0xCC, 0x0C, 0xCC,
\r
219 0x0C, 0xCC, 0x0C, 0xCC, 0x0E, 0xCC, 0x07, 0xFC, 0x03, 0xF8,
\r
220 0xFF, 0xFC, 0xFF, 0xFC, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C,
\r
221 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x9C, 0x01, 0xF8, 0x00, 0xF0,
\r
222 0x03, 0xF0, 0x07, 0xF8, 0x0E, 0x1C, 0x0C, 0x0C, 0x0C, 0x0C,
\r
223 0x0C, 0x0C, 0x0C, 0x0C, 0x0E, 0x1C, 0x07, 0x38, 0x03, 0x30,
\r
224 0x00, 0xF0, 0x01, 0xF8, 0x03, 0x9C, 0x03, 0x0C, 0x03, 0x0C,
\r
225 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0xFF, 0xFC, 0xFF, 0xFC,
\r
226 0x03, 0xF0, 0x07, 0xF8, 0x0E, 0xDC, 0x0C, 0xCC, 0x0C, 0xCC,
\r
227 0x0C, 0xCC, 0x0C, 0xCC, 0x0E, 0xDC, 0x07, 0xD8, 0x03, 0x90,
\r
228 0x00, 0x00, 0x03, 0x00, 0x3F, 0xFC, 0x7F, 0xFC, 0xE3, 0x00,
\r
229 0xE3, 0x00, 0x70, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
230 0x03, 0x18, 0x07, 0x9C, 0x0F, 0xCC, 0x0C, 0xCC, 0x0C, 0xCC,
\r
231 0x0C, 0xCC, 0x0C, 0xCC, 0x0C, 0xDC, 0x0F, 0xF8, 0x07, 0xF0,
\r
232 0xFF, 0xFC, 0xFF, 0xFC, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00,
\r
233 0x03, 0x00, 0x03, 0x80, 0x01, 0xFC, 0x00, 0xFC, 0x00, 0x00,
\r
234 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0xFC,
\r
235 0x1B, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
236 0x00, 0x00, 0x00, 0x30, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x0C,
\r
237 0x00, 0x0C, 0x00, 0x1C, 0xCF, 0xF8, 0xCF, 0xF0, 0x00, 0x00,
\r
238 0x00, 0x00, 0xFF, 0xFC, 0xFF, 0xFC, 0x00, 0xE0, 0x01, 0xE0,
\r
239 0x03, 0xF0, 0x07, 0x38, 0x0E, 0x1C, 0x0C, 0x0C, 0x00, 0x00,
\r
240 0x00, 0x00, 0x00, 0x00, 0xC0, 0x0C, 0xC0, 0x0C, 0xFF, 0xFC,
\r
241 0xFF, 0xFC, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
\r
242 0x0F, 0xFC, 0x0F, 0xFC, 0x0E, 0x00, 0x07, 0x00, 0x03, 0xC0,
\r
243 0x03, 0xC0, 0x07, 0x00, 0x0E, 0x00, 0x0F, 0xFC, 0x0F, 0xFC,
\r
244 0x0F, 0xFC, 0x0F, 0xFC, 0x03, 0x00, 0x07, 0x00, 0x0E, 0x00,
\r
245 0x0C, 0x00, 0x0C, 0x00, 0x0E, 0x00, 0x07, 0xFC, 0x03, 0xFC,
\r
246 0x03, 0xF0, 0x07, 0xF8, 0x0E, 0x1C, 0x0C, 0x0C, 0x0C, 0x0C,
\r
247 0x0C, 0x0C, 0x0C, 0x0C, 0x0E, 0x1C, 0x07, 0xF8, 0x03, 0xF0,
\r
248 0x0F, 0xFC, 0x0F, 0xFC, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0,
\r
249 0x0C, 0xC0, 0x0C, 0xC0, 0x0F, 0xC0, 0x07, 0x80, 0x03, 0x00,
\r
250 0x03, 0x00, 0x07, 0x80, 0x0F, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0,
\r
251 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0F, 0xFC, 0x0F, 0xFC,
\r
252 0x0F, 0xFC, 0x0F, 0xFC, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x00,
\r
253 0x0C, 0x00, 0x0C, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x03, 0x00,
\r
254 0x03, 0x18, 0x07, 0x9C, 0x0F, 0xCC, 0x0C, 0xCC, 0x0C, 0xCC,
\r
255 0x0C, 0xCC, 0x0C, 0xCC, 0x0C, 0xFC, 0x0E, 0x78, 0x06, 0x30,
\r
256 0x00, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0xFF, 0xF0, 0xFF, 0xF8,
\r
257 0x0C, 0x1C, 0x0C, 0x1C, 0x0C, 0x38, 0x0C, 0x30, 0x00, 0x00,
\r
258 0x0F, 0xF0, 0x0F, 0xF8, 0x00, 0x1C, 0x00, 0x0C, 0x00, 0x0C,
\r
259 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x1C, 0x0F, 0xF8, 0x0F, 0xF0,
\r
260 0x0F, 0xC0, 0x0F, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C,
\r
261 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x0F, 0xE0, 0x0F, 0xC0,
\r
262 0x0F, 0xF0, 0x0F, 0xF8, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0xF8,
\r
263 0x00, 0xF8, 0x00, 0x1C, 0x00, 0x1C, 0x0F, 0xF8, 0x0F, 0xF0,
\r
264 0x0C, 0x0C, 0x0E, 0x1C, 0x07, 0x38, 0x03, 0xF0, 0x01, 0xE0,
\r
265 0x01, 0xE0, 0x03, 0xF0, 0x07, 0x38, 0x0E, 0x1C, 0x0C, 0x0C,
\r
266 0x0C, 0x00, 0x0E, 0x00, 0x07, 0x0C, 0x03, 0x9C, 0x01, 0xF8,
\r
267 0x01, 0xF0, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x00, 0x0C, 0x00,
\r
268 0x0C, 0x0C, 0x0C, 0x1C, 0x0C, 0x3C, 0x0C, 0x7C, 0x0C, 0xEC,
\r
269 0x0D, 0xCC, 0x0F, 0x8C, 0x0F, 0x0C, 0x0E, 0x0C, 0x0C, 0x0C,
\r
270 0x00, 0x00, 0x03, 0x00, 0x07, 0x80, 0x3F, 0xF0, 0x7C, 0xF8,
\r
271 0xE0, 0x1C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0x00, 0x00,
\r
272 0x03, 0x0C, 0x03, 0x0C, 0x3F, 0xFC, 0x7F, 0xFC, 0xE3, 0x0C,
\r
273 0xC3, 0x0C, 0xC0, 0x0C, 0xE0, 0x0C, 0x70, 0x0C, 0x30, 0x0C,
\r
274 0x00, 0x00, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xE0, 0x1C,
\r
275 0x7C, 0xF8, 0x3F, 0xF0, 0x07, 0x80, 0x03, 0x00, 0x00, 0x00,
\r
276 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00,
\r
277 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00,
\r
278 0xFF, 0xFC, 0xFF, 0xFC, 0xFF, 0xFC, 0xFF, 0xFC, 0xFF, 0xFC,
\r
279 0xFF, 0xFC, 0xFF, 0xFC, 0xFF, 0xFC, 0xFF, 0xFC, 0xFF, 0xFC
\r
283 * \brief Prepare to write GRAM data for ili93xx.
\r
285 static void ili93xx_write_ram_prepare(void)
\r
287 if (g_uc_device_type == DEVICE_TYPE_ILI9325) {
\r
288 /** Write Data to GRAM (R22h) */
\r
290 LCD_IR(ILI9325_GRAM_DATA_REG);
\r
291 } else if (g_uc_device_type == DEVICE_TYPE_ILI9341) {
\r
292 /** memory write command (R2Ch)*/
\r
293 LCD_IR(ILI9341_CMD_MEMORY_WRITE);
\r
295 LCD_IR(ILI9341_CMD_WRITE_MEMORY_CONTINUE);
\r
300 * \brief Write data to LCD GRAM.
\r
302 * \param ul_color 24-bits RGB color.
\r
304 static void ili93xx_write_ram(ili93xx_color_t ul_color)
\r
306 LCD_WD((ul_color >> 16) & 0xFF);
\r
307 LCD_WD((ul_color >> 8) & 0xFF);
\r
308 LCD_WD(ul_color & 0xFF);
\r
312 * \brief Write multiple data in buffer to LCD controller for ili93xx.
\r
314 * \param p_ul_buf data buffer.
\r
315 * \param ul_size size in pixels.
\r
317 static void ili93xx_write_ram_buffer(const ili93xx_color_t *p_ul_buf,
\r
321 for (ul_addr = 0; ul_addr < (ul_size - ul_size % 8); ul_addr += 8) {
\r
322 ili93xx_write_ram(p_ul_buf[ul_addr]);
\r
323 ili93xx_write_ram(p_ul_buf[ul_addr + 1]);
\r
324 ili93xx_write_ram(p_ul_buf[ul_addr + 2]);
\r
325 ili93xx_write_ram(p_ul_buf[ul_addr + 3]);
\r
326 ili93xx_write_ram(p_ul_buf[ul_addr + 4]);
\r
327 ili93xx_write_ram(p_ul_buf[ul_addr + 5]);
\r
328 ili93xx_write_ram(p_ul_buf[ul_addr + 6]);
\r
329 ili93xx_write_ram(p_ul_buf[ul_addr + 7]);
\r
331 for (; ul_addr < ul_size; ul_addr++) {
\r
332 ili93xx_write_ram(p_ul_buf[ul_addr]);
\r
337 * \brief Write a word (16bits)to LCD Register.
\r
339 * \param uc_reg register address.
\r
340 * \param us_data data to be written.
\r
342 static void ili93xx_write_register_word(uint8_t uc_reg, uint16_t us_data)
\r
346 LCD_WD((us_data >> 8) & 0xFF);
\r
347 LCD_WD(us_data & 0xFF);
\r
351 * \brief Write data to LCD Register for ili93xx.
\r
353 * \param uc_reg register address.
\r
354 * \param us_data data to be written.
\r
356 static void ili93xx_write_register(uint8_t uc_reg, uint8_t *p_data,
\r
357 uint8_t uc_datacnt)
\r
363 for (i = 0; i < uc_datacnt; i++) {
\r
369 * \brief Prepare to read GRAM data for ili93xx.
\r
371 static void ili93xx_read_ram_prepare(void)
\r
373 if (g_uc_device_type == DEVICE_TYPE_ILI9325) {
\r
375 /** Write Data to GRAM (R22h) */
\r
376 LCD_IR(ILI9325_GRAM_DATA_REG);
\r
377 } else if (g_uc_device_type == DEVICE_TYPE_ILI9341) {
\r
379 /** Write Data to GRAM (R2Eh) */
\r
380 LCD_IR(ILI9341_CMD_MEMORY_READ);
\r
385 * \brief Read data to LCD GRAM for ili93xx.
\r
387 * \note For ili9325, because pixel data LCD GRAM is 18-bits, so convertion
\r
388 * to RGB 24-bits will cause low color bit lose.
\r
390 * \return color 24-bits RGB color.
\r
392 static uint32_t ili93xx_read_ram(void)
\r
396 if (g_uc_device_type == DEVICE_TYPE_ILI9325) {
\r
398 value[0] = LCD_RD();
\r
399 value[1] = LCD_RD();
\r
400 /** data upper byte*/
\r
401 value[0] = LCD_RD();
\r
402 /** data lower byte */
\r
403 value[1] = LCD_RD();
\r
405 /** Convert RGB565 to RGB888 */
\r
406 /** For BGR format */
\r
407 color = ((value[0] & 0xF8)) | ((value[0] & 0x07) << 13) |
\r
408 ((value[1] & 0xE0) << 5) |
\r
409 ((value[1] & 0x1F) << 19);
\r
410 } else if (g_uc_device_type == DEVICE_TYPE_ILI9341) {
\r
412 value[0] = LCD_RD();
\r
413 /** the highest byte - R byte*/
\r
414 value[0] = LCD_RD();
\r
415 /** the middle byte - G byte*/
\r
416 value[1] = LCD_RD();
\r
417 /** the lowest byte - B byte*/
\r
418 value[2] = LCD_RD();
\r
419 /** combine R, G, B byte to a color value */
\r
420 color = (value[0] << 16) | (value[1] << 8) | value[2];
\r
427 * \brief Read data from LCD Register.
\r
429 * \param uc_reg register address.
\r
430 * \param p_data the pointer to the read data.
\r
431 * \param uc_datacnt the number of the read data
\r
433 static void ili93xx_read_register(uint8_t uc_reg, uint8_t *p_data,
\r
434 uint8_t uc_datacnt)
\r
441 for (i = 0; i < uc_datacnt; i++) {
\r
442 p_data[i] = LCD_RD();
\r
447 * \brief Delay function.
\r
449 static void ili93xx_delay(uint32_t ul_ms)
\r
451 volatile uint32_t i;
\r
453 for (i = 0; i < ul_ms; i++) {
\r
454 for (i = 0; i < 100000; i++) {
\r
460 * \brief Check box coordinates.
\r
462 * \param p_ul_x1 X coordinate of upper-left corner on LCD.
\r
463 * \param p_ul_y1 Y coordinate of upper-left corner on LCD.
\r
464 * \param p_ul_x2 X coordinate of lower-right corner on LCD.
\r
465 * \param p_ul_y2 Y coordinate of lower-right corner on LCD.
\r
467 static void ili93xx_check_box_coordinates(uint32_t *p_ul_x1, uint32_t *p_ul_y1,
\r
468 uint32_t *p_ul_x2, uint32_t *p_ul_y2)
\r
472 if (*p_ul_x1 >= g_ul_lcd_x_length) {
\r
473 *p_ul_x1 = g_ul_lcd_x_length - 1;
\r
476 if (*p_ul_x2 >= g_ul_lcd_x_length) {
\r
477 *p_ul_x2 = g_ul_lcd_x_length - 1;
\r
480 if (*p_ul_y1 >= g_ul_lcd_y_length) {
\r
481 *p_ul_y1 = g_ul_lcd_y_length - 1;
\r
484 if (*p_ul_y2 >= g_ul_lcd_y_length) {
\r
485 *p_ul_y2 = g_ul_lcd_y_length - 1;
\r
488 if (*p_ul_x1 > *p_ul_x2) {
\r
490 *p_ul_x1 = *p_ul_x2;
\r
494 if (*p_ul_y1 > *p_ul_y2) {
\r
496 *p_ul_y1 = *p_ul_y2;
\r
502 * \brief Read device ID to idenfity the device
\r
503 * ILI9325 device ID locates in Device Code Read (R00h) register.
\r
504 * ILI9341 device ID locates in Read ID4 (RD3h) register.
\r
506 * \return 0 if secceed in identifying device; otherwise fails.
\r
508 uint8_t ili93xx_device_type_identify(void)
\r
510 uint8_t paratable[6];
\r
513 /** Read ID4 (RD4h) register to get device code for ILI9341*/
\r
514 ili93xx_read_register(ILI9341_CMD_READ_ID4, paratable, 4);
\r
515 chipid = ((uint16_t)paratable[2] << 8) + paratable[3];
\r
517 if (chipid == ILI9341_DEVICE_CODE) {
\r
518 g_uc_device_type = DEVICE_TYPE_ILI9341;
\r
522 /** Driver Code Read (R00h) for ILI9325*/
\r
523 ili93xx_read_register(ILI9325_DEVICE_CODE_REG, paratable, 2);
\r
524 chipid = ((uint16_t)paratable[0] << 8) + paratable[1];
\r
525 if (chipid == ILI9325_DEVICE_CODE) {
\r
526 g_uc_device_type = DEVICE_TYPE_ILI9325;
\r
534 * \brief Initialize the ILI93XX lcd driver.
\r
536 * \note Make sure below works have been done before calling ili93xx_init()
\r
537 * 1. ILI93xx related Pins have been initialized correctly.
\r
538 * 2. SMC has been configured correctly for access ILI93xx (8-bit system
\r
539 * interface for now).
\r
541 * \param p_opt pointer to ILI93xx option structure.
\r
543 * \return 0 if initialization succeeds, otherwise fails.
\r
545 uint32_t ili93xx_init(struct ili93xx_opt_t *p_opt)
\r
547 uint8_t paratable[15];
\r
549 /** Identify the LCD driver device*/
\r
550 if (ili93xx_device_type_identify() != 0) {
\r
554 g_ul_lcd_x_length = ILI93XX_LCD_WIDTH;
\r
555 g_ul_lcd_y_length = ILI93XX_LCD_HEIGHT;
\r
557 if (g_uc_device_type == DEVICE_TYPE_ILI9325) {
\r
558 /** Turn off LCD */
\r
559 ili93xx_write_register_word(ILI9325_DISP_CTRL1, ILI9325_DISP_CTRL1_GON |
\r
560 ILI9325_DISP_CTRL1_DTE | ILI9325_DISP_CTRL1_D(0x03));
\r
562 /** Start initial sequence */
\r
563 /** Disable sleep and standby mode*/
\r
564 ili93xx_write_register_word(ILI9325_POWER_CTRL1, 0x0000);
\r
565 /** Start internal OSC */
\r
566 ili93xx_write_register_word(ILI9325_START_OSC_CTRL,
\r
567 ILI9325_START_OSC_CTRL_EN);
\r
568 /** Set SS bit and direction output from S720 to S1 */
\r
569 ili93xx_write_register_word(ILI9325_DRIVER_OUTPUT_CTRL1,
\r
570 ILI9325_DRIVER_OUTPUT_CTRL1_SS);
\r
571 /** Set 1 line inversion */
\r
572 ili93xx_write_register_word(ILI9325_LCD_DRIVING_CTRL,
\r
573 ILI9325_LCD_DRIVING_CTRL_BIT10 | ILI9325_LCD_DRIVING_CTRL_EOR
\r
574 | ILI9325_LCD_DRIVING_CTRL_BC0);
\r
575 /** Disable resizing feature */
\r
576 ili93xx_write_register_word(ILI9325_RESIZE_CTRL, 0x0000);
\r
577 /** Set the back porch and front porch */
\r
578 ili93xx_write_register_word(ILI9325_DISP_CTRL2,
\r
579 ILI9325_DISP_CTRL2_BP(
\r
580 0x07) | ILI9325_DISP_CTRL2_FP(0x02));
\r
581 /** Set non-display area refresh cycle ISC[3:0] */
\r
582 ili93xx_write_register_word(ILI9325_DISP_CTRL3, 0x0000);
\r
583 /** Disable FMARK function */
\r
584 ili93xx_write_register_word(ILI9325_DISP_CTRL4, 0x0000);
\r
585 /** 18-bit RGB interface and writing display data by system
\r
587 ili93xx_write_register_word(ILI9325_RGB_DISP_INTERFACE_CTRL1,
\r
589 /** Set the output position of frame cycle */
\r
590 ili93xx_write_register_word(ILI9325_FRAME_MAKER_POS, 0x0000);
\r
591 /** RGB interface polarity */
\r
592 ili93xx_write_register_word(ILI9325_RGB_DISP_INTERFACE_CTRL2,
\r
595 /** Power on sequence */
\r
596 /** Disable sleep and standby mode */
\r
597 ili93xx_write_register_word(ILI9325_POWER_CTRL1, 0x0000);
\r
600 * Selects the operating frequency of the step-up circuit 1,2
\r
601 * and Sets the ratio factor of Vci.
\r
603 ili93xx_write_register_word(ILI9325_POWER_CTRL2, 0x0000);
\r
604 /** Set VREG1OUT voltage */
\r
605 ili93xx_write_register_word(ILI9325_POWER_CTRL3, 0x0000);
\r
606 /** Set VCOM amplitude */
\r
607 ili93xx_write_register_word(ILI9325_POWER_CTRL4, 0x0000);
\r
608 ili93xx_delay(200);
\r
610 /** Enable power supply and source driver */
\r
613 * Adjusts the constant current and Sets the factor used
\r
614 * in the step-up circuits.
\r
616 ili93xx_write_register_word(ILI9325_POWER_CTRL1,
\r
617 ILI9325_POWER_CTRL1_SAP | ILI9325_POWER_CTRL1_BT(0x02) |
\r
618 ILI9325_POWER_CTRL1_APE |
\r
619 ILI9325_POWER_CTRL1_AP(0x01));
\r
622 * Select the operating frequency of the step-up circuit 1,2 and
\r
623 * Sets the ratio factor of Vci
\r
625 ili93xx_write_register_word(ILI9325_POWER_CTRL2,
\r
626 ILI9325_POWER_CTRL2_DC1(0x02) |
\r
627 ILI9325_POWER_CTRL2_DC0(0x02) | ILI9325_POWER_CTRL2_VC(0x07));
\r
629 /** Internal reference voltage= Vci */
\r
630 ili93xx_write_register_word(ILI9325_POWER_CTRL3,
\r
631 ILI9325_POWER_CTRL3_PON | ILI9325_POWER_CTRL3_VRH(0x0B));
\r
633 /** Set VDV[4:0] for VCOM amplitude */
\r
634 ili93xx_write_register_word(ILI9325_POWER_CTRL4,
\r
635 ILI9325_POWER_CTRL4_VDV(0x11));
\r
636 /** Set VCM[5:0] for VCOMH */
\r
637 ili93xx_write_register_word(ILI9325_POWER_CTRL7,
\r
638 ILI9325_POWER_CTRL7_VCM(0x19));
\r
639 /** Set Frame Rate */
\r
640 ili93xx_write_register_word(ILI9325_FRAME_RATE_AND_COLOR_CTRL,
\r
641 ILI9325_FRAME_RATE_AND_COLOR_CTRL_FRS(0x0D));
\r
644 /** Adjust the Gamma Curve */
\r
645 ili93xx_write_register_word(ILI9325_GAMMA_CTL1, 0x0000);
\r
646 ili93xx_write_register_word(ILI9325_GAMMA_CTL2,
\r
647 ILI9325_GAMMA_CTL2_KP3(0x02) |
\r
648 ILI9325_GAMMA_CTL2_KP2(0x04));
\r
649 ili93xx_write_register_word(ILI9325_GAMMA_CTL3,
\r
650 ILI9325_GAMMA_CTL3_KP5(0x02) |
\r
651 ILI9325_GAMMA_CTL3_KP4(0x00));
\r
652 ili93xx_write_register_word(ILI9325_GAMMA_CTL4,
\r
653 ILI9325_GAMMA_CTL4_RP1(0x00) |
\r
654 ILI9325_GAMMA_CTL4_RP0(0x07));
\r
655 ili93xx_write_register_word(ILI9325_GAMMA_CTL5,
\r
656 ILI9325_GAMMA_CTL5_VRP1(0x14) |
\r
657 ILI9325_GAMMA_CTL5_VRP0(0x04));
\r
658 ili93xx_write_register_word(ILI9325_GAMMA_CTL6,
\r
659 ILI9325_GAMMA_CTL6_KN1(0x07) |
\r
660 ILI9325_GAMMA_CTL6_KN0(0x05));
\r
661 ili93xx_write_register_word(ILI9325_GAMMA_CTL7,
\r
662 ILI9325_GAMMA_CTL7_KN3(0x03) |
\r
663 ILI9325_GAMMA_CTL7_KN2(0x05));
\r
664 ili93xx_write_register_word(ILI9325_GAMMA_CTL8,
\r
665 ILI9325_GAMMA_CTL8_KN5(0x07) |
\r
666 ILI9325_GAMMA_CTL8_KN4(0x07));
\r
667 ili93xx_write_register_word(ILI9325_GAMMA_CTL9,
\r
668 ILI9325_GAMMA_CTL9_RN1(0x07) |
\r
669 ILI9325_GAMMA_CTL9_RN0(0x01));
\r
670 ili93xx_write_register_word(ILI9325_GAMMA_CTL10,
\r
671 ILI9325_GAMMA_CTL10_VRN1(0x00) |
\r
672 ILI9325_GAMMA_CTL10_VRN0(0x0E));
\r
674 * Use the high speed write mode (HWM=1)
\r
675 * When TRI = 1, data are transferred to the internal RAM in
\r
676 * 8-bit x 3 transfers mode via the 8-bit interface.
\r
677 * DFM Set the mode of transferring data to the internal RAM
\r
679 * I/D[1:0] = 11 Horizontal : increment Vertical : increment,
\r
682 ili93xx_write_register_word(ILI9325_ENTRY_MODE,
\r
683 ILI9325_ENTRY_MODE_TRI | ILI9325_ENTRY_MODE_DFM |
\r
684 ILI9325_ENTRY_MODE_ID(0x01) | ILI9325_ENTRY_MODE_BGR);
\r
686 * Sets the number of lines to drive the LCD at an interval of 8
\r
687 * lines. The scan direction is from G320 to G1
\r
689 ili93xx_write_register_word(ILI9325_DRIVER_OUTPUT_CTRL2,
\r
690 ILI9325_DRIVER_OUTPUT_CTRL2_GS |
\r
691 ILI9325_DRIVER_OUTPUT_CTRL2_NL(0x27));
\r
693 /** Vertical Scrolling */
\r
694 /** Disable scrolling and enable the grayscale inversion */
\r
695 ili93xx_write_register_word(ILI9325_BASE_IMG_DISP_CTRL,
\r
696 ILI9325_BASE_IMG_DISP_CTRL_REV);
\r
697 ili93xx_write_register_word(ILI9325_VERTICAL_SCROLL_CTRL,
\r
700 /** Disable Partial Display */
\r
701 ili93xx_write_register_word(ILI9325_PARTIAL_IMG1_DISP_POS,
\r
703 ili93xx_write_register_word(
\r
704 ILI9325_PARTIAL_IMG1_AREA_START_LINE,
\r
706 ili93xx_write_register_word(ILI9325_PARTIAL_IMG1_AREA_END_LINE,
\r
708 ili93xx_write_register_word(ILI9325_PARTIAL_IMG2_DISP_POS,
\r
710 ili93xx_write_register_word(
\r
711 ILI9325_PARTIAL_IMG2_AREA_START_LINE,
\r
713 ili93xx_write_register_word(ILI9325_PARTIAL_IMG2_AREA_END_LINE,
\r
716 /** Panel Control */
\r
717 ili93xx_write_register_word(ILI9325_PANEL_INTERFACE_CTRL1,
\r
718 ILI9325_PANEL_INTERFACE_CTRL1_RTNI(0x10));
\r
719 ili93xx_write_register_word(ILI9325_PANEL_INTERFACE_CTRL2,
\r
720 ILI9325_PANEL_INTERFACE_CTRL2_NOWI(0x06));
\r
721 ili93xx_write_register_word(ILI9325_PANEL_INTERFACE_CTRL4,
\r
722 ILI9325_PANEL_INTERFACE_CTRL4_DIVE(0x01) |
\r
723 ILI9325_PANEL_INTERFACE_CTRL4_RTNE(0x10));
\r
725 ili93xx_set_window(0, 0, p_opt->ul_width, p_opt->ul_height);
\r
726 ili93xx_set_foreground_color(p_opt->foreground_color);
\r
727 ili93xx_set_cursor_position(0, 0);
\r
728 } else if (g_uc_device_type == DEVICE_TYPE_ILI9341) {
\r
729 /** init for ILI9341 **/
\r
730 /** power control A configuration*/
\r
731 paratable[0] = 0x39;
\r
732 paratable[1] = 0x2C;
\r
733 paratable[2] = 0x00;
\r
734 paratable[3] = 0x34;
\r
735 paratable[4] = 0x02;
\r
736 ili93xx_write_register(ILI9341_CMD_POWER_CONTROL_A, paratable, 5);
\r
738 /** power control B configuration */
\r
740 paratable[1] = 0xAA;
\r
741 paratable[2] = 0xB0;
\r
742 ili93xx_write_register(ILI9341_CMD_POWER_CONTROL_B, paratable, 3);
\r
744 /** Pump Ratio Control configuration */
\r
745 paratable[0] = 0x30;
\r
746 ili93xx_write_register(ILI9341_CMD_PUMP_RATIO_CONTROL,
\r
749 /** Power Control 1 configuration*/
\r
750 paratable[0] = 0x25;
\r
751 ili93xx_write_register(ILI9341_CMD_POWER_CONTROL_1, paratable, 1);
\r
753 /** Power Control 2 configuration*/
\r
754 paratable[0] = 0x11;
\r
755 ili93xx_write_register(ILI9341_CMD_POWER_CONTROL_2, paratable, 1);
\r
757 /** VOM Control 1 configuration*/
\r
758 paratable[0] = 0x5C;
\r
759 paratable[1] = 0x4C;
\r
760 ili93xx_write_register(ILI9341_CMD_VCOM_CONTROL_1, paratable, 2);
\r
762 /** VOM control 2 configuration*/
\r
763 paratable[0] = 0x94;
\r
764 ili93xx_write_register(ILI9341_CMD_VCOM_CONTROL_2, paratable, 1);
\r
766 /** Driver Timing Control A configuration*/
\r
767 paratable[0] = 0x85;
\r
768 paratable[1] = 0x01;
\r
769 paratable[2] = 0x78;
\r
770 ili93xx_write_register(ILI9341_CMD_DRIVER_TIMING_CTL_A, paratable, 3);
\r
772 /** Driver Timing Control B configuration*/
\r
773 paratable[0] = 0x00;
\r
774 paratable[1] = 0x00;
\r
775 ili93xx_write_register(ILI9341_CMD_DRIVER_TIMING_CTL_B, paratable, 2);
\r
777 /** Memory Access Control configuration*/
\r
778 paratable[0] = ILI9341_CMD_MEMORY_ACCESS_CONTROL_MX |
\r
779 ILI9341_CMD_MEMORY_ACCESS_CONTROL_BGR;
\r
780 ili93xx_write_register(ILI9341_CMD_MEMORY_ACCESS_CONTROL,
\r
783 /** Colmod Pixel Format Set configuation*/
\r
784 paratable[0] = 0x06;
\r
785 ili93xx_write_register(ILI9341_CMD_PIXEL_FORMAT_SET, paratable, 1);
\r
787 /** Display Function Control */
\r
788 paratable[0] = 0x02;
\r
789 paratable[1] = 0x82;
\r
790 paratable[2] = 0x27;
\r
791 paratable[3] = 0x00;
\r
792 ili93xx_write_register(ILI9341_CMD_DISPLAY_FUNCTION_CTL,
\r
795 paratable[0] = 0x00;
\r
796 ili93xx_write_register(ILI9341_CMD_ENABLE_3_GAMMA_CONTROL,
\r
799 paratable[0] = 0x01;
\r
800 ili93xx_write_register(ILI9341_CMD_GAMMA_SET, paratable,1);
\r
802 /** set gamma curve parameters*/
\r
813 paratable[10]=0x10;
\r
814 paratable[11]=0x03;
\r
815 paratable[12]=0x0E;
\r
816 paratable[13]=0x09;
\r
817 paratable[14]=0x00;
\r
818 ili93xx_write_register(ILI9341_CMD_POSITIVE_GAMMA_CORRECTION,
\r
830 paratable[10]=0x0F;
\r
831 paratable[11]=0x0C;
\r
832 paratable[12]=0x31;
\r
833 paratable[13]=0x36;
\r
834 paratable[14]=0x0F;
\r
835 ili93xx_write_register(ILI9341_CMD_NEGATIVE_GAMMA_CORRECTION,
\r
838 /** set window area*/
\r
839 ili93xx_set_window(0, 0, p_opt->ul_width, p_opt->ul_height);
\r
840 ili93xx_set_foreground_color(p_opt->foreground_color);
\r
841 /** Leave sleep mode*/
\r
842 ili93xx_write_register(ILI9341_CMD_SLEEP_OUT, paratable, 0);
\r
845 ili93xx_write_register(ILI9341_CMD_DISPLAY_ON, paratable, 0);
\r
847 /** exit with return value 1 if device type is not supported.*/
\r
855 * \brief get the device type.
\r
857 uint8_t ili93xx_device_type(void)
\r
859 return g_uc_device_type;
\r
863 * \brief Turn on the LCD.
\r
865 void ili93xx_display_on(void)
\r
867 if (g_uc_device_type == DEVICE_TYPE_ILI9325) {
\r
868 ili93xx_write_register_word(ILI9325_DISP_CTRL1,
\r
869 ILI9325_DISP_CTRL1_BASEE |
\r
870 ILI9325_DISP_CTRL1_GON |
\r
871 ILI9325_DISP_CTRL1_DTE |
\r
872 ILI9325_DISP_CTRL1_D(0x03));
\r
873 } else if (g_uc_device_type == DEVICE_TYPE_ILI9341) {
\r
874 ili93xx_write_register(ILI9341_CMD_DISPLAY_ON, NULL, 0);
\r
879 * \brief Turn off the LCD.
\r
881 void ili93xx_display_off(void)
\r
883 if (g_uc_device_type == DEVICE_TYPE_ILI9325) {
\r
884 ili93xx_write_register_word(ILI9325_DISP_CTRL1, 0x00);
\r
885 } else if (g_uc_device_type == DEVICE_TYPE_ILI9341) {
\r
886 ili93xx_write_register(ILI9341_CMD_DISPLAY_OFF, NULL, 0);
\r
891 * \brief Set foreground color.
\r
893 * \param ul_color foreground color.
\r
895 void ili93xx_set_foreground_color(ili93xx_color_t ul_color)
\r
899 /** Fill the cache with selected color */
\r
900 for (i = 0; i < LCD_DATA_CACHE_SIZE; ++i) {
\r
901 g_ul_pixel_cache[i] = ul_color;
\r
906 * \brief Fill the LCD buffer with the specified color.
\r
908 * \param ul_color fill color.
\r
910 void ili93xx_fill(ili93xx_color_t ul_color)
\r
913 if (g_uc_device_type == DEVICE_TYPE_ILI9325) {
\r
914 ili93xx_set_cursor_position(0, 0);
\r
915 } else if (g_uc_device_type == DEVICE_TYPE_ILI9341) {
\r
916 ili93xx_set_window(0, 0, g_ul_lcd_x_length, g_ul_lcd_y_length);
\r
919 ili93xx_write_ram_prepare();
\r
921 for (dw = ILI93XX_LCD_WIDTH * ILI93XX_LCD_HEIGHT; dw > 0; dw--) {
\r
922 ili93xx_write_ram(ul_color);
\r
927 * \brief Set display window.
\r
929 * \param ul_x Horizontal address start position
\r
930 * \param ul_y Vertical address start position
\r
931 * \param ul_width The width of the window.
\r
932 * \param ul_height The height of the window.
\r
934 void ili93xx_set_window(uint32_t ul_x, uint32_t ul_y, uint32_t ul_width,
\r
935 uint32_t ul_height)
\r
937 Assert(ul_x <= (g_ul_lcd_x_length - 1));
\r
938 Assert(ul_y <= (g_ul_lcd_y_length - 1));
\r
939 Assert(ul_width <= (g_ul_lcd_x_length - ul_x));
\r
940 Assert(ul_height <= (g_ul_lcd_y_length - ul_y));
\r
941 if (g_uc_device_type == DEVICE_TYPE_ILI9325) {
\r
942 /** Set Horizontal Address Start Position */
\r
943 ili93xx_write_register_word(ILI9325_HORIZONTAL_ADDR_START,
\r
946 /** Set Horizontal Address End Position */
\r
947 ili93xx_write_register_word(ILI9325_HORIZONTAL_ADDR_END,
\r
948 (uint16_t)(ul_x + ul_width - 1));
\r
950 /** Set Vertical Address Start Position */
\r
951 ili93xx_write_register_word(ILI9325_VERTICAL_ADDR_START,
\r
954 /** Set Vertical Address End Position */
\r
955 ili93xx_write_register_word(ILI9325_VERTICAL_ADDR_END,
\r
956 (uint16_t)(ul_y + ul_height - 1));
\r
957 } else if (g_uc_device_type == DEVICE_TYPE_ILI9341) {
\r
958 uint8_t paratable[4];
\r
960 /** Set Column Address Position */
\r
961 paratable[0] = (ul_x >> 8) & 0xFF;
\r
962 paratable[1] = ul_x & 0xFF;
\r
963 paratable[2] = ((ul_x + ul_width - 1) >> 8) & 0xFF;
\r
964 paratable[3] = (ul_x + ul_width - 1) & 0xFF;
\r
965 ili93xx_write_register(ILI9341_CMD_COLUMN_ADDRESS_SET,
\r
968 /** Set Page Address Position */
\r
969 paratable[0] = (ul_y >> 8) & 0xFF;
\r
970 paratable[1] = ul_y & 0xFF;
\r
971 paratable[2] = ((ul_y + ul_height - 1) >> 8) & 0xFF;
\r
972 paratable[3] = (ul_y + ul_height - 1) & 0xFF;
\r
973 ili93xx_write_register(ILI9341_CMD_PAGE_ADDRESS_SET,
\r
979 * \brief Set cursor of LCD screen.
\r
981 * \param us_x X coordinate of upper-left corner on LCD.
\r
982 * \param us_y Y coordinate of upper-left corner on LCD.
\r
984 void ili93xx_set_cursor_position(uint16_t us_x, uint16_t us_y)
\r
986 if (g_uc_device_type == DEVICE_TYPE_ILI9325) {
\r
987 /** GRAM Horizontal/Vertical Address Set (R20h, R21h) */
\r
988 ili93xx_write_register_word(ILI9325_HORIZONTAL_GRAM_ADDR_SET, us_x);
\r
989 ili93xx_write_register_word(ILI9325_VERTICAL_GRAM_ADDR_SET, us_y);
\r
990 } else if (g_uc_device_type == DEVICE_TYPE_ILI9341) {
\r
991 /** There is no corresponding operation for ILI9341. */
\r
996 * \brief Scroll up/down for the number of specified lines.
\r
998 * \param ul_lines number of lines to scroll.
\r
1000 void ili93xx_scroll(int32_t ul_lines)
\r
1002 if (g_uc_device_type == DEVICE_TYPE_ILI9325) {
\r
1003 ili93xx_write_register_word(ILI9325_VERTICAL_SCROLL_CTRL, ul_lines);
\r
1004 } else if (g_uc_device_type == DEVICE_TYPE_ILI9341) {
\r
1005 uint8_t paratable[2];
\r
1007 paratable[0] = (ul_lines >> 8) & 0xFF;
\r
1008 paratable[1] = ul_lines & 0xFF;
\r
1009 ili93xx_write_register(ILI9341_CMD_VERT_SCROLL_START_ADDRESS,
\r
1015 * \brief Vertical Scroll area definition for ili9341.
\r
1017 * \param us_tfa the top fixed area (the No. of lines)
\r
1018 * \param us_vsa the height of the vetical scrolling area
\r
1019 * \param us_bfa the bottom fixed area (the No. of lines)
\r
1021 void ili93xx_vscroll_area_define(uint16_t us_tfa, uint16_t us_vsa,
\r
1024 if (g_uc_device_type == DEVICE_TYPE_ILI9341) {
\r
1025 uint8_t paratable[6];
\r
1027 paratable[0] = (us_tfa >> 8) & 0xFF;
\r
1028 paratable[1] = us_tfa & 0xFF;
\r
1029 paratable[2] = (us_vsa >> 8) & 0xFF;
\r
1030 paratable[3] = us_vsa & 0xFF;
\r
1031 paratable[4] = (us_bfa >> 8) & 0xFF;
\r
1032 paratable[5] = us_bfa & 0xFF;
\r
1033 ili93xx_write_register(ILI9341_CMD_VERT_SCROLL_DEFINITION,
\r
1039 * \brief Enable the scrolling feature.
\r
1041 void ili93xx_enable_scroll(void)
\r
1043 if (g_uc_device_type == DEVICE_TYPE_ILI9325) {
\r
1044 ili93xx_write_register_word(ILI9325_BASE_IMG_DISP_CTRL,
\r
1045 ILI9325_BASE_IMG_DISP_CTRL_REV |
\r
1046 ILI9325_BASE_IMG_DISP_CTRL_VLE);
\r
1047 } else if (g_uc_device_type == DEVICE_TYPE_ILI9341) {
\r
1048 /** no operation needed for ILI9341*/
\r
1053 * \brief Disable the scrolling feature.
\r
1055 void ili93xx_disable_scroll(void)
\r
1057 if (g_uc_device_type == DEVICE_TYPE_ILI9325) {
\r
1058 ili93xx_write_register_word(ILI9325_BASE_IMG_DISP_CTRL,
\r
1059 ILI9325_BASE_IMG_DISP_CTRL_REV);
\r
1060 } else if (g_uc_device_type == DEVICE_TYPE_ILI9341) {
\r
1061 ili93xx_display_off();
\r
1062 ili93xx_write_register(ILI9341_CMD_NORMAL_DISP_MODE_ON, NULL, 0);
\r
1063 ili93xx_display_on();
\r
1068 * \brief Set display direction.
\r
1070 * \param e_dd 0: horizontal direction, 1: vertical direction
\r
1071 * \param e_shd: horizontal increase(0) or decrease(1)
\r
1072 * \param e_scd: vertical increase(1) or decrease(0)
\r
1074 void ili93xx_set_display_direction(enum ili93xx_display_direction e_dd,
\r
1075 enum ili93xx_shift_direction e_shd,
\r
1076 enum ili93xx_scan_direction e_scd)
\r
1078 if (g_uc_device_type == DEVICE_TYPE_ILI9325) {
\r
1079 if (e_dd == LANDSCAPE) {
\r
1080 ili93xx_write_register_word(ILI9325_ENTRY_MODE,
\r
1081 ILI9325_ENTRY_MODE_BGR | ILI9325_ENTRY_MODE_TRI |
\r
1082 ILI9325_ENTRY_MODE_DFM | ILI9325_ENTRY_MODE_ID(0x00)|
\r
1083 ILI9325_ENTRY_MODE_AM);
\r
1084 g_ul_lcd_x_length = ILI93XX_LCD_HEIGHT;
\r
1085 g_ul_lcd_y_length = ILI93XX_LCD_WIDTH;
\r
1087 ili93xx_write_register_word(ILI9325_ENTRY_MODE,
\r
1088 ILI9325_ENTRY_MODE_BGR | ILI9325_ENTRY_MODE_TRI |
\r
1089 ILI9325_ENTRY_MODE_DFM | ILI9325_ENTRY_MODE_ID(0x01));
\r
1090 g_ul_lcd_x_length = ILI93XX_LCD_WIDTH;
\r
1091 g_ul_lcd_y_length = ILI93XX_LCD_HEIGHT;
\r
1094 if (e_shd == H_INCREASE) {
\r
1095 ili93xx_write_register_word(ILI9325_DRIVER_OUTPUT_CTRL1, 0x0000);
\r
1097 ili93xx_write_register_word(ILI9325_DRIVER_OUTPUT_CTRL1,
\r
1098 ILI9325_DRIVER_OUTPUT_CTRL1_SS);
\r
1101 if (e_scd == V_INCREASE) {
\r
1102 ili93xx_write_register_word(ILI9325_DRIVER_OUTPUT_CTRL2,
\r
1103 ILI9325_DRIVER_OUTPUT_CTRL2_NL(0x27));
\r
1105 ili93xx_write_register_word(ILI9325_DRIVER_OUTPUT_CTRL2,
\r
1106 ILI9325_DRIVER_OUTPUT_CTRL2_GS |
\r
1107 ILI9325_DRIVER_OUTPUT_CTRL2_NL(0x27));
\r
1109 } else if (g_uc_device_type == DEVICE_TYPE_ILI9341) {
\r
1110 if (e_dd == LANDSCAPE) {
\r
1111 uint8_t paratable[1];
\r
1112 paratable[0] = ILI9341_CMD_MEMORY_ACCESS_CONTROL_MV |
\r
1113 ILI9341_CMD_MEMORY_ACCESS_CONTROL_BGR;
\r
1114 ili93xx_write_register(
\r
1115 ILI9341_CMD_MEMORY_ACCESS_CONTROL,
\r
1117 g_ul_lcd_x_length = ILI93XX_LCD_HEIGHT;
\r
1118 g_ul_lcd_y_length = ILI93XX_LCD_WIDTH;
\r
1120 uint8_t paratable[1];
\r
1121 paratable[0] = ILI9341_CMD_MEMORY_ACCESS_CONTROL_BGR |
\r
1122 ILI9341_CMD_MEMORY_ACCESS_CONTROL_MX;
\r
1123 ili93xx_write_register(
\r
1124 ILI9341_CMD_MEMORY_ACCESS_CONTROL,
\r
1126 g_ul_lcd_x_length = ILI93XX_LCD_WIDTH;
\r
1127 g_ul_lcd_y_length = ILI93XX_LCD_HEIGHT;
\r
1133 * \brief Draw a pixel on LCD.
\r
1135 * \param ul_x X coordinate of pixel.
\r
1136 * \param ul_y Y coordinate of pixel.
\r
1138 * \return 0 if succeeds, otherwise fails.
\r
1140 uint32_t ili93xx_draw_pixel(uint32_t ul_x, uint32_t ul_y)
\r
1142 if ((ul_x >= g_ul_lcd_x_length) || (ul_y >= g_ul_lcd_y_length)) {
\r
1146 if (g_uc_device_type == DEVICE_TYPE_ILI9325) {
\r
1148 ili93xx_set_cursor_position(ul_x, ul_y);
\r
1149 /** Prepare to write in GRAM */
\r
1150 ili93xx_write_ram_prepare();
\r
1151 ili93xx_write_ram(*g_ul_pixel_cache);
\r
1152 } else if (g_uc_device_type == DEVICE_TYPE_ILI9341) {
\r
1153 ili93xx_set_window(ul_x, ul_y, 0, 0);
\r
1154 /** Prepare to write in GRAM */
\r
1155 ili93xx_write_ram_prepare();
\r
1156 ili93xx_write_ram(*g_ul_pixel_cache);
\r
1163 * \brief Get a pixel from LCD.
\r
1165 * \param ul_x X coordinate of pixel.
\r
1166 * \param ul_y Y coordinate of pixel.
\r
1168 * \return the pixel color.
\r
1170 ili93xx_color_t ili93xx_get_pixel(uint32_t ul_x, uint32_t ul_y)
\r
1172 Assert(ul_x <= g_ul_lcd_x_length);
\r
1173 Assert(ul_y <= g_ul_lcd_y_length);
\r
1175 if (g_uc_device_type == DEVICE_TYPE_ILI9325) {
\r
1177 ili93xx_set_cursor_position(ul_x, ul_y);
\r
1178 /** Prepare to write in GRAM */
\r
1179 ili93xx_read_ram_prepare();
\r
1180 return ili93xx_read_ram();
\r
1181 } else if (g_uc_device_type == DEVICE_TYPE_ILI9341) {
\r
1182 ili93xx_set_window(ul_x, ul_y, 0, 0);
\r
1183 /** Prepare to write in GRAM */
\r
1184 ili93xx_read_ram_prepare();
\r
1185 return ili93xx_read_ram();
\r
1192 * \brief Draw a line on LCD, which is not horizontal or vertical.
\r
1194 * \param ul_x1 X coordinate of line start.
\r
1195 * \param ul_y1 Y coordinate of line start.
\r
1196 * \param ul_x2 X coordinate of line end.
\r
1197 * \param ul_y2 Y coordinate of line endl.
\r
1199 static void ili93xx_draw_line_bresenham(uint32_t ul_x1, uint32_t ul_y1,
\r
1200 uint32_t ul_x2, uint32_t ul_y2)
\r
1204 int xinc, yinc, cumul;
\r
1209 dx = ul_x2 - ul_x1;
\r
1210 dy = ul_y2 - ul_y1;
\r
1211 xinc = (dx > 0) ? 1 : -1;
\r
1212 yinc = (dy > 0) ? 1 : -1;
\r
1213 dx = abs(ul_x2 - ul_x1);
\r
1214 dy = abs(ul_y2 - ul_y1);
\r
1216 ili93xx_draw_pixel(x, y);
\r
1221 for (i = 1; i <= dx; i++) {
\r
1225 if (cumul >= dx) {
\r
1230 ili93xx_draw_pixel(x, y);
\r
1235 for (i = 1; i <= dy; i++) {
\r
1239 if (cumul >= dy) {
\r
1244 ili93xx_draw_pixel(x, y);
\r
1250 * \brief Draw a line on LCD.
\r
1252 * \param ul_x1 X coordinate of line start.
\r
1253 * \param ul_y1 Y coordinate of line start.
\r
1254 * \param ul_x2 X coordinate of line end.
\r
1255 * \param ul_y2 Y coordinate of line end.
\r
1257 void ili93xx_draw_line(uint32_t ul_x1, uint32_t ul_y1,
\r
1258 uint32_t ul_x2, uint32_t ul_y2)
\r
1260 if ((ul_y1 == ul_y2) || (ul_x1 == ul_x2)) {
\r
1261 ili93xx_draw_filled_rectangle(ul_x1, ul_y1, ul_x2, ul_y2);
\r
1263 ili93xx_draw_line_bresenham(ul_x1, ul_y1, ul_x2, ul_y2);
\r
1268 * \brief Draw a rectangle on LCD.
\r
1270 * \param ul_x1 X coordinate of upper-left corner on LCD.
\r
1271 * \param ul_y1 Y coordinate of upper-left corner on LCD.
\r
1272 * \param ul_x2 X coordinate of lower-right corner on LCD.
\r
1273 * \param ul_y2 Y coordinate of lower-right corner on LCD.
\r
1275 void ili93xx_draw_rectangle(uint32_t ul_x1, uint32_t ul_y1,
\r
1276 uint32_t ul_x2, uint32_t ul_y2)
\r
1278 ili93xx_check_box_coordinates(&ul_x1, &ul_y1, &ul_x2, &ul_y2);
\r
1280 ili93xx_draw_filled_rectangle(ul_x1, ul_y1, ul_x2, ul_y1);
\r
1281 ili93xx_draw_filled_rectangle(ul_x1, ul_y2, ul_x2, ul_y2);
\r
1283 ili93xx_draw_filled_rectangle(ul_x1, ul_y1, ul_x1, ul_y2);
\r
1284 ili93xx_draw_filled_rectangle(ul_x2, ul_y1, ul_x2, ul_y2);
\r
1288 * \brief Draw a filled rectangle on LCD.
\r
1290 * \param ul_x1 X coordinate of upper-left corner on LCD.
\r
1291 * \param ul_y1 Y coordinate of upper-left corner on LCD.
\r
1292 * \param ul_x2 X coordinate of lower-right corner on LCD.
\r
1293 * \param ul_y2 Y coordinate of lower-right corner on LCD.
\r
1295 void ili93xx_draw_filled_rectangle(uint32_t ul_x1, uint32_t ul_y1,
\r
1296 uint32_t ul_x2, uint32_t ul_y2)
\r
1298 uint32_t size, blocks;
\r
1300 /** Swap coordinates if necessary */
\r
1301 ili93xx_check_box_coordinates(&ul_x1, &ul_y1, &ul_x2, &ul_y2);
\r
1303 /** Determine the refresh window area */
\r
1304 ili93xx_set_window(ul_x1, ul_y1, (ul_x2 - ul_x1) + 1,
\r
1305 (ul_y2 - ul_y1) + 1);
\r
1308 ili93xx_set_cursor_position(ul_x1, ul_y1);
\r
1310 /** Prepare to write in Graphic RAM */
\r
1311 ili93xx_write_ram_prepare();
\r
1313 size = (ul_x2 - ul_x1 + 1) * (ul_y2 - ul_y1 + 1);
\r
1315 /** Send pixels blocks => one SPI IT / block */
\r
1316 blocks = size / LCD_DATA_CACHE_SIZE;
\r
1317 while (blocks--) {
\r
1318 ili93xx_write_ram_buffer(g_ul_pixel_cache,
\r
1319 LCD_DATA_CACHE_SIZE);
\r
1322 /** Send remaining pixels */
\r
1323 ili93xx_write_ram_buffer(g_ul_pixel_cache,
\r
1324 size % LCD_DATA_CACHE_SIZE);
\r
1326 /** Reset the refresh window area */
\r
1327 ili93xx_set_window(0, 0, g_ul_lcd_x_length, g_ul_lcd_y_length);
\r
1331 * \brief Draw a circle on LCD.
\r
1333 * \param ul_x X coordinate of circle center.
\r
1334 * \param ul_y Y coordinate of circle center.
\r
1335 * \param ul_r circle radius.
\r
1337 * \return 0 if succeeds, otherwise fails.
\r
1339 uint32_t ili93xx_draw_circle(uint32_t ul_x, uint32_t ul_y, uint32_t ul_r)
\r
1349 d = 3 - (ul_r << 1);
\r
1353 while (curX <= curY) {
\r
1354 ili93xx_draw_pixel(ul_x + curX, ul_y + curY);
\r
1355 ili93xx_draw_pixel(ul_x + curX, ul_y - curY);
\r
1356 ili93xx_draw_pixel(ul_x - curX, ul_y + curY);
\r
1357 ili93xx_draw_pixel(ul_x - curX, ul_y - curY);
\r
1358 ili93xx_draw_pixel(ul_x + curY, ul_y + curX);
\r
1359 ili93xx_draw_pixel(ul_x + curY, ul_y - curX);
\r
1360 ili93xx_draw_pixel(ul_x - curY, ul_y + curX);
\r
1361 ili93xx_draw_pixel(ul_x - curY, ul_y - curX);
\r
1364 d += (curX << 2) + 6;
\r
1366 d += ((curX - curY) << 2) + 10;
\r
1377 * \brief Draw a filled circle on LCD.
\r
1379 * \param ul_x X coordinate of circle center.
\r
1380 * \param ul_y Y coordinate of circle center.
\r
1381 * \param ul_r circle radius.
\r
1383 * \return 0 if succeeds, otherwise fails.
\r
1385 uint32_t ili93xx_draw_filled_circle(uint32_t ul_x, uint32_t ul_y, uint32_t ul_r)
\r
1387 signed int d; /* Decision Variable */
\r
1388 uint32_t dwCurX; /* Current X Value */
\r
1389 uint32_t dwCurY; /* Current Y Value */
\r
1390 uint32_t dwXmin, dwYmin;
\r
1396 d = 3 - (ul_r << 1);
\r
1400 while (dwCurX <= dwCurY) {
\r
1401 dwXmin = (dwCurX > ul_x) ? 0 : ul_x - dwCurX;
\r
1402 dwYmin = (dwCurY > ul_y) ? 0 : ul_y - dwCurY;
\r
1403 ili93xx_draw_filled_rectangle(dwXmin, dwYmin, ul_x + dwCurX,
\r
1405 ili93xx_draw_filled_rectangle(dwXmin, ul_y + dwCurY,
\r
1406 ul_x + dwCurX, ul_y + dwCurY);
\r
1407 dwXmin = (dwCurY > ul_x) ? 0 : ul_x - dwCurY;
\r
1408 dwYmin = (dwCurX > ul_y) ? 0 : ul_y - dwCurX;
\r
1409 ili93xx_draw_filled_rectangle(dwXmin, dwYmin, ul_x + dwCurY,
\r
1411 ili93xx_draw_filled_rectangle(dwXmin, ul_y + dwCurX,
\r
1412 ul_x + dwCurY, ul_y + dwCurX);
\r
1415 d += (dwCurX << 2) + 6;
\r
1417 d += ((dwCurX - dwCurY) << 2) + 10;
\r
1428 * \brief Draw an ASCII character on LCD.
\r
1430 * \param ul_x X coordinate of character upper-left corner.
\r
1431 * \param ul_y Y coordinate of character upper-left corner.
\r
1432 * \param uc_c character to print.
\r
1434 static void ili93xx_draw_char(uint32_t ul_x, uint32_t ul_y, uint8_t uc_c)
\r
1436 uint32_t row, col;
\r
1437 uint32_t offset, offset0, offset1;
\r
1440 * Compute offset according of the specified ASCII character
\r
1441 * Note: the first 32 characters of the ASCII table are not handled
\r
1443 offset = ((uint32_t)uc_c - 0x20) * 20;
\r
1445 for (col = 0; col < 10; col++) {
\r
1446 /** Compute the first and second byte offset of a column */
\r
1447 offset0 = offset + col * 2;
\r
1448 offset1 = offset0 + 1;
\r
1451 * Draw pixel on screen depending on the corresponding bit value
\r
1452 * from the charset
\r
1454 for (row = 0; row < 8; row++) {
\r
1455 if ((p_uc_charset10x14[offset0] >> (7 - row)) & 0x1) {
\r
1456 ili93xx_draw_pixel(ul_x + col, ul_y + row);
\r
1460 for (row = 0; row < 6; row++) {
\r
1461 if ((p_uc_charset10x14[offset1] >> (7 - row)) & 0x1) {
\r
1462 ili93xx_draw_pixel(ul_x + col, ul_y + row + 8);
\r
1469 * \brief Draw a string on LCD.
\r
1471 * \param ul_x X coordinate of string top-left corner.
\r
1472 * \param ul_y Y coordinate of string top-left corner.
\r
1473 * \param p_str String to display.
\r
1475 void ili93xx_draw_string(uint32_t ul_x, uint32_t ul_y, const uint8_t *p_str)
\r
1477 uint32_t xorg = ul_x;
\r
1479 while (*p_str != 0) {
\r
1480 /** If newline, jump to the next line (font height + 2) */
\r
1481 if (*p_str == '\n') {
\r
1482 ul_y += gfont.height + 2;
\r
1486 * Draw the character and place cursor right after (font
\r
1489 ili93xx_draw_char(ul_x, ul_y, *p_str);
\r
1490 ul_x += gfont.width + 2;
\r
1498 * \brief Draw a pixmap on LCD.
\r
1500 * \param ul_x X coordinate of upper-left corner on LCD.
\r
1501 * \param ul_y Y coordinate of upper-left corner on LCD.
\r
1502 * \param ul_width width of the picture.
\r
1503 * \param ul_height height of the picture.
\r
1504 * \param p_ul_pixmap pixmap of the image.
\r
1506 void ili93xx_draw_pixmap(uint32_t ul_x, uint32_t ul_y, uint32_t ul_width,
\r
1507 uint32_t ul_height, const ili93xx_color_t *p_ul_pixmap)
\r
1510 uint32_t dwX1, dwY1, dwX2, dwY2;
\r
1513 dwX2 = ul_x + ul_width;
\r
1514 dwY2 = ul_y + ul_height;
\r
1516 /** Swap coordinates if necessary */
\r
1517 ili93xx_check_box_coordinates(&dwX1, &dwY1, &dwX2, &dwY2);
\r
1519 /** Determine the refresh window area */
\r
1520 ili93xx_set_window(dwX1, dwY1, (dwX2 - dwX1 + 1), (dwY2 - dwY1 + 1));
\r
1522 if (g_uc_device_type == DEVICE_TYPE_ILI9325) {
\r
1524 ili93xx_set_cursor_position(dwX1, dwY1);
\r
1525 /** Prepare to write in GRAM */
\r
1526 ili93xx_write_ram_prepare();
\r
1528 size = (dwX2 - dwX1) * (dwY2 - dwY1);
\r
1530 ili93xx_write_ram_buffer(p_ul_pixmap, size);
\r
1532 /** Reset the refresh window area */
\r
1533 ili93xx_set_window(0, 0, g_ul_lcd_x_length, g_ul_lcd_y_length);
\r
1534 } else if (g_uc_device_type == DEVICE_TYPE_ILI9341) {
\r
1535 /** Prepare to write in GRAM */
\r
1536 ili93xx_write_ram_prepare();
\r
1538 size = (dwX2 - dwX1) * (dwY2 - dwY1);
\r
1540 ili93xx_write_ram_buffer(p_ul_pixmap, size);
\r
1542 /** Reset the refresh window area */
\r
1543 ili93xx_set_window(0, 0, g_ul_lcd_x_length, g_ul_lcd_y_length);
\r
1549 * \brief Helper function to send the drawing limits (boundaries) to the display
\r
1551 * This function is used to send the currently set upper-left and lower-right
\r
1552 * drawing limits to the display, as set through the various limit functions.
\r
1554 * \param send_end_limits True to also send the lower-right drawing limits
\r
1556 static inline void ili93xx_send_draw_limits(const bool send_end_limits)
\r
1558 if (g_uc_device_type == DEVICE_TYPE_ILI9325) {
\r
1559 /** Set Horizontal Address Start Position */
\r
1560 ili93xx_write_register_word(ILI9325_HORIZONTAL_ADDR_START,
\r
1561 (uint16_t)limit_start_x);
\r
1563 if (send_end_limits) {
\r
1564 /** Set Horizontal Address End Position */
\r
1565 ili93xx_write_register_word(ILI9325_HORIZONTAL_ADDR_END,
\r
1566 (uint16_t)(limit_end_x));
\r
1569 /** Set Vertical Address Start Position */
\r
1570 ili93xx_write_register_word(ILI9325_VERTICAL_ADDR_START,
\r
1571 (uint16_t)limit_start_y);
\r
1572 if (send_end_limits) {
\r
1573 /** Set Vertical Address End Position */
\r
1574 ili93xx_write_register_word(ILI9325_VERTICAL_ADDR_END,
\r
1575 (uint16_t)(limit_end_y));
\r
1578 /** GRAM Horizontal/Vertical Address Set (R20h, R21h) */
\r
1579 ili93xx_write_register_word(ILI9325_HORIZONTAL_GRAM_ADDR_SET,
\r
1581 ili93xx_write_register_word(ILI9325_VERTICAL_GRAM_ADDR_SET,
\r
1584 } else if (g_uc_device_type == DEVICE_TYPE_ILI9341) {
\r
1585 /** Set Horizontal Address Start Position */
\r
1586 ili93xx_write_register_word(ILI9341_CMD_COLUMN_ADDRESS_SET,
\r
1587 (uint16_t)limit_start_x);
\r
1589 if (send_end_limits) {
\r
1590 /** Set Horizontal Address End Position */
\r
1591 ili93xx_write_register_word(
\r
1592 ILI9341_CMD_COLUMN_ADDRESS_SET,
\r
1593 (uint16_t)(limit_end_x));
\r
1596 ili93xx_write_register(0, NULL, 0);
\r
1598 /** Set Vertical Address Start Position */
\r
1599 ili93xx_write_register_word(ILI9341_CMD_PAGE_ADDRESS_SET,
\r
1600 (uint16_t)limit_start_y);
\r
1601 if (send_end_limits) {
\r
1602 /** Set Vertical Address End Position */
\r
1603 ili93xx_write_register_word(
\r
1604 ILI9341_CMD_PAGE_ADDRESS_SET,
\r
1605 (uint16_t)(limit_end_y));
\r
1608 ili93xx_write_register(0, NULL, 0);
\r
1613 * \brief Set the display top left drawing limit
\r
1615 * Use this function to set the top left limit of the drawing limit box.
\r
1617 * \param x The x coordinate of the top left corner
\r
1618 * \param y The y coordinate of the top left corner
\r
1620 void ili93xx_set_top_left_limit(ili93xx_coord_t x, ili93xx_coord_t y)
\r
1622 limit_start_x = x;
\r
1623 limit_start_y = y;
\r
1625 ili93xx_send_draw_limits(false);
\r
1629 * \brief Set the display bottom right drawing limit
\r
1631 * Use this function to set the bottom right corner of the drawing limit box.
\r
1633 * \param x The x coordinate of the bottom right corner
\r
1634 * \param y The y coordinate of the bottom right corner
\r
1636 void ili93xx_set_bottom_right_limit(ili93xx_coord_t x, ili93xx_coord_t y)
\r
1641 ili93xx_send_draw_limits(true);
\r
1645 * \brief Set the full display drawing limits
\r
1647 * Use this function to set the full drawing limit box.
\r
1649 * \param start_x The x coordinate of the top left corner
\r
1650 * \param start_y The y coordinate of the top left corner
\r
1651 * \param end_x The x coordinate of the bottom right corner
\r
1652 * \param end_y The y coordinate of the bottom right corner
\r
1654 void ili93xx_set_limits(ili93xx_coord_t start_x, ili93xx_coord_t start_y,
\r
1655 ili93xx_coord_t end_x, ili93xx_coord_t end_y)
\r
1657 limit_start_x = start_x;
\r
1658 limit_start_y = start_y;
\r
1659 limit_end_x = end_x;
\r
1660 limit_end_y = end_y;
\r
1662 ili93xx_send_draw_limits(true);
\r
1666 * \brief Read a single color from the graphical memory
\r
1668 * Use this function to read a color from the graphical memory of the
\r
1671 * \retval ili93xx_color_t The read color pixel
\r
1673 ili93xx_color_t ili93xx_read_gram(void)
\r
1676 ili93xx_color_t color;
\r
1678 if (g_uc_device_type == DEVICE_TYPE_ILI9325) {
\r
1680 /** Write Data to GRAM (R22h) */
\r
1681 LCD_IR(ILI9325_GRAM_DATA_REG);
\r
1682 /** two dummy read */
\r
1683 value[0] = LCD_RD();
\r
1684 value[1] = LCD_RD();
\r
1685 /** data upper byte */
\r
1686 value[0] = LCD_RD();
\r
1687 /** data lower byte */
\r
1688 value[1] = LCD_RD();
\r
1690 /** Convert RGB565 to RGB888 */
\r
1691 /** For BGR format */
\r
1692 color = ((value[0] & 0xF8)) |
\r
1693 ((value[0] & 0x07) << 13) | ((value[1] & 0xE0) << 5) |
\r
1694 ((value[1] & 0x1F) << 19);
\r
1695 } else if (g_uc_device_type == DEVICE_TYPE_ILI9341) {
\r
1697 /** Write Data to GRAM (R2Eh) */
\r
1698 LCD_IR(ILI9341_CMD_MEMORY_READ);
\r
1700 value[0] = LCD_RD();
\r
1701 /** the highest byte - R byte*/
\r
1702 value[0] = LCD_RD();
\r
1703 /** the middle byte - G byte*/
\r
1704 value[1] = LCD_RD();
\r
1705 /** the lowest byte - B byte*/
\r
1706 value[2] = LCD_RD();
\r
1707 /** combine R, G, B byte to a color value */
\r
1708 color = (value[0] << 16) | (value[1] << 8) | value[2];
\r
1714 * \brief Write the graphical memory with a single color pixel
\r
1716 * Use this function to write a single color pixel to the controller memory.
\r
1718 * \param color The color pixel to write to the screen
\r
1720 void ili93xx_write_gram(ili93xx_color_t color)
\r
1722 if (g_uc_device_type == DEVICE_TYPE_ILI9325) {
\r
1724 /** Write Data to GRAM (R22h) */
\r
1725 LCD_IR(ILI9325_GRAM_DATA_REG);
\r
1726 } else if (g_uc_device_type == DEVICE_TYPE_ILI9341) {
\r
1727 /** memory write command (R2Ch)*/
\r
1728 LCD_IR(ILI9341_CMD_MEMORY_WRITE);
\r
1730 LCD_IR(ILI9341_CMD_WRITE_MEMORY_CONTINUE);
\r
1732 LCD_WD((color >> 16) & 0xFF);
\r
1733 LCD_WD((color >> 8) & 0xFF);
\r
1734 LCD_WD(color & 0xFF);
\r
1738 * \brief Copy pixels from SRAM to the screen
\r
1740 * Used to copy a large quantitative of data to the screen in one go.
\r
1742 * \param pixels Pointer to the pixel data
\r
1743 * \param count Number of pixels to copy to the screen
\r
1745 void ili93xx_copy_pixels_to_screen(const ili93xx_color_t *pixels,
\r
1748 /** Sanity check to make sure that the pixel count is not zero */
\r
1749 Assert(count > 0);
\r
1751 if (g_uc_device_type == DEVICE_TYPE_ILI9325) {
\r
1753 LCD_IR(ILI9325_GRAM_DATA_REG);
\r
1754 } else if (g_uc_device_type == DEVICE_TYPE_ILI9341) {
\r
1755 LCD_IR(ILI9341_CMD_MEMORY_WRITE);
\r
1757 LCD_IR(ILI9341_CMD_WRITE_MEMORY_CONTINUE);
\r
1761 LCD_WD((*pixels >> 16) & 0xFF);
\r
1762 LCD_WD((*pixels >> 8) & 0xFF);
\r
1763 LCD_WD(*pixels & 0xFF);
\r
1769 * \brief Copy pixels from SRAM to the screen
\r
1771 * Used to copy a large quantitative of data to the screen in one go.
\r
1773 * \param pixels Pointer to the pixel data
\r
1774 * \param count Number of pixels to copy to the screen
\r
1776 void ili93xx_copy_raw_pixel_24bits_to_screen(const uint8_t *raw_pixels,
\r
1779 ili93xx_color_t pixels;
\r
1781 /** Sanity check to make sure that the pixel count is not zero */
\r
1782 Assert(count > 0);
\r
1784 if (g_uc_device_type == DEVICE_TYPE_ILI9325) {
\r
1786 LCD_IR(ILI9325_GRAM_DATA_REG);
\r
1787 } else if (g_uc_device_type == DEVICE_TYPE_ILI9341) {
\r
1788 LCD_IR(ILI9341_CMD_MEMORY_WRITE);
\r
1790 LCD_IR(ILI9341_CMD_WRITE_MEMORY_CONTINUE);
\r
1793 pixels = (*raw_pixels) |
\r
1794 (*(raw_pixels +1)) << 8 |
\r
1795 (*(raw_pixels + 2)) << 16;
\r
1796 LCD_WD((pixels >> 16) & 0xFF);
\r
1797 LCD_WD((pixels >> 8) & 0xFF);
\r
1798 LCD_WD(pixels & 0xFF);
\r
1804 * \brief Set a given number of pixels to the same color
\r
1806 * Use this function to write a certain number of pixels to the same color
\r
1807 * within a set limit.
\r
1809 * \param color The color to write to the display
\r
1810 * \param count The number of pixels to write with this color
\r
1812 void ili93xx_duplicate_pixel(const ili93xx_color_t color, uint32_t count)
\r
1814 /** Sanity check to make sure that the pixel count is not zero */
\r
1815 Assert(count > 0);
\r
1817 if (g_uc_device_type == DEVICE_TYPE_ILI9325) {
\r
1818 /** Write Data to GRAM (R22h) */
\r
1820 LCD_IR(ILI9325_GRAM_DATA_REG);
\r
1821 } else if (g_uc_device_type == DEVICE_TYPE_ILI9341) {
\r
1822 LCD_IR(ILI9341_CMD_MEMORY_WRITE);
\r
1824 LCD_IR(ILI9341_CMD_WRITE_MEMORY_CONTINUE);
\r
1828 LCD_WD((color >> 16) & 0xFF);
\r
1829 LCD_WD((color >> 8) & 0xFF);
\r
1830 LCD_WD(color & 0xFF);
\r
1835 * \brief Copy pixels from the screen to a pixel buffer
\r
1837 * Use this function to copy pixels from the display to an internal SRAM buffer.
\r
1839 * \param pixels Pointer to the pixel buffer to read to
\r
1840 * \param count Number of pixels to read
\r
1842 void ili93xx_copy_pixels_from_screen(ili93xx_color_t *pixels, uint32_t count)
\r
1844 /** Remove warnings */
\r