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