1 /*
2  * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3  */
4 
5 #include "st7789.h"
6 #include "aos/vfs.h"
7 #include "vfsdev/gpio_dev.h"
8 #include "vfsdev/spi_dev.h"
9 
10 #include <drivers/char/u_device.h>
11 #include <drivers/u_ld.h>
12 #include <stdio.h>
13 #include <sys/ioctl.h>
14 
15 #define SPI_MAX_BLOCK 60000
16 
17 typedef enum {
18     CMD = 0,
19     DAT = 1,
20 } st7789_dc_t;
21 
gpio_output(int gpio_fd,int gpio_id,bool output)22 static int gpio_output(int gpio_fd, int gpio_id, bool output)
23 {
24     struct gpio_io_config config = {0};
25     config.id                    = gpio_id;
26     config.config                = GPIO_IO_OUTPUT | GPIO_IO_OUTPUT_PP;
27     config.data                  = output > 0;
28     int ret = ioctl(gpio_fd, IOC_GPIO_SET, (unsigned long)&config);
29     return ret;
30 }
31 
spi_write(int spi_fd,const void * data,uint32_t size)32 static inline void spi_write(int spi_fd, const void *data, uint32_t size)
33 {
34     if (size > SPI_MAX_BLOCK) {
35         uint32_t rest  = size;
36         uint32_t start = 0;
37         while (rest > SPI_MAX_BLOCK) {
38             write(spi_fd, (const void *)(data + start), SPI_MAX_BLOCK);
39             start += SPI_MAX_BLOCK;
40             rest -= SPI_MAX_BLOCK;
41         }
42         write(spi_fd, (const void *)(data + start), rest);
43     } else {
44         write(spi_fd, (const void *)data, (uint16_t)size);
45     }
46 }
47 
st7789_dc_write_bytes(st7789_dev_t st7789_dev,st7789_dc_t st7789_dc,uint8_t * bytes,uint32_t size)48 static inline void st7789_dc_write_bytes(st7789_dev_t st7789_dev,
49                                          st7789_dc_t  st7789_dc,
50                                          uint8_t *bytes,
51                                          uint32_t     size)
52 {
53     gpio_output(st7789_dev.gpio_fd, st7789_dev.gpio_dc_id, st7789_dc);
54     spi_write(st7789_dev.spi_fd, bytes, size);
55 }
56 
st7789_dc_write_byte(st7789_dev_t st7789_dev,st7789_dc_t st7789_dc,uint8_t byte)57 static inline void st7789_dc_write_byte(st7789_dev_t st7789_dev,
58                                         st7789_dc_t  st7789_dc,
59                                         uint8_t      byte)
60 {
61     gpio_output(st7789_dev.gpio_fd, st7789_dev.gpio_dc_id, st7789_dc);
62     spi_write(st7789_dev.spi_fd, &byte, 1);
63 }
64 
st7789_hw_init(st7789_dev_t * st7789_dev)65 int st7789_hw_init(st7789_dev_t *st7789_dev)
66 {
67     int ret = 0;
68 
69     char spi_dev_name[20] = {0};
70     sprintf(spi_dev_name, "/dev/spi%d", st7789_dev->spi_port);
71 
72     st7789_dev->spi_fd = open(spi_dev_name, 0);
73 
74     if (st7789_dev->spi_fd > 0) {
75         ret |= ioctl(st7789_dev->spi_fd, IOC_SPI_SET_CFLAG,
76                      SPI_MODE_3 | SPI_MSB | SPI_MASTER | SPI_DATA_8BIT);
77         ret |=
78             ioctl(st7789_dev->spi_fd, IOC_SPI_SET_FREQ, st7789_dev->spi_freq);
79         ret |= ioctl(st7789_dev->spi_fd, IOC_SPI_SET_SERIAL_LEN, 8);
80     } else {
81         printf(
82             "st7789 hardware_init fail, open /dev/spi%d fiail, spi_fd is %d\n",
83             st7789_dev->spi_port, st7789_dev->spi_fd);
84         return 1;
85     }
86 
87     st7789_dev->gpio_fd = open("/dev/gpio", 0);
88     if (st7789_dev->gpio_fd > 0) {
89         ret |= gpio_output(st7789_dev->gpio_fd, st7789_dev->gpio_reset_id, 0);
90         usleep(50 * 1000);
91         ret |= gpio_output(st7789_dev->gpio_fd, st7789_dev->gpio_reset_id, 1);
92     } else {
93         printf(
94             "st7789 hardware_init fail, open /dev/gpio fail, gpio_fd is %d\n",
95             st7789_dev->gpio_fd);
96         return 1;
97     }
98 
99     st7789_init_command(*st7789_dev);
100 
101     printf("st7789 hardware_init %s\n", ret == 0 ? "success" : "fail");
102 
103     return ret;
104 }
105 
st7789_init_command(st7789_dev_t st7789_dev)106 static void st7789_init_command(st7789_dev_t st7789_dev)
107 {
108     st7789_dc_write_byte(st7789_dev, CMD, ST7789_MADCTL);
109     st7789_dc_write_byte(st7789_dev, DAT, 0x00);
110 
111     st7789_dc_write_byte(st7789_dev, CMD, ST7789_COLMOD);
112     st7789_dc_write_byte(st7789_dev, DAT, 0x05);
113 
114     st7789_dc_write_byte(st7789_dev, CMD, 0xb2);
115     st7789_dc_write_byte(st7789_dev, DAT, 0x0c);
116     st7789_dc_write_byte(st7789_dev, DAT, 0x0c);
117     st7789_dc_write_byte(st7789_dev, DAT, 0x00);
118     st7789_dc_write_byte(st7789_dev, DAT, 0x33);
119     st7789_dc_write_byte(st7789_dev, DAT, 0x33);
120 
121     st7789_dc_write_byte(st7789_dev, CMD, 0xb7);
122     st7789_dc_write_byte(st7789_dev, DAT, 0x70);
123 
124     st7789_dc_write_byte(st7789_dev, CMD, 0xbb);
125     st7789_dc_write_byte(st7789_dev, DAT, 0x21);
126 
127     st7789_dc_write_byte(st7789_dev, CMD, 0xc0);
128     st7789_dc_write_byte(st7789_dev, DAT, 0x2c);
129 
130     st7789_dc_write_byte(st7789_dev, CMD, 0xc2);
131     st7789_dc_write_byte(st7789_dev, DAT, 0x01);
132 
133     st7789_dc_write_byte(st7789_dev, CMD, 0xc3);
134     st7789_dc_write_byte(st7789_dev, DAT, 0x0B);
135 
136     st7789_dc_write_byte(st7789_dev, CMD, 0xc4);
137     st7789_dc_write_byte(st7789_dev, DAT, 0x27);
138 
139     st7789_dc_write_byte(st7789_dev, CMD, 0xc6);
140     st7789_dc_write_byte(st7789_dev, DAT, 0x0f);
141 
142     st7789_dc_write_byte(st7789_dev, CMD, 0xd0);
143     st7789_dc_write_byte(st7789_dev, DAT, 0xa4);
144     st7789_dc_write_byte(st7789_dev, DAT, 0xa1);
145 
146     st7789_dc_write_byte(st7789_dev, CMD, 0xe0);
147     st7789_dc_write_byte(st7789_dev, DAT, 0xD0);
148     st7789_dc_write_byte(st7789_dev, DAT, 0x06);
149     st7789_dc_write_byte(st7789_dev, DAT, 0x0B);
150     st7789_dc_write_byte(st7789_dev, DAT, 0x09);
151     st7789_dc_write_byte(st7789_dev, DAT, 0x08);
152     st7789_dc_write_byte(st7789_dev, DAT, 0x30);
153     st7789_dc_write_byte(st7789_dev, DAT, 0x30);
154     st7789_dc_write_byte(st7789_dev, DAT, 0x5B);
155     st7789_dc_write_byte(st7789_dev, DAT, 0x4B);
156     st7789_dc_write_byte(st7789_dev, DAT, 0x18);
157     st7789_dc_write_byte(st7789_dev, DAT, 0x14);
158     st7789_dc_write_byte(st7789_dev, DAT, 0x14);
159     st7789_dc_write_byte(st7789_dev, DAT, 0x2C);
160     st7789_dc_write_byte(st7789_dev, DAT, 0x32);
161 
162     st7789_dc_write_byte(st7789_dev, CMD, 0xe1);
163     st7789_dc_write_byte(st7789_dev, DAT, 0xD0);
164     st7789_dc_write_byte(st7789_dev, DAT, 0x05);
165     st7789_dc_write_byte(st7789_dev, DAT, 0x0A);
166     st7789_dc_write_byte(st7789_dev, DAT, 0x0A);
167     st7789_dc_write_byte(st7789_dev, DAT, 0x07);
168     st7789_dc_write_byte(st7789_dev, DAT, 0x28);
169     st7789_dc_write_byte(st7789_dev, DAT, 0x32);
170     st7789_dc_write_byte(st7789_dev, DAT, 0x2C);
171     st7789_dc_write_byte(st7789_dev, DAT, 0x49);
172     st7789_dc_write_byte(st7789_dev, DAT, 0x18);
173     st7789_dc_write_byte(st7789_dev, DAT, 0x13);
174     st7789_dc_write_byte(st7789_dev, DAT, 0x13);
175     st7789_dc_write_byte(st7789_dev, DAT, 0x2C);
176     st7789_dc_write_byte(st7789_dev, DAT, 0x33);
177 
178     st7789_dc_write_byte(st7789_dev, CMD, ST7789_INVON);
179 
180     st7789_dc_write_byte(st7789_dev, CMD, ST7789_CASET);
181     st7789_dc_write_byte(st7789_dev, DAT, 0x00);
182     st7789_dc_write_byte(st7789_dev, DAT, 0x00);
183     st7789_dc_write_byte(st7789_dev, DAT, 0x00);
184     st7789_dc_write_byte(st7789_dev, DAT, 0xEF);
185 
186     st7789_dc_write_byte(st7789_dev, CMD, ST7789_RASET);
187     st7789_dc_write_byte(st7789_dev, DAT, 0x00);
188     st7789_dc_write_byte(st7789_dev, DAT, 0x00);
189     st7789_dc_write_byte(st7789_dev, DAT, 0x01);
190     st7789_dc_write_byte(st7789_dev, DAT, 0x3F);
191 
192     st7789_dc_write_byte(st7789_dev, CMD, ST7789_SLPOUT);
193     usleep(120 * 1000);
194 
195     st7789_dc_write_byte(st7789_dev, CMD, ST7789_DISPON);
196     st7789_dc_write_byte(st7789_dev, CMD, ST7789_RAMWR);
197 }
198 
st7789_hw_uninit(st7789_dev_t * st7789_dev)199 int st7789_hw_uninit(st7789_dev_t *st7789_dev)
200 {
201     int ret = 0;
202     ret |= close(st7789_dev->spi_fd);
203     ret |= close(st7789_dev->gpio_fd);
204     return ret;
205 }
206 
set_addr_window(st7789_dev_t st7789_dev,uint16_t x_0,uint16_t y_0,uint16_t x_1,uint16_t y_1)207 static void set_addr_window(st7789_dev_t st7789_dev,
208                             uint16_t     x_0,
209                             uint16_t     y_0,
210                             uint16_t     x_1,
211                             uint16_t     y_1)
212 {
213     uint8_t data[4] = {0};
214     if (x_0 < x_1) {
215         data[0] = x_0 >> 8;
216         data[1] = x_0;
217         data[2] = x_1 >> 8;
218         data[3] = x_1;
219     } else {
220         data[0] = x_1 >> 8;
221         data[1] = x_1;
222         data[2] = x_0 >> 8;
223         data[3] = x_0;
224     }
225     st7789_dc_write_byte(st7789_dev, CMD, ST7789_CASET);
226     st7789_dc_write_bytes(st7789_dev, DAT, data, 4);
227     if (y_0 < y_1) {
228         data[0] = y_0 >> 8;
229         data[1] = y_0;
230         data[2] = y_1 >> 8;
231         data[3] = y_1;
232     } else {
233         data[0] = y_1 >> 8;
234         data[1] = y_1;
235         data[2] = y_0 >> 8;
236         data[3] = y_0;
237     }
238     st7789_dc_write_byte(st7789_dev, CMD, ST7789_RASET);
239     st7789_dc_write_bytes(st7789_dev, DAT, data, 4);
240 
241     st7789_dc_write_byte(st7789_dev, CMD, ST7789_RAMWR);
242 }
243 
st7789_draw_pixel(st7789_dev_t st7789_dev,uint16_t x,uint16_t y,uint16_t color)244 void st7789_draw_pixel(st7789_dev_t st7789_dev,
245                        uint16_t     x,
246                        uint16_t     y,
247                        uint16_t     color)
248 {
249     set_addr_window(st7789_dev, x, y, x, y);
250     uint8_t data[2] = {color >> 8, color};
251     st7789_dc_write_bytes(st7789_dev, DAT, data, 2);
252 }
253 
st7789_draw_area(st7789_dev_t st7789_dev,uint16_t x,uint16_t y,uint16_t width,uint16_t height,uint8_t * frame)254 void st7789_draw_area(st7789_dev_t st7789_dev,
255                       uint16_t     x,
256                       uint16_t     y,
257                       uint16_t     width,
258                       uint16_t     height,
259                       uint8_t *frame)
260 {
261     uint16_t *rgb565_frame = (uint16_t *)frame;
262 
263     set_addr_window(st7789_dev, x, y, x + width - 1, y + height - 1);
264     uint32_t       bufferSize   = width * height * sizeof(uint16_t);
265     unsigned char *burst_buffer = (unsigned char *)malloc(bufferSize);
266     for (uint32_t i = 0; i < bufferSize; i++) {
267         burst_buffer[i] =
268             (bufferSize % 2) ? rgb565_frame[i] : rgb565_frame[i] >> 8;
269     }
270     st7789_dc_write_bytes(st7789_dev, DAT, burst_buffer, bufferSize);
271     free(burst_buffer);
272 }
273 
st7789_draw_rect(st7789_dev_t st7789_dev,uint16_t x,uint16_t y,uint16_t width,uint16_t height,uint16_t color)274 void st7789_draw_rect(st7789_dev_t st7789_dev,
275                       uint16_t     x,
276                       uint16_t     y,
277                       uint16_t     width,
278                       uint16_t     height,
279                       uint16_t     color)
280 {
281     set_addr_window(st7789_dev, x, y, x + width - 1, y + height - 1);
282     uint32_t       bufferSize   = width * height * sizeof(uint16_t);
283     unsigned char *burst_buffer = (unsigned char *)malloc(bufferSize);
284     for (uint32_t i = 0; i < bufferSize; i++) {
285         burst_buffer[i] = (bufferSize % 2) ? color : color >> 8;
286     }
287     st7789_dc_write_bytes(st7789_dev, DAT, burst_buffer, bufferSize);
288     free(burst_buffer);
289 }
290 
st7789_draw_frame(st7789_dev_t st7789_dev,uint8_t * frame)291 void st7789_draw_frame(st7789_dev_t st7789_dev, uint8_t *frame)
292 {
293     uint16_t *rgb565_frame = (uint16_t *)frame;
294     uint32_t  bufferSize   = ST7789_HEIGHT * ST7789_WIDTH * sizeof(uint16_t);
295     set_addr_window(st7789_dev, 0, 0, ST7789_WIDTH - 1, ST7789_HEIGHT - 1);
296     unsigned char *burst_buffer = (unsigned char *)malloc(bufferSize);
297     for (uint32_t i = 0; i < bufferSize; i++) {
298         burst_buffer[i] =
299             (bufferSize % 2) ? rgb565_frame[i] : rgb565_frame[i] >> 8;
300     }
301     st7789_dc_write_bytes(st7789_dev, DAT, burst_buffer, bufferSize);
302     free(burst_buffer);
303 }
304 
st7789_set_rotation(st7789_dev_t st7789_dev,uint16_t rotation)305 void st7789_set_rotation(st7789_dev_t st7789_dev, uint16_t rotation)
306 {
307     st7789_dc_write_byte(st7789_dev, CMD, ST7789_MADCTL);
308     switch (rotation) {
309         case 0:
310             st7789_dc_write_byte(st7789_dev, DAT,
311                                  ST7789_MADCTL_MX | ST7789_MADCTL_RGB);
312             break;
313         case 90:
314             st7789_dc_write_byte(st7789_dev, DAT,
315                                  ST7789_MADCTL_MV | ST7789_MADCTL_MX |
316                                      ST7789_MADCTL_RGB);
317             break;
318         case 180:
319             st7789_dc_write_byte(st7789_dev, DAT,
320                                  ST7789_MADCTL_MY | ST7789_MADCTL_RGB);
321             break;
322         case 270:
323             st7789_dc_write_byte(st7789_dev, DAT,
324                                  ST7789_MADCTL_MX | ST7789_MADCTL_MY |
325                                      ST7789_MADCTL_MV | ST7789_MADCTL_RGB);
326             break;
327         default:
328             break;
329     }
330 }
331 
st7789_set_invert(st7789_dev_t st7789_dev,uint8_t invert)332 void st7789_set_invert(st7789_dev_t st7789_dev, uint8_t invert)
333 {
334     st7789_dc_write_byte(st7789_dev, CMD,
335                          invert ? ST7789_INVON : ST7789_INVOFF);
336 }
337 
st7789_enter_sleep(st7789_dev_t st7789_dev)338 void st7789_enter_sleep(st7789_dev_t st7789_dev)
339 {
340     st7789_dc_write_byte(st7789_dev, CMD, 0x28);
341     usleep(20 * 1000);
342     st7789_dc_write_byte(st7789_dev, CMD, 0x10);
343 }
344 
st7789_exit_sleep(st7789_dev_t st7789_dev)345 void st7789_exit_sleep(st7789_dev_t st7789_dev)
346 {
347     st7789_dc_write_byte(st7789_dev, CMD, 0x11);
348     usleep(120 * 1000);
349     st7789_dc_write_byte(st7789_dev, CMD, 0x29);
350 }
351