acc_reg_protocol.c
Go to the documentation of this file.
1 // Copyright (c) Acconeer AB, 2023
2 // All rights reserved
3 // This file is subject to the terms and conditions defined in the file
4 // 'LICENSES/license_acconeer.txt', (BSD 3-Clause License) which is part
5 // of this source code package.
6
7 #include <inttypes.h>
8 #include <stdbool.h>
9 #include <stddef.h>
10 #include <stdint.h>
11
12 #include "acc_reg_protocol.h"
13
14 /**
15 * @brief Register access mode
16 */
17 typedef enum
18 {
19 REG_MODE_READ_WRITE,
20 REG_MODE_READ,
21 REG_MODE_WRITE,
22 REG_MODE_ERROR,
23 } acc_reg_mode_t;
24
25
26 /**
27 * @brief Register protocol state
28 */
29 typedef enum
30 {
31 REG_STATE_WAIT_FOR_ADDRESS,
32 REG_STATE_WAIT_FOR_READ_OR_WRITE,
33 REG_STATE_WAIT_FOR_WRITE,
34 REG_STATE_WAIT_FOR_READ,
35 REG_STATE_NACK_NEXT_WRITE,
36 } acc_reg_protocol_state_t;
37
38 #define REG_INVALID_ADDRESS 0xffffU
39 #define REG_ERROR_READ_ADDRESS 0xeeeeee00U
40 #define REG_ERROR_READ_OF_WO_REG 0xeeeeee01U
41
42 static const acc_reg_protocol_t *reg_protocol_struct = NULL;
43 static uint16_t reg_register_count = 0;
44 static acc_reg_protocol_state_t reg_state = REG_STATE_WAIT_FOR_ADDRESS;
45 static uint16_t reg_address = REG_INVALID_ADDRESS;
46 static uint32_t reg_error_flags = 0;
47
48
49 /**
50 * @brief Get register struct from protocol struct
51 *
52 * @param[in] register_address The address of the register
53 * @return A pointer to the register struct, NULL if the address is invalid
54 */
55 static const acc_reg_protocol_t *get_register_struct(uint16_t register_address)
56 {
57 const acc_reg_protocol_t *reg = NULL;
58
59 if (reg_protocol_struct != NULL)
60 {
61 for (uint16_t idx = 0; idx < reg_register_count; idx++)
62 {
63 if (register_address == reg_protocol_struct[idx].address)
64 {
65 reg = &reg_protocol_struct[idx];
66 break;
67 }
68 }
69 }
70
71 return reg;
72 }
73
74
75 /**
76 * @brief Set current register address
77 *
78 * @param[in] buffer The input data buffer
79 */
80 static void set_address(uint8_t *buffer)
81 {
82 uint16_t register_address = (buffer[0] << 8) | buffer[1];
83
84 const acc_reg_protocol_t *reg = get_register_struct(register_address);
85
86 if (reg != NULL)
87 {
88 reg_address = register_address;
89 }
90 else
91 {
92 reg_error_flags |= ACC_REG_ERROR_FLAG_ADDRESS_ERROR;
93 reg_address = REG_INVALID_ADDRESS;
94 }
95 }
96
97
98 /**
99 * @brief Return true if register is writable
100 */
101 static bool register_is_writable(void)
102 {
103 const acc_reg_protocol_t *reg = get_register_struct(reg_address);
104
105 return (reg != NULL) && (reg->write != NULL);
106 }
107
108
109 /**
110 * @brief Read register at current register address and increase address
111 *
112 * @param[out] buffer The output data buffer
113 */
114 static void read_register(uint8_t *buffer)
115 {
116 uint32_t data = 0;
117
118 const acc_reg_protocol_t *reg = get_register_struct(reg_address);
119
120 if (reg != NULL)
121 {
122 if (reg->read != NULL)
123 {
124 reg->read(&data);
125 }
126 else
127 {
128 /* Register read error, read a write only register */
129 data = REG_ERROR_READ_OF_WO_REG;
130 }
131 }
132 else
133 {
134 /* Register read outside of address space */
135 data = REG_ERROR_READ_ADDRESS;
136 }
137
138 buffer[0] = (data >> 24) & 0xff;
139 buffer[1] = (data >> 16) & 0xff;
140 buffer[2] = (data >> 8) & 0xff;
141 buffer[3] = (data >> 0) & 0xff;
142
143 /* Increase reg addess */
144 if (reg_address < REG_INVALID_ADDRESS)
145 {
146 reg_address++;
147 }
148 }
149
150
151 /**
152 * @brief Write register at current register address and increase address
153 *
154 * @param[in] buffer The input data buffer
155 */
156 static bool write_register(uint8_t *buffer)
157 {
158 bool status = true;
159
160 uint32_t data =
161 (((uint32_t)buffer[0]) << 24) |
162 (((uint32_t)buffer[1]) << 16) |
163 (((uint32_t)buffer[2]) << 8) |
164 (((uint32_t)buffer[3]) << 0);
165
166 const acc_reg_protocol_t *reg = get_register_struct(reg_address);
167
168 if (reg != NULL)
169 {
170 if (reg->write != NULL)
171 {
172 if (!reg->write(data))
173 {
174 reg_error_flags |= ACC_REG_ERROR_FLAG_WRITE_FAILED;
175 status = false;
176 }
177 }
178 else
179 {
180 /* Register write error, write to read only register */
181 reg_error_flags |= ACC_REG_ERROR_FLAG_WRITE_TO_READ_ONLY;
182 status = false;
183 }
184 }
185 else
186 {
187 /* Register read outside of address space */
188 reg_error_flags |= ACC_REG_ERROR_FLAG_ADDRESS_ERROR;
189 status = false;
190 }
191
192 /* Increase reg addess */
193 if (reg_address < REG_INVALID_ADDRESS)
194 {
195 reg_address++;
196 }
197
198 return status;
199 }
200
201
202 void acc_reg_protocol_setup(const acc_reg_protocol_t *protocol_struct, uint16_t register_count)
203 {
204 reg_protocol_struct = protocol_struct;
205 reg_register_count = register_count;
206
207 acc_reg_protocol_reset();
208 }
209
210
211 void acc_reg_protocol_reset(void)
212 {
213 reg_state = REG_STATE_WAIT_FOR_ADDRESS;
214 reg_address = REG_INVALID_ADDRESS;
215 }
216
217
218 bool acc_reg_protocol_data_nack(void)
219 {
220 if ((reg_state == REG_STATE_NACK_NEXT_WRITE) ||
221 (reg_state == REG_STATE_WAIT_FOR_READ))
222 {
223 return true;
224 }
225
226 return false;
227 }
228
229
230 void acc_reg_protocol_data_in(uint8_t *buffer, size_t data_in_length)
231 {
232 if (data_in_length == ACC_REG_PROTOCOL_ADDRESS_LENGTH)
233 {
234 if (reg_state == REG_STATE_WAIT_FOR_ADDRESS)
235 {
236 set_address(buffer);
237
238 if (register_is_writable())
239 {
240 /* Register can be read or written */
241 reg_state = REG_STATE_WAIT_FOR_READ_OR_WRITE;
242 }
243 else
244 {
245 /**
246 * - Read only register
247 * - No valid address, read is still possoble
248 */
249 reg_state = REG_STATE_WAIT_FOR_READ;
250 }
251 }
252 else
253 {
254 /* FAIL: Incorrect state */
255 reg_error_flags |= ACC_REG_ERROR_FLAG_PROTOCOL_STATE_ERROR;
256 reg_state = REG_STATE_NACK_NEXT_WRITE;
257 }
258 }
259 else if (data_in_length == ACC_REG_PROTOCOL_REGDATA_LENGTH)
260 {
261 if ((reg_state == REG_STATE_WAIT_FOR_READ_OR_WRITE) ||
262 (reg_state == REG_STATE_WAIT_FOR_WRITE))
263 {
264 if (write_register(buffer) && register_is_writable())
265 {
266 /* OK: Another write is possible */
267 reg_state = REG_STATE_WAIT_FOR_WRITE;
268 }
269 else
270 {
271 /**
272 * - Write register failed
273 * - Next register is read only
274 */
275 reg_state = REG_STATE_NACK_NEXT_WRITE;
276 }
277 }
278 else
279 {
280 /* FAIL: Incorrect state */
281 reg_error_flags |= ACC_REG_ERROR_FLAG_PROTOCOL_STATE_ERROR;
282 reg_state = REG_STATE_NACK_NEXT_WRITE;
283 }
284 }
285 else
286 {
287 /* FAIL: Incorrect packet length */
288 reg_error_flags |= ACC_REG_ERROR_FLAG_PACKET_LENGTH_ERROR;
289 reg_state = REG_STATE_NACK_NEXT_WRITE;
290 }
291 }
292
293
294 void acc_reg_protocol_data_out(uint8_t *buffer, size_t data_out_length)
295 {
296 if ((reg_state == REG_STATE_WAIT_FOR_READ_OR_WRITE) ||
297 (reg_state == REG_STATE_WAIT_FOR_READ))
298 {
299 reg_state = REG_STATE_WAIT_FOR_READ;
300
301 if (data_out_length == ACC_REG_PROTOCOL_REGDATA_LENGTH)
302 {
303 read_register(buffer);
304 }
305 else
306 {
307 /* FAIL: Incorrect data length for register data */
308 reg_error_flags |= ACC_REG_ERROR_FLAG_PACKET_LENGTH_ERROR;
309 }
310 }
311 else
312 {
313 /* FAIL: Incorrect state */
314 reg_error_flags |= ACC_REG_ERROR_FLAG_PROTOCOL_STATE_ERROR;
315 }
316 }
317
318
319 uint32_t acc_reg_protocol_get_error_flags(void)
320 {
321 uint32_t error_flags = reg_error_flags;
322
323 /* Clear flags */
324 reg_error_flags = 0;
325
326 return error_flags;
327 }
328
329
330 int32_t acc_reg_protocol_float_to_int32_milli(float value)
331 {
332 return (int32_t)(value*1000.0f);
333 }
334
335
336 uint32_t acc_reg_protocol_float_to_uint32_milli(float value)
337 {
338 return (uint32_t)(value*1000.0f);
339 }
340
341
342 float acc_reg_protocol_int32_milli_to_float(int32_t value)
343 {
344 float val = (float)value;
345
346 val = val / 1000.0f;
347 return val;
348 }
349
350
351 float acc_reg_protocol_uint32_milli_to_float(uint32_t value)
352 {
353 float val = (float)value;
354
355 val = val / 1000.0f;
356 return val;
357 }
acc_reg_protocol_data_out
void acc_reg_protocol_data_out(uint8_t *buffer, size_t data_out_length)
Handle data input from the register protocol.
Definition: acc_reg_protocol.c:294
acc_reg_protocol_int32_milli_to_float
float acc_reg_protocol_int32_milli_to_float(int32_t value)
Convert int32 / 1000 to float.
Definition: acc_reg_protocol.c:342
ACC_REG_PROTOCOL_ADDRESS_LENGTH
#define ACC_REG_PROTOCOL_ADDRESS_LENGTH
Definition: acc_reg_protocol.h:11
ACC_REG_ERROR_FLAG_PACKET_LENGTH_ERROR
#define ACC_REG_ERROR_FLAG_PACKET_LENGTH_ERROR
Definition: acc_reg_protocol.h:15
acc_reg_protocol_t::write
acc_reg_write_func_t * write
Definition: acc_reg_protocol.h:42
read_register
static void read_register(uint8_t *buffer)
Read register at current register address and increase address.
Definition: acc_reg_protocol.c:114
write_register
static bool write_register(uint8_t *buffer)
Write register at current register address and increase address.
Definition: acc_reg_protocol.c:156
reg_address
static uint16_t reg_address
Definition: acc_reg_protocol.c:45
ACC_REG_ERROR_FLAG_ADDRESS_ERROR
#define ACC_REG_ERROR_FLAG_ADDRESS_ERROR
Definition: acc_reg_protocol.h:16
acc_reg_protocol_reset
void acc_reg_protocol_reset(void)
Reset register protocol.
Definition: acc_reg_protocol.c:211
acc_reg_protocol_data_in
void acc_reg_protocol_data_in(uint8_t *buffer, size_t data_in_length)
Handle data input to the register protocol.
Definition: acc_reg_protocol.c:230
REG_STATE_WAIT_FOR_READ
@ REG_STATE_WAIT_FOR_READ
Definition: acc_reg_protocol.c:34
set_address
static void set_address(uint8_t *buffer)
Set current register address.
Definition: acc_reg_protocol.c:80
REG_ERROR_READ_OF_WO_REG
#define REG_ERROR_READ_OF_WO_REG
Definition: acc_reg_protocol.c:40
ACC_REG_PROTOCOL_REGDATA_LENGTH
#define ACC_REG_PROTOCOL_REGDATA_LENGTH
Definition: acc_reg_protocol.h:12
acc_reg_protocol_float_to_int32_milli
int32_t acc_reg_protocol_float_to_int32_milli(float value)
Convert 1000 * float to int32.
Definition: acc_reg_protocol.c:330
REG_STATE_WAIT_FOR_ADDRESS
@ REG_STATE_WAIT_FOR_ADDRESS
Definition: acc_reg_protocol.c:31
reg_register_count
static uint16_t reg_register_count
Definition: acc_reg_protocol.c:43
acc_reg_protocol_uint32_milli_to_float
float acc_reg_protocol_uint32_milli_to_float(uint32_t value)
Convert uint32 / 1000 to float.
Definition: acc_reg_protocol.c:351
REG_MODE_READ
@ REG_MODE_READ
Definition: acc_reg_protocol.c:20
acc_reg_protocol_state_t
acc_reg_protocol_state_t
Register protocol state.
Definition: acc_reg_protocol.c:29
ACC_REG_ERROR_FLAG_WRITE_FAILED
#define ACC_REG_ERROR_FLAG_WRITE_FAILED
Definition: acc_reg_protocol.h:17
REG_MODE_ERROR
@ REG_MODE_ERROR
Definition: acc_reg_protocol.c:22
REG_ERROR_READ_ADDRESS
#define REG_ERROR_READ_ADDRESS
Definition: acc_reg_protocol.c:39
acc_reg_protocol_setup
void acc_reg_protocol_setup(const acc_reg_protocol_t *protocol_struct, uint16_t register_count)
Setup register protocol.
Definition: acc_reg_protocol.c:202
acc_reg_protocol_get_error_flags
uint32_t acc_reg_protocol_get_error_flags(void)
Get the error flags for the register protocol.
Definition: acc_reg_protocol.c:319
REG_MODE_READ_WRITE
@ REG_MODE_READ_WRITE
Definition: acc_reg_protocol.c:19
reg_protocol_struct
static const acc_reg_protocol_t * reg_protocol_struct
Definition: acc_reg_protocol.c:42
register_is_writable
static bool register_is_writable(void)
Return true if register is writable.
Definition: acc_reg_protocol.c:101
acc_reg_protocol_float_to_uint32_milli
uint32_t acc_reg_protocol_float_to_uint32_milli(float value)
Convert 1000 * float to uint32.
Definition: acc_reg_protocol.c:336
acc_reg_mode_t
acc_reg_mode_t
Register access mode.
Definition: acc_reg_protocol.c:17
ACC_REG_ERROR_FLAG_PROTOCOL_STATE_ERROR
#define ACC_REG_ERROR_FLAG_PROTOCOL_STATE_ERROR
Definition: acc_reg_protocol.h:14
REG_MODE_WRITE
@ REG_MODE_WRITE
Definition: acc_reg_protocol.c:21
ACC_REG_ERROR_FLAG_WRITE_TO_READ_ONLY
#define ACC_REG_ERROR_FLAG_WRITE_TO_READ_ONLY
Definition: acc_reg_protocol.h:18
acc_reg_protocol_t
Register access mode and functions struct.
Definition: acc_reg_protocol.h:38
acc_reg_protocol.h
REG_STATE_NACK_NEXT_WRITE
@ REG_STATE_NACK_NEXT_WRITE
Definition: acc_reg_protocol.c:35
REG_STATE_WAIT_FOR_WRITE
@ REG_STATE_WAIT_FOR_WRITE
Definition: acc_reg_protocol.c:33
REG_STATE_WAIT_FOR_READ_OR_WRITE
@ REG_STATE_WAIT_FOR_READ_OR_WRITE
Definition: acc_reg_protocol.c:32
reg_state
static acc_reg_protocol_state_t reg_state
Definition: acc_reg_protocol.c:44
acc_reg_protocol_data_nack
bool acc_reg_protocol_data_nack(void)
Should protocol NACK the next data.
Definition: acc_reg_protocol.c:218
reg_error_flags
static uint32_t reg_error_flags
Definition: acc_reg_protocol.c:46
acc_reg_protocol_t::read
acc_reg_read_func_t * read
Definition: acc_reg_protocol.h:41
REG_INVALID_ADDRESS
#define REG_INVALID_ADDRESS
Definition: acc_reg_protocol.c:38
get_register_struct
static const acc_reg_protocol_t * get_register_struct(uint16_t register_address)
Get register struct from protocol struct.
Definition: acc_reg_protocol.c:55