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 {
24 
25 
26 /**
27  * @brief Register protocol state
28  */
29 typedef enum
30 {
37 
38 #define REG_INVALID_ADDRESS 0xffffU
39 #define REG_ERROR_READ_ADDRESS 0xeeeeee00U
40 #define REG_ERROR_READ_OF_WO_REG 0xeeeeee01U
41 
43 static uint16_t reg_register_count = 0;
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  {
94  }
95 }
96 
97 
98 /**
99  * @brief Return true if register is writable
100  */
101 static bool register_is_writable(void)
102 {
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 
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 */
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 */
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 
167 
168  if (reg != NULL)
169  {
170  if (reg->write != NULL)
171  {
172  if (!reg->write(data))
173  {
175  status = false;
176  }
177  }
178  else
179  {
180  /* Register write error, write to read only register */
182  status = false;
183  }
184  }
185  else
186  {
187  /* Register read outside of address space */
189  status = false;
190  }
191 
192  /* Increase reg addess */
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 
208 }
209 
210 
212 {
215 }
216 
217 
219 {
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  {
235  {
236  set_address(buffer);
237 
238  if (register_is_writable())
239  {
240  /* Register can be read or written */
242  }
243  else
244  {
245  /**
246  * - Read only register
247  * - No valid address, read is still possoble
248  */
250  }
251  }
252  else
253  {
254  /* FAIL: Incorrect state */
257  }
258  }
259  else if (data_in_length == ACC_REG_PROTOCOL_REGDATA_LENGTH)
260  {
263  {
264  if (write_register(buffer) && register_is_writable())
265  {
266  /* OK: Another write is possible */
268  }
269  else
270  {
271  /**
272  * - Write register failed
273  * - Next register is read only
274  */
276  }
277  }
278  else
279  {
280  /* FAIL: Incorrect state */
283  }
284  }
285  else
286  {
287  /* FAIL: Incorrect packet length */
290  }
291 }
292 
293 
294 void acc_reg_protocol_data_out(uint8_t *buffer, size_t data_out_length)
295 {
298  {
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 */
309  }
310  }
311  else
312  {
313  /* FAIL: Incorrect state */
315  }
316 }
317 
318 
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 
331 {
332  return (int32_t)(value*1000.0f);
333 }
334 
335 
337 {
338  return (uint32_t)(value*1000.0f);
339 }
340 
341 
343 {
344  float val = (float)value;
345 
346  val = val / 1000.0f;
347  return val;
348 }
349 
350 
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