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