1 /**
2   ******************************************************************************
3   * @file    ais25ba_reg.c
4   * @author  Sensors Software Solution Team
5   * @brief   AIS25BA driver file
6   ******************************************************************************
7   * @attention
8   *
9   * <h2><center>&copy; Copyright (c) 2022 STMicroelectronics.
10   * All rights reserved.</center></h2>
11   *
12   * This software component is licensed by ST under BSD 3-Clause license,
13   * the "License"; You may not use this file except in compliance with the
14   * License. You may obtain a copy of the License at:
15   *                        opensource.org/licenses/BSD-3-Clause
16   *
17   ******************************************************************************
18   */
19 
20 #include "ais25ba_reg.h"
21 
22 /**
23   * @defgroup  AIS25BA
24   * @brief     This file provides a set of functions needed to drive the
25   *            ais25ba enhanced inertial module.
26   * @{
27   *
28   */
29 
30 /**
31   * @defgroup  AIS25BA_Interfaces_Functions
32   * @brief     This section provide a set of functions used to read and
33   *            write a generic register of the device.
34   *            MANDATORY: return 0 -> no Error.
35   * @{
36   *
37   */
38 
39 /**
40   * @brief  Read generic device register
41   *
42   * @param  ctx   communication interface handler.(ptr)
43   * @param  reg   first register address to read.
44   * @param  data  buffer for data read.(ptr)
45   * @param  len   number of consecutive register to read.
46   * @retval       interface status (MANDATORY: return 0 -> no Error).
47   *
48   */
ais25ba_read_reg(const stmdev_ctx_t * ctx,uint8_t reg,uint8_t * data,uint16_t len)49 int32_t __weak ais25ba_read_reg(const stmdev_ctx_t *ctx, uint8_t reg,
50                                 uint8_t *data,
51                                 uint16_t len)
52 {
53   int32_t ret;
54 
55   if (ctx == NULL) return -1;
56 
57   ret = ctx->read_reg(ctx->handle, reg, data, len);
58 
59   return ret;
60 }
61 
62 /**
63   * @brief  Write generic device register
64   *
65   * @param  ctx   communication interface handler.(ptr)
66   * @param  reg   first register address to write.
67   * @param  data  the buffer contains data to be written.(ptr)
68   * @param  len   number of consecutive register to write.
69   * @retval       interface status (MANDATORY: return 0 -> no Error).
70   *
71   */
ais25ba_write_reg(const stmdev_ctx_t * ctx,uint8_t reg,uint8_t * data,uint16_t len)72 int32_t __weak ais25ba_write_reg(const stmdev_ctx_t *ctx, uint8_t reg,
73                                  uint8_t *data,
74                                  uint16_t len)
75 {
76   int32_t ret;
77 
78   if (ctx == NULL) return -1;
79 
80   ret = ctx->write_reg(ctx->handle, reg, data, len);
81 
82   return ret;
83 }
84 
85 /**
86   * @}
87   *
88   */
89 
90 /**
91   * @defgroup  AIS25BA_Private_functions
92   * @brief     Section collect all the utility functions needed by APIs.
93   * @{
94   *
95   */
96 
bytecpy(uint8_t * target,uint8_t * source)97 static void bytecpy(uint8_t *target, uint8_t *source)
98 {
99   if ((target != NULL) && (source != NULL))
100   {
101     *target = *source;
102   }
103 }
104 
105 /**
106   * @}
107   *
108   */
109 
110 /**
111   * @defgroup  AIS25BA_Sensitivity
112   * @brief     These functions convert raw-data into engineering units.
113   * @{
114   *
115   */
ais25ba_from_raw_to_mg(int16_t lsb)116 float_t ais25ba_from_raw_to_mg(int16_t lsb)
117 {
118   return ((float_t)lsb) * 0.122f;
119 }
120 
121 /**
122   * @}
123   *
124   */
125 
126 /**
127   * @defgroup  Basic configuration
128   * @brief     This section groups all the functions concerning
129   *            device basic configuration.
130   * @{
131   *
132   */
133 
134 /**
135   * @brief  Device "Who am I".[get]
136   *
137   * @param  ctx   communication interface handler.(ptr)
138   * @param  val   ID values read from the I2C interface.
139   *
140   * @retval       interface status (MANDATORY: return 0 -> no Error).
141   *
142   */
ais25ba_id_get(const stmdev_ctx_t * ctx,ais25ba_id_t * val)143 int32_t ais25ba_id_get(const stmdev_ctx_t *ctx, ais25ba_id_t *val)
144 {
145   int32_t ret = 0;
146 
147   if (ctx != NULL)
148   {
149     ret = ais25ba_read_reg(ctx, AIS25BA_WHO_AM_I, (uint8_t *) & (val->id), 1);
150   }
151 
152   return ret;
153 }
154 
155 /**
156   * @brief  Configures the bus operating mode.[set]
157   *
158   * @param  ctx   communication interface handler.(ptr)
159   * @param  val   configures the TDM bus operating mode.(ptr)
160   *
161   * @retval       interface status (MANDATORY: return 0 -> no Error).
162   *
163   */
ais25ba_bus_mode_set(const stmdev_ctx_t * ctx,ais25ba_bus_mode_t * val)164 int32_t ais25ba_bus_mode_set(const stmdev_ctx_t *ctx,
165                              ais25ba_bus_mode_t *val)
166 {
167   ais25ba_tdm_ctrl_reg_t tdm_ctrl_reg;
168   ais25ba_tdm_cmax_h_t tdm_cmax_h;
169   ais25ba_tdm_cmax_l_t tdm_cmax_l;
170   uint8_t reg[2];
171   int32_t ret;
172 
173   ret = ais25ba_read_reg(ctx, AIS25BA_TDM_CTRL_REG,
174                          (uint8_t *)&tdm_ctrl_reg, 1);
175 
176   if (ret == 0)
177   {
178     ret = ais25ba_read_reg(ctx, AIS25BA_TDM_CMAX_H, reg, 2);
179     bytecpy((uint8_t *)&tdm_cmax_h, &reg[0]);
180     bytecpy((uint8_t *)&tdm_cmax_l, &reg[1]);
181     tdm_ctrl_reg.tdm_pd = ~val->tdm.en;
182     tdm_ctrl_reg.data_valid = val->tdm.clk_pol;
183     tdm_ctrl_reg.delayed = val->tdm.clk_edge;
184     tdm_ctrl_reg.wclk_fq = val->tdm.mapping;
185     tdm_cmax_h.tdm_cmax = (uint8_t)(val->tdm.cmax / 256U);
186     tdm_cmax_l.tdm_cmax = (uint8_t)(val->tdm.cmax - tdm_cmax_h.tdm_cmax);
187   }
188 
189   if (ret == 0)
190   {
191     ret = ais25ba_write_reg(ctx, AIS25BA_TDM_CTRL_REG,
192                             (uint8_t *)&tdm_ctrl_reg, 1);
193   }
194 
195   if (ret == 0)
196   {
197     bytecpy(&reg[0], (uint8_t *)&tdm_cmax_h);
198     bytecpy(&reg[1], (uint8_t *)&tdm_cmax_l);
199     ret = ais25ba_write_reg(ctx, AIS25BA_TDM_CMAX_H, reg, 2);
200   }
201 
202   return ret;
203 }
204 
205 /**
206   * @brief  Get the bus operating mode.[get]
207   *
208   * @param  ctx   communication interface handler.(ptr)
209   * @param  val   configures the TDM bus operating mode.(ptr)
210   *
211   * @retval       interface status (MANDATORY: return 0 -> no Error).
212   *
213   */
ais25ba_bus_mode_get(const stmdev_ctx_t * ctx,ais25ba_bus_mode_t * val)214 int32_t ais25ba_bus_mode_get(const stmdev_ctx_t *ctx,
215                              ais25ba_bus_mode_t *val)
216 {
217   ais25ba_tdm_ctrl_reg_t tdm_ctrl_reg;
218   ais25ba_tdm_cmax_h_t tdm_cmax_h;
219   ais25ba_tdm_cmax_l_t tdm_cmax_l;
220   uint8_t reg[2];
221   int32_t ret;
222 
223   ret = ais25ba_read_reg(ctx, AIS25BA_TDM_CTRL_REG,
224                          (uint8_t *)&tdm_ctrl_reg, 1);
225 
226   if (ret == 0)
227   {
228     ret = ais25ba_read_reg(ctx, AIS25BA_TDM_CMAX_H, reg, 2);
229     bytecpy((uint8_t *)&tdm_cmax_h, &reg[0]);
230     bytecpy((uint8_t *)&tdm_cmax_l, &reg[1]);
231   }
232 
233   val->tdm.en = ~tdm_ctrl_reg.tdm_pd;
234   val->tdm.clk_pol = tdm_ctrl_reg.data_valid;
235   val->tdm.clk_edge = tdm_ctrl_reg.delayed;
236   val->tdm.mapping = tdm_ctrl_reg.wclk_fq;
237   val->tdm.cmax = tdm_cmax_h.tdm_cmax * 256U;
238   val->tdm.cmax += tdm_cmax_l.tdm_cmax;
239 
240   return ret;
241 }
242 
243 /**
244   * @brief  Sensor conversion parameters selection.[set]
245   *
246   * @param  ctx   communication interface handler.(ptr)
247   * @param  val   set the sensor conversion parameters by checking
248   *               the constraints of the device.(ptr)
249   *
250   * @retval       interface status (MANDATORY: return 0 -> no Error).
251   *
252   */
ais25ba_mode_set(const stmdev_ctx_t * ctx,ais25ba_md_t * val)253 int32_t ais25ba_mode_set(const stmdev_ctx_t *ctx, ais25ba_md_t *val)
254 {
255   ais25ba_axes_ctrl_reg_t axes_ctrl_reg;
256   ais25ba_tdm_ctrl_reg_t tdm_ctrl_reg;
257   ais25ba_ctrl_reg_t ctrl_reg;
258   uint8_t reg[2];
259   int32_t ret;
260 
261   ret = ais25ba_read_reg(ctx, AIS25BA_CTRL_REG_1, (uint8_t *)&ctrl_reg, 1);
262 
263   if (ret == 0)
264   {
265     ret = ais25ba_read_reg(ctx, AIS25BA_TDM_CTRL_REG, reg, 2);
266     bytecpy((uint8_t *)&tdm_ctrl_reg, &reg[0]);
267     bytecpy((uint8_t *)&axes_ctrl_reg,  &reg[1]);
268   }
269 
270   ctrl_reg.pd = (uint8_t)val->xl.odr & 0x01U;
271   tdm_ctrl_reg.wclk_fq = ((uint8_t)val->xl.odr & 0x06U) >> 1;
272   axes_ctrl_reg.odr_auto_en = ((uint8_t)val->xl.odr & 0x10U) >> 4;
273 
274   if (ret == 0)
275   {
276     ret = ais25ba_write_reg(ctx, AIS25BA_CTRL_REG_1, (uint8_t *)&ctrl_reg, 1);
277   }
278 
279   /* writing checked configuration */
280   bytecpy(&reg[0], (uint8_t *)&tdm_ctrl_reg);
281   bytecpy(&reg[1], (uint8_t *)&axes_ctrl_reg);
282 
283   if (ret == 0)
284   {
285     ret = ais25ba_write_reg(ctx, AIS25BA_TDM_CTRL_REG, (uint8_t *)&reg,
286                             2);
287   }
288 
289   return ret;
290 }
291 
292 /**
293   * @brief  Sensor conversion parameters selection.[get]
294   *
295   * @param  ctx   communication interface handler.(ptr)
296   * @param  val   get the sensor conversion parameters.(ptr)
297   *
298   * @retval       interface status (MANDATORY: return 0 -> no Error).
299   *
300   */
ais25ba_mode_get(const stmdev_ctx_t * ctx,ais25ba_md_t * val)301 int32_t ais25ba_mode_get(const stmdev_ctx_t *ctx, ais25ba_md_t *val)
302 {
303   ais25ba_axes_ctrl_reg_t axes_ctrl_reg;
304   ais25ba_tdm_ctrl_reg_t tdm_ctrl_reg;
305   ais25ba_ctrl_reg_t ctrl_reg;
306   uint8_t reg[2];
307   int32_t ret;
308 
309   ret = ais25ba_read_reg(ctx, AIS25BA_CTRL_REG_1, (uint8_t *)&ctrl_reg, 1);
310 
311   if (ret == 0)
312   {
313     ret = ais25ba_read_reg(ctx, AIS25BA_TDM_CTRL_REG, reg, 2);
314     bytecpy((uint8_t *)&tdm_ctrl_reg, &reg[0]);
315     bytecpy((uint8_t *)&axes_ctrl_reg,  &reg[1]);
316   }
317 
318   switch ((axes_ctrl_reg.odr_auto_en << 4) | (tdm_ctrl_reg.wclk_fq <<
319                                               1) |
320           ctrl_reg.pd)
321   {
322     case AIS25BA_XL_OFF:
323       val->xl.odr = AIS25BA_XL_OFF;
324       break;
325 
326     case AIS25BA_XL_8kHz:
327       val->xl.odr = AIS25BA_XL_8kHz;
328       break;
329 
330     case AIS25BA_XL_16kHz:
331       val->xl.odr = AIS25BA_XL_16kHz;
332       break;
333 
334     case AIS25BA_XL_24kHz:
335       val->xl.odr = AIS25BA_XL_24kHz;
336       break;
337 
338     case AIS25BA_XL_HW_SEL:
339       val->xl.odr = AIS25BA_XL_HW_SEL;
340       break;
341 
342     default:
343       val->xl.odr = AIS25BA_XL_OFF;
344       break;
345   }
346 
347   return ret;
348 }
349 
350 /**
351   * @brief  Read data in engineering unit.[get]
352   *
353   * @param  tdm_stream  data stream from TDM interface.(ptr)
354   * @param  md          the TDM interface configuration.(ptr)
355   * @param  data        data read by the sensor.(ptr)
356   *
357   * @retval             interface status (MANDATORY: return 0 -> no Error).
358   *
359   */
ais25ba_data_get(uint16_t * tdm_stream,ais25ba_bus_mode_t * md,ais25ba_data_t * data)360 int32_t ais25ba_data_get(uint16_t *tdm_stream, ais25ba_bus_mode_t *md,
361                          ais25ba_data_t *data)
362 {
363   uint8_t offset;
364   uint8_t i;
365 
366   if (md->tdm.mapping == PROPERTY_DISABLE)
367   {
368     offset = 0; /* slot0-1-2 */
369   }
370 
371   else
372   {
373     offset = 4; /* slot4-5-6 */
374   }
375 
376   for (i = 0U; i < 3U; i++)
377   {
378     data->xl.raw[i] = (int16_t) tdm_stream[i + offset];
379     data->xl.mg[i] = ais25ba_from_raw_to_mg(data->xl.raw[i]);
380   }
381 
382   return 0;
383 }
384 
385 /**
386   * @brief  Linear acceleration sensor self-test enable.[set]
387   *
388   * @param  ctx      read / write interface definitions.(ptr)
389   * @param  val      enable/ disable selftest
390   *
391   * @retval          interface status (MANDATORY: return 0 -> no Error).
392   *
393   */
ais25ba_self_test_set(const stmdev_ctx_t * ctx,uint8_t val)394 int32_t ais25ba_self_test_set(const stmdev_ctx_t *ctx, uint8_t val)
395 {
396   ais25ba_test_reg_t test_reg;
397   int32_t ret;
398 
399   ret = ais25ba_read_reg(ctx, AIS25BA_TEST_REG, (uint8_t *)&test_reg, 1);
400 
401   if (ret == 0)
402   {
403     test_reg.st = val;
404     ret = ais25ba_write_reg(ctx, AIS25BA_TEST_REG, (uint8_t *)&test_reg, 1);
405   }
406 
407   return ret;
408 }
409 
410 /**
411   * @brief  Linear acceleration sensor self-test enable.[get]
412   *
413   * @param  ctx      read / write interface definitions.(ptr)
414   * @param  val      enable/ disable selftest.(ptr)
415   *
416   * @retval          interface status (MANDATORY: return 0 -> no Error).
417   *
418   */
ais25ba_self_test_get(const stmdev_ctx_t * ctx,uint8_t * val)419 int32_t ais25ba_self_test_get(const stmdev_ctx_t *ctx, uint8_t *val)
420 {
421   ais25ba_test_reg_t test_reg;
422   int32_t ret;
423 
424   ret = ais25ba_read_reg(ctx, AIS25BA_TEST_REG, (uint8_t *)&test_reg, 1);
425   *val = test_reg.st;
426 
427   return ret;
428 }
429 
430 /**
431   * @}
432   *
433   */
434 
435 /**
436   * @}
437   *
438   */
439 
440 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
441