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