1 /*
2  * Copyright (c) 2020 Hubert Miś
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/drivers/misc/ft8xx/ft8xx_copro.h>
8 
9 #include <stdint.h>
10 #include <string.h>
11 
12 #include <zephyr/drivers/misc/ft8xx/ft8xx_common.h>
13 #include <zephyr/drivers/misc/ft8xx/ft8xx_memory.h>
14 #include "ft8xx_drv.h"
15 
16 #define FT800_RAM_CMD_SIZE 4096UL
17 
18 enum {
19 	CMD_DLSTART   = 0xffffff00,
20 	CMD_SWAP      = 0xffffff01,
21 	CMD_TEXT      = 0xffffff0c,
22 	CMD_NUMBER    = 0xffffff2e,
23 	CMD_CALIBRATE = 0xffffff15,
24 } ft8xx_cmd;
25 
26 static uint16_t reg_cmd_read;
27 static uint16_t reg_cmd_write;
28 
ram_cmd_fullness(void)29 static uint16_t ram_cmd_fullness(void)
30 {
31 	return (reg_cmd_write - reg_cmd_read) % 4096UL;
32 }
33 
ram_cmd_freespace(void)34 static uint16_t ram_cmd_freespace(void)
35 {
36 	return (FT800_RAM_CMD_SIZE - 4UL) - ram_cmd_fullness();
37 }
38 
refresh_reg_cmd_read(void)39 static void refresh_reg_cmd_read(void)
40 {
41 	reg_cmd_read = ft8xx_rd32(FT800_REG_CMD_READ);
42 }
43 
flush_reg_cmd_write(void)44 static void flush_reg_cmd_write(void)
45 {
46 	ft8xx_wr32(FT800_REG_CMD_WRITE, reg_cmd_write);
47 }
48 
increase_reg_cmd_write(uint16_t value)49 static void increase_reg_cmd_write(uint16_t value)
50 {
51 	reg_cmd_write = (reg_cmd_write + value) % FT800_RAM_CMD_SIZE;
52 }
53 
ft8xx_copro_cmd(uint32_t cmd)54 void ft8xx_copro_cmd(uint32_t cmd)
55 {
56 	while (ram_cmd_freespace() < sizeof(cmd)) {
57 		refresh_reg_cmd_read();
58 	}
59 
60 	ft8xx_wr32(FT800_RAM_CMD + reg_cmd_write, cmd);
61 	increase_reg_cmd_write(sizeof(cmd));
62 
63 	flush_reg_cmd_write();
64 }
65 
ft8xx_copro_cmd_dlstart(void)66 void ft8xx_copro_cmd_dlstart(void)
67 {
68 	ft8xx_copro_cmd(CMD_DLSTART);
69 }
70 
ft8xx_copro_cmd_swap(void)71 void ft8xx_copro_cmd_swap(void)
72 {
73 	ft8xx_copro_cmd(CMD_SWAP);
74 }
75 
ft8xx_copro_cmd_text(int16_t x,int16_t y,int16_t font,uint16_t options,const char * s)76 void ft8xx_copro_cmd_text(int16_t x,
77 			   int16_t y,
78 			   int16_t font,
79 			   uint16_t options,
80 			   const char *s)
81 {
82 	const uint16_t str_bytes = strlen(s) + 1;
83 	const uint16_t padding_bytes = (4 - (str_bytes % 4)) % 4;
84 	const uint16_t cmd_size = sizeof(CMD_TEXT) +
85 				   sizeof(x) +
86 				   sizeof(y) +
87 				   sizeof(font) +
88 				   sizeof(options) +
89 				   str_bytes +
90 				   padding_bytes;
91 
92 	while (ram_cmd_freespace() < cmd_size) {
93 		refresh_reg_cmd_read();
94 	}
95 
96 	ft8xx_wr32(FT800_RAM_CMD + reg_cmd_write, CMD_TEXT);
97 	increase_reg_cmd_write(sizeof(CMD_TEXT));
98 
99 	ft8xx_wr16(FT800_RAM_CMD + reg_cmd_write, x);
100 	increase_reg_cmd_write(sizeof(x));
101 
102 	ft8xx_wr16(FT800_RAM_CMD + reg_cmd_write, y);
103 	increase_reg_cmd_write(sizeof(y));
104 
105 	ft8xx_wr16(FT800_RAM_CMD + reg_cmd_write, font);
106 	increase_reg_cmd_write(sizeof(font));
107 
108 	ft8xx_wr16(FT800_RAM_CMD + reg_cmd_write, options);
109 	increase_reg_cmd_write(sizeof(options));
110 
111 	(void)ft8xx_drv_write(FT800_RAM_CMD + reg_cmd_write, s, str_bytes);
112 	increase_reg_cmd_write(str_bytes + padding_bytes);
113 
114 	flush_reg_cmd_write();
115 }
116 
ft8xx_copro_cmd_number(int16_t x,int16_t y,int16_t font,uint16_t options,int32_t n)117 void ft8xx_copro_cmd_number(int16_t x,
118 			     int16_t y,
119 			     int16_t font,
120 			     uint16_t options,
121 			     int32_t n)
122 {
123 	const uint16_t cmd_size = sizeof(CMD_NUMBER) +
124 				   sizeof(x) +
125 				   sizeof(y) +
126 				   sizeof(font) +
127 				   sizeof(options) +
128 				   sizeof(n);
129 
130 	while (ram_cmd_freespace() < cmd_size) {
131 		refresh_reg_cmd_read();
132 	}
133 
134 	ft8xx_wr32(FT800_RAM_CMD + reg_cmd_write, CMD_NUMBER);
135 	increase_reg_cmd_write(sizeof(CMD_NUMBER));
136 
137 	ft8xx_wr16(FT800_RAM_CMD + reg_cmd_write, x);
138 	increase_reg_cmd_write(sizeof(x));
139 
140 	ft8xx_wr16(FT800_RAM_CMD + reg_cmd_write, y);
141 	increase_reg_cmd_write(sizeof(y));
142 
143 	ft8xx_wr16(FT800_RAM_CMD + reg_cmd_write, font);
144 	increase_reg_cmd_write(sizeof(font));
145 
146 	ft8xx_wr16(FT800_RAM_CMD + reg_cmd_write, options);
147 	increase_reg_cmd_write(sizeof(options));
148 
149 	ft8xx_wr32(FT800_RAM_CMD + reg_cmd_write, n);
150 	increase_reg_cmd_write(sizeof(n));
151 
152 	flush_reg_cmd_write();
153 }
154 
ft8xx_copro_cmd_calibrate(uint32_t * result)155 void ft8xx_copro_cmd_calibrate(uint32_t *result)
156 {
157 	const uint16_t cmd_size = sizeof(CMD_CALIBRATE) + sizeof(uint32_t);
158 	uint32_t result_address;
159 
160 	while (ram_cmd_freespace() < cmd_size) {
161 		refresh_reg_cmd_read();
162 	}
163 
164 	ft8xx_wr32(FT800_RAM_CMD + reg_cmd_write, CMD_CALIBRATE);
165 	increase_reg_cmd_write(sizeof(CMD_CALIBRATE));
166 
167 	result_address = FT800_RAM_CMD + reg_cmd_write;
168 	ft8xx_wr32(result_address, 1UL);
169 	increase_reg_cmd_write(sizeof(uint32_t));
170 
171 	flush_reg_cmd_write();
172 
173 	/* Wait until calibration is finished. */
174 	while (ram_cmd_fullness() > 0) {
175 		refresh_reg_cmd_read();
176 	}
177 
178 	*result = ft8xx_rd32(result_address);
179 }
180