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