1 /*
2 * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3 */
4
5 #include "ili9341.h"
6 #include "aos/vfs.h"
7 #include "vfsdev/gpio_dev.h"
8 #include "vfsdev/spi_dev.h"
9
10 #include <stdio.h>
11 #include <sys/ioctl.h>
12
13 #define SPI_MAX_BLOCK 60000
14
15 typedef enum {
16 CMD = 0,
17 DAT = 1,
18 } ili9341_dc_t;
19
gpio_output(int gpio_fd,int gpio_id,bool output)20 static int gpio_output(int gpio_fd, int gpio_id, bool output)
21 {
22 struct gpio_io_config config = {0};
23 config.id = gpio_id;
24 config.config = GPIO_IO_OUTPUT | GPIO_IO_OUTPUT_PP;
25 config.data = output > 0;
26 int ret = ioctl(gpio_fd, IOC_GPIO_SET, (unsigned long)&config);
27 return ret;
28 }
29
spi_write(int spi_fd,const void * data,uint32_t size)30 static inline void spi_write(int spi_fd, const void *data, uint32_t size)
31 {
32 if (size > SPI_MAX_BLOCK) {
33 uint32_t rest = size;
34 uint32_t start = 0;
35 while (rest > SPI_MAX_BLOCK) {
36 write(spi_fd, (const void *)(data + start), SPI_MAX_BLOCK);
37 start += SPI_MAX_BLOCK;
38 rest -= SPI_MAX_BLOCK;
39 }
40 write(spi_fd, (const void *)(data + start), rest);
41 } else {
42 write(spi_fd, (const void *)data, (uint16_t)size);
43 }
44 }
45
ili9341_dc_write_bytes(ili9341_dev_t ili9341_dev,ili9341_dc_t ili9341_dc,uint8_t * bytes,uint32_t size)46 static inline void ili9341_dc_write_bytes(ili9341_dev_t ili9341_dev,
47 ili9341_dc_t ili9341_dc,
48 uint8_t *bytes,
49 uint32_t size)
50 {
51 gpio_output(ili9341_dev.gpio_fd, ili9341_dev.gpio_dc_id, ili9341_dc);
52 spi_write(ili9341_dev.spi_fd, bytes, size);
53 }
54
ili9341_dc_write_byte(ili9341_dev_t ili9341_dev,ili9341_dc_t ili9341_dc,uint8_t byte)55 static inline void ili9341_dc_write_byte(ili9341_dev_t ili9341_dev,
56 ili9341_dc_t ili9341_dc,
57 uint8_t byte)
58 {
59 gpio_output(ili9341_dev.gpio_fd, ili9341_dev.gpio_dc_id, ili9341_dc);
60 spi_write(ili9341_dev.spi_fd, &byte, 1);
61 }
62
ili9341_hw_init(ili9341_dev_t * ili9341_dev)63 int ili9341_hw_init(ili9341_dev_t *ili9341_dev)
64 {
65 int ret = 0;
66
67 char spi_dev_name[20] = {0};
68 sprintf(spi_dev_name, "/dev/spi%d", ili9341_dev->spi_port);
69
70 ili9341_dev->spi_fd = open(spi_dev_name, 0);
71
72 if (ili9341_dev->spi_fd > 0) {
73 ret |= ioctl(ili9341_dev->spi_fd, IOC_SPI_SET_CFLAG,
74 SPI_MODE_3 | SPI_MSB | SPI_MASTER | SPI_DATA_8BIT);
75 ret |=
76 ioctl(ili9341_dev->spi_fd, IOC_SPI_SET_FREQ, ili9341_dev->spi_freq);
77 ret |= ioctl(ili9341_dev->spi_fd, IOC_SPI_SET_SERIAL_LEN, 8);
78 } else {
79 printf(
80 "ili9341 hardware_init fail, open /dev/spi%d fiail, spi_fd is %d\n",
81 ili9341_dev->spi_port, ili9341_dev->spi_fd);
82 return 1;
83 }
84
85 ili9341_dev->gpio_fd = open("/dev/gpio", 0);
86 if (ili9341_dev->gpio_fd > 0) {
87 ret |= gpio_output(ili9341_dev->gpio_fd, ili9341_dev->gpio_reset_id, 0);
88 usleep(50 * 1000);
89 ret |= gpio_output(ili9341_dev->gpio_fd, ili9341_dev->gpio_reset_id, 1);
90 } else {
91 printf(
92 "ili9341 hardware_init fail, open /dev/gpio fail, gpio_fd is %d\n",
93 ili9341_dev->gpio_fd);
94 return 1;
95 }
96
97 ili9341_init_command(*ili9341_dev);
98
99 printf("ili9341 hardware_init %s\n", ret == 0 ? "success" : "fail");
100
101 return ret;
102 }
103
ili9341_init_command(ili9341_dev_t ili9341_dev)104 static void ili9341_init_command(ili9341_dev_t ili9341_dev)
105 {
106 ili9341_dc_write_byte(ili9341_dev, CMD, ILI9341_SWRESET);
107 usleep(1000 * 120);
108 ili9341_dc_write_byte(ili9341_dev, CMD, ILI9341_DISPOFF);
109 usleep(1000 * 120);
110 ili9341_dc_write_byte(ili9341_dev, CMD, ILI9341_PWCTRB);
111 ili9341_dc_write_byte(ili9341_dev, DAT, 0x00);
112 ili9341_dc_write_byte(ili9341_dev, DAT, 0XC1);
113 ili9341_dc_write_byte(ili9341_dev, DAT, 0X30);
114
115 ili9341_dc_write_byte(ili9341_dev, CMD, ILI9341_TIMCTRA);
116 ili9341_dc_write_byte(ili9341_dev, DAT, 0x85);
117 ili9341_dc_write_byte(ili9341_dev, DAT, 0x00);
118 ili9341_dc_write_byte(ili9341_dev, DAT, 0x78);
119
120 ili9341_dc_write_byte(ili9341_dev, CMD, ILI9341_PWCTRSEQ);
121 ili9341_dc_write_byte(ili9341_dev, DAT, 0x39);
122 ili9341_dc_write_byte(ili9341_dev, DAT, 0x2C);
123 ili9341_dc_write_byte(ili9341_dev, DAT, 0x00);
124 ili9341_dc_write_byte(ili9341_dev, DAT, 0x34);
125 ili9341_dc_write_byte(ili9341_dev, DAT, 0x02);
126
127 ili9341_dc_write_byte(ili9341_dev, CMD, ILI9341_PUMP);
128 ili9341_dc_write_byte(ili9341_dev, DAT, 0x20);
129
130 ili9341_dc_write_byte(ili9341_dev, CMD, ILI9341_TIMCTRB);
131 ili9341_dc_write_byte(ili9341_dev, DAT, 0x00);
132 ili9341_dc_write_byte(ili9341_dev, DAT, 0x00);
133
134 ili9341_dc_write_byte(ili9341_dev, CMD, ILI9341_PWCTR1);
135 ili9341_dc_write_byte(ili9341_dev, DAT, 0x23);
136
137 ili9341_dc_write_byte(ili9341_dev, CMD, ILI9341_PWCTR2);
138 ili9341_dc_write_byte(ili9341_dev, DAT, 0x10);
139
140 ili9341_dc_write_byte(ili9341_dev, CMD, ILI9341_VMCTR1);
141 ili9341_dc_write_byte(ili9341_dev, DAT, 0x3e);
142 ili9341_dc_write_byte(ili9341_dev, DAT, 0x28);
143
144 ili9341_dc_write_byte(ili9341_dev, CMD, ILI9341_VMCTR2);
145 ili9341_dc_write_byte(ili9341_dev, DAT, 0x86);
146
147 ili9341_dc_write_byte(ili9341_dev, CMD, ILI9341_MADCTL);
148 ili9341_dc_write_byte(ili9341_dev, DAT, 0x48);
149
150 ili9341_dc_write_byte(ili9341_dev, CMD, ILI9341_PIXFMT);
151 ili9341_dc_write_byte(ili9341_dev, DAT, 0x55);
152
153 ili9341_dc_write_byte(ili9341_dev, CMD, ILI9341_FRMCTR1);
154 ili9341_dc_write_byte(ili9341_dev, DAT, 0x00);
155 ili9341_dc_write_byte(ili9341_dev, DAT, 0x18);
156
157 ili9341_dc_write_byte(ili9341_dev, CMD, ILI9341_DFUNCTR);
158 ili9341_dc_write_byte(ili9341_dev, DAT, 0x08);
159 ili9341_dc_write_byte(ili9341_dev, DAT, 0x82);
160 ili9341_dc_write_byte(ili9341_dev, DAT, 0x27);
161
162 ili9341_dc_write_byte(ili9341_dev, CMD, ILI9341_ENGMCTR);
163 ili9341_dc_write_byte(ili9341_dev, DAT, 0x00);
164
165 ili9341_dc_write_byte(ili9341_dev, CMD, ILI9341_GAMMASET);
166 ili9341_dc_write_byte(ili9341_dev, DAT, 0x01);
167
168 ili9341_dc_write_byte(ili9341_dev, CMD, ILI9341_GMCTRP1);
169 ili9341_dc_write_byte(ili9341_dev, DAT, 0x0F);
170 ili9341_dc_write_byte(ili9341_dev, DAT, 0x31);
171 ili9341_dc_write_byte(ili9341_dev, DAT, 0x2B);
172 ili9341_dc_write_byte(ili9341_dev, DAT, 0x0C);
173 ili9341_dc_write_byte(ili9341_dev, DAT, 0x0E);
174 ili9341_dc_write_byte(ili9341_dev, DAT, 0x08);
175 ili9341_dc_write_byte(ili9341_dev, DAT, 0x4E);
176 ili9341_dc_write_byte(ili9341_dev, DAT, 0xF1);
177 ili9341_dc_write_byte(ili9341_dev, DAT, 0x37);
178 ili9341_dc_write_byte(ili9341_dev, DAT, 0x07);
179 ili9341_dc_write_byte(ili9341_dev, DAT, 0x10);
180 ili9341_dc_write_byte(ili9341_dev, DAT, 0x03);
181 ili9341_dc_write_byte(ili9341_dev, DAT, 0x0E);
182 ili9341_dc_write_byte(ili9341_dev, DAT, 0x09);
183 ili9341_dc_write_byte(ili9341_dev, DAT, 0x00);
184
185 ili9341_dc_write_byte(ili9341_dev, CMD, ILI9341_GMCTRN1);
186 ili9341_dc_write_byte(ili9341_dev, DAT, 0x00);
187 ili9341_dc_write_byte(ili9341_dev, DAT, 0x0E);
188 ili9341_dc_write_byte(ili9341_dev, DAT, 0x14);
189 ili9341_dc_write_byte(ili9341_dev, DAT, 0x03);
190 ili9341_dc_write_byte(ili9341_dev, DAT, 0x11);
191 ili9341_dc_write_byte(ili9341_dev, DAT, 0x07);
192 ili9341_dc_write_byte(ili9341_dev, DAT, 0x31);
193 ili9341_dc_write_byte(ili9341_dev, DAT, 0xC1);
194 ili9341_dc_write_byte(ili9341_dev, DAT, 0x48);
195 ili9341_dc_write_byte(ili9341_dev, DAT, 0x08);
196 ili9341_dc_write_byte(ili9341_dev, DAT, 0x0F);
197 ili9341_dc_write_byte(ili9341_dev, DAT, 0x0C);
198 ili9341_dc_write_byte(ili9341_dev, DAT, 0x31);
199 ili9341_dc_write_byte(ili9341_dev, DAT, 0x36);
200 ili9341_dc_write_byte(ili9341_dev, DAT, 0x0F);
201
202 ili9341_dc_write_byte(ili9341_dev, CMD, ILI9341_SLPOUT);
203 usleep(1000 * 120);
204 ili9341_dc_write_byte(ili9341_dev, CMD, ILI9341_DISPON);
205 }
206
ili9341_hw_uninit(ili9341_dev_t * ili9341_dev)207 int ili9341_hw_uninit(ili9341_dev_t *ili9341_dev)
208 {
209 int ret = 0;
210 ret |= close(ili9341_dev->spi_fd);
211 ret |= close(ili9341_dev->gpio_fd);
212 return ret;
213 }
214
set_addr_window(ili9341_dev_t ili9341_dev,uint16_t x_0,uint16_t y_0,uint16_t x_1,uint16_t y_1)215 static void set_addr_window(ili9341_dev_t ili9341_dev,
216 uint16_t x_0,
217 uint16_t y_0,
218 uint16_t x_1,
219 uint16_t y_1)
220 {
221 uint8_t data[4] = {0};
222 if (x_0 < x_1) {
223 data[0] = x_0 >> 8;
224 data[1] = x_0;
225 data[2] = x_1 >> 8;
226 data[3] = x_1;
227 } else {
228 data[0] = x_1 >> 8;
229 data[1] = x_1;
230 data[2] = x_0 >> 8;
231 data[3] = x_0;
232 }
233 ili9341_dc_write_byte(ili9341_dev, CMD, ILI9341_CASET);
234 ili9341_dc_write_bytes(ili9341_dev, DAT, data, 4);
235 if (y_0 < y_1) {
236 data[0] = y_0 >> 8;
237 data[1] = y_0;
238 data[2] = y_1 >> 8;
239 data[3] = y_1;
240 } else {
241 data[0] = y_1 >> 8;
242 data[1] = y_1;
243 data[2] = y_0 >> 8;
244 data[3] = y_0;
245 }
246 ili9341_dc_write_byte(ili9341_dev, CMD, ILI9341_PASET);
247 ili9341_dc_write_bytes(ili9341_dev, DAT, data, 4);
248
249 ili9341_dc_write_byte(ili9341_dev, CMD, ILI9341_RAMWR);
250 }
251
ili9341_draw_pixel(ili9341_dev_t ili9341_dev,uint16_t x,uint16_t y,uint16_t color)252 void ili9341_draw_pixel(ili9341_dev_t ili9341_dev,
253 uint16_t x,
254 uint16_t y,
255 uint16_t color)
256 {
257 set_addr_window(ili9341_dev, x, y, x, y);
258 uint8_t data[2] = {color >> 8, color};
259 ili9341_dc_write_bytes(ili9341_dev, DAT, data, 2);
260 }
261
ili9341_draw_area(ili9341_dev_t ili9341_dev,uint16_t x,uint16_t y,uint16_t width,uint16_t height,uint8_t * frame)262 void ili9341_draw_area(ili9341_dev_t ili9341_dev,
263 uint16_t x,
264 uint16_t y,
265 uint16_t width,
266 uint16_t height,
267 uint8_t *frame)
268 {
269 uint16_t *rgb565_frame = (uint16_t *)frame;
270
271 set_addr_window(ili9341_dev, x, y, x + width - 1, y + height - 1);
272 uint32_t bufferSize = width * height * sizeof(uint16_t);
273 unsigned char *burst_buffer = (unsigned char *)malloc(bufferSize);
274 for (uint32_t i = 0; i < bufferSize; i++) {
275 burst_buffer[i] =
276 (bufferSize % 2) ? rgb565_frame[i] : rgb565_frame[i] >> 8;
277 }
278 ili9341_dc_write_bytes(ili9341_dev, DAT, burst_buffer, bufferSize);
279 free(burst_buffer);
280 }
281
ili9341_draw_rect(ili9341_dev_t ili9341_dev,uint16_t x,uint16_t y,uint16_t width,uint16_t height,uint32_t color)282 void ili9341_draw_rect(ili9341_dev_t ili9341_dev,
283 uint16_t x,
284 uint16_t y,
285 uint16_t width,
286 uint16_t height,
287 uint32_t color)
288 {
289 set_addr_window(ili9341_dev, x, y, x + width - 1, y + height - 1);
290 uint32_t bufferSize = width * height * sizeof(uint16_t);
291 unsigned char *burst_buffer = (unsigned char *)malloc(bufferSize);
292 for (uint32_t i = 0; i < bufferSize; i++) {
293 burst_buffer[i] = (bufferSize % 2) ? color : color >> 8;
294 }
295 ili9341_dc_write_bytes(ili9341_dev, DAT, burst_buffer, bufferSize);
296 free(burst_buffer);
297 }
298
ili9341_draw_frame(ili9341_dev_t ili9341_dev,uint8_t * frame)299 void ili9341_draw_frame(ili9341_dev_t ili9341_dev, uint8_t *frame)
300 {
301 uint16_t *rgb565_frame = (uint16_t *)frame;
302 uint32_t bufferSize = ILI9341_HEIGHT * ILI9341_WIDTH * sizeof(uint16_t);
303 unsigned char *burst_buffer = (unsigned char *)malloc(bufferSize);
304
305 set_addr_window(ili9341_dev, 0, 0, ILI9341_WIDTH - 1, ILI9341_HEIGHT - 1);
306
307 for (uint32_t i = 0; i < bufferSize / 2; i++) {
308 burst_buffer[2 * i] = rgb565_frame[i] >> 8;
309 burst_buffer[2 * i + 1] = rgb565_frame[i];
310 }
311
312 ili9341_dc_write_bytes(ili9341_dev, DAT, burst_buffer, bufferSize);
313 free(burst_buffer);
314 }
315
ili9341_set_rotation(ili9341_dev_t ili9341_dev,uint16_t rotation)316 void ili9341_set_rotation(ili9341_dev_t ili9341_dev, uint16_t rotation)
317 {
318 ili9341_dc_write_byte(ili9341_dev, CMD, ILI9341_MADCTL);
319 switch (rotation) {
320 case 0:
321 ili9341_dc_write_byte(ili9341_dev, DAT,
322 ILI9341_MADCTL_MX | ILI9341_MADCTL_BGR);
323 break;
324 case 90:
325 ili9341_dc_write_byte(ili9341_dev, DAT,
326 ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR);
327 break;
328 case 180:
329 ili9341_dc_write_byte(ili9341_dev, DAT,
330 ILI9341_MADCTL_MY | ILI9341_MADCTL_BGR);
331 break;
332 case 270:
333 ili9341_dc_write_byte(ili9341_dev, DAT,
334 ILI9341_MADCTL_MX | ILI9341_MADCTL_MY |
335 ILI9341_MADCTL_BGR);
336 break;
337 default:
338 break;
339 }
340 }
341
ili9341_set_invert(ili9341_dev_t ili9341_dev,uint8_t invert)342 void ili9341_set_invert(ili9341_dev_t ili9341_dev, uint8_t invert)
343 {
344 ili9341_dc_write_byte(ili9341_dev, CMD,
345 invert ? ILI9341_INVON : ILI9341_INVOFF);
346 }
347
ili9341_enter_sleep(ili9341_dev_t ili9341_dev)348 void ili9341_enter_sleep(ili9341_dev_t ili9341_dev)
349 {
350 ili9341_dc_write_byte(ili9341_dev, CMD, 0x28);
351 usleep(20 * 1000);
352 ili9341_dc_write_byte(ili9341_dev, CMD, 0x10);
353 }
354
ili9341_exit_sleep(ili9341_dev_t ili9341_dev)355 void ili9341_exit_sleep(ili9341_dev_t ili9341_dev)
356 {
357 ili9341_dc_write_byte(ili9341_dev, CMD, 0x11);
358 usleep(120 * 1000);
359 ili9341_dc_write_byte(ili9341_dev, CMD, 0x29);
360 }
361