1 /**
2   ******************************************************************************
3   * @file    lis25ba_reg.c
4   * @author  Sensors Software Solution Team
5   * @brief   LIS25BA driver file
6   ******************************************************************************
7   * @attention
8   *
9   * <h2><center>&copy; Copyright (c) 2021 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 "lis25ba_reg.h"
21 
22 /**
23   * @defgroup  LIS25BA
24   * @brief     This file provides a set of functions needed to drive the
25   *            lis25ba enhanced inertial module.
26   * @{
27   *
28   */
29 
30 /**
31   * @defgroup  LIS25BA_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   */
lis25ba_read_reg(const stmdev_ctx_t * ctx,uint8_t reg,uint8_t * data,uint16_t len)49 int32_t __weak lis25ba_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)
56   {
57     return -1;
58   }
59 
60   ret = ctx->read_reg(ctx->handle, reg, data, len);
61 
62   return ret;
63 }
64 
65 /**
66   * @brief  Write generic device register
67   *
68   * @param  ctx   communication interface handler.(ptr)
69   * @param  reg   first register address to write.
70   * @param  data  the buffer contains data to be written.(ptr)
71   * @param  len   number of consecutive register to write.
72   * @retval       interface status (MANDATORY: return 0 -> no Error).
73   *
74   */
lis25ba_write_reg(const stmdev_ctx_t * ctx,uint8_t reg,uint8_t * data,uint16_t len)75 int32_t __weak lis25ba_write_reg(const stmdev_ctx_t *ctx, uint8_t reg,
76                                  uint8_t *data,
77                                  uint16_t len)
78 {
79   int32_t ret;
80 
81   if (ctx == NULL)
82   {
83     return -1;
84   }
85 
86   ret = ctx->write_reg(ctx->handle, reg, data, len);
87 
88   return ret;
89 }
90 
91 /**
92   * @}
93   *
94   */
95 
96 /**
97   * @defgroup  LIS25BA_Private_functions
98   * @brief     Section collect all the utility functions needed by APIs.
99   * @{
100   *
101   */
102 
bytecpy(uint8_t * target,uint8_t * source)103 static void bytecpy(uint8_t *target, uint8_t *source)
104 {
105   if ((target != NULL) && (source != NULL))
106   {
107     *target = *source;
108   }
109 }
110 
111 /**
112   * @}
113   *
114   */
115 
116 /**
117   * @defgroup  LIS25BA_Sensitivity
118   * @brief     These functions convert raw-data into engineering units.
119   * @{
120   *
121   */
lis25ba_from_raw_to_mg(int16_t lsb)122 float_t lis25ba_from_raw_to_mg(int16_t lsb)
123 {
124   return ((float_t)lsb) * 0.122f;
125 }
126 
127 /**
128   * @}
129   *
130   */
131 
132 /**
133   * @defgroup  Basic configuration
134   * @brief     This section groups all the functions concerning
135   *            device basic configuration.
136   * @{
137   *
138   */
139 
140 /**
141   * @brief  Device "Who am I".[get]
142   *
143   * @param  ctx   communication interface handler.(ptr)
144   * @param  val   ID values read from the I2C interface.
145   *
146   * @retval       interface status (MANDATORY: return 0 -> no Error).
147   *
148   */
lis25ba_id_get(const stmdev_ctx_t * ctx,lis25ba_id_t * val)149 int32_t lis25ba_id_get(const stmdev_ctx_t *ctx, lis25ba_id_t *val)
150 {
151   int32_t ret = 0;
152 
153   if (ctx != NULL)
154   {
155     ret = lis25ba_read_reg(ctx, LIS25BA_WHO_AM_I, (uint8_t *) & (val->id), 1);
156   }
157 
158   return ret;
159 }
160 
161 /**
162   * @brief  Configures the bus operating mode.[set]
163   *
164   * @param  ctx   communication interface handler.(ptr)
165   * @param  val   configures the TDM bus operating mode.(ptr)
166   *
167   * @retval       interface status (MANDATORY: return 0 -> no Error).
168   *
169   */
lis25ba_bus_mode_set(const stmdev_ctx_t * ctx,lis25ba_bus_mode_t * val)170 int32_t lis25ba_bus_mode_set(const stmdev_ctx_t *ctx,
171                              lis25ba_bus_mode_t *val)
172 {
173   lis25ba_tdm_ctrl_reg_t tdm_ctrl_reg;
174   lis25ba_tdm_cmax_h_t tdm_cmax_h;
175   lis25ba_tdm_cmax_l_t tdm_cmax_l;
176   uint8_t reg[2];
177   int32_t ret;
178 
179   ret = lis25ba_read_reg(ctx, LIS25BA_TDM_CTRL_REG,
180                          (uint8_t *)&tdm_ctrl_reg, 1);
181 
182   if (ret == 0)
183   {
184     ret = lis25ba_read_reg(ctx, LIS25BA_TDM_CMAX_H, reg, 2);
185     bytecpy((uint8_t *)&tdm_cmax_h, &reg[0]);
186     bytecpy((uint8_t *)&tdm_cmax_l, &reg[1]);
187     tdm_ctrl_reg.tdm_pd = ~val->tdm.en;
188     tdm_ctrl_reg.data_valid = val->tdm.clk_pol;
189     tdm_ctrl_reg.delayed = val->tdm.clk_edge;
190     tdm_ctrl_reg.wclk_fq = val->tdm.mapping;
191     tdm_cmax_h.tdm_cmax = (uint8_t)(val->tdm.cmax / 256U);
192     tdm_cmax_l.tdm_cmax = (uint8_t)(val->tdm.cmax - tdm_cmax_h.tdm_cmax);
193   }
194 
195   if (ret == 0)
196   {
197     ret = lis25ba_write_reg(ctx, LIS25BA_TDM_CTRL_REG,
198                             (uint8_t *)&tdm_ctrl_reg, 1);
199   }
200 
201   if (ret == 0)
202   {
203     bytecpy(&reg[0], (uint8_t *)&tdm_cmax_h);
204     bytecpy(&reg[1], (uint8_t *)&tdm_cmax_l);
205     ret = lis25ba_write_reg(ctx, LIS25BA_TDM_CMAX_H, reg, 2);
206   }
207 
208   return ret;
209 }
210 
211 /**
212   * @brief  Get the bus operating mode.[get]
213   *
214   * @param  ctx   communication interface handler.(ptr)
215   * @param  val   configures the TDM bus operating mode.(ptr)
216   *
217   * @retval       interface status (MANDATORY: return 0 -> no Error).
218   *
219   */
lis25ba_bus_mode_get(const stmdev_ctx_t * ctx,lis25ba_bus_mode_t * val)220 int32_t lis25ba_bus_mode_get(const stmdev_ctx_t *ctx,
221                              lis25ba_bus_mode_t *val)
222 {
223   lis25ba_tdm_ctrl_reg_t tdm_ctrl_reg;
224   lis25ba_tdm_cmax_h_t tdm_cmax_h;
225   lis25ba_tdm_cmax_l_t tdm_cmax_l;
226   uint8_t reg[2];
227   int32_t ret;
228 
229   ret = lis25ba_read_reg(ctx, LIS25BA_TDM_CTRL_REG,
230                          (uint8_t *)&tdm_ctrl_reg, 1);
231 
232   if (ret == 0)
233   {
234     ret = lis25ba_read_reg(ctx, LIS25BA_TDM_CMAX_H, reg, 2);
235     bytecpy((uint8_t *)&tdm_cmax_h, &reg[0]);
236     bytecpy((uint8_t *)&tdm_cmax_l, &reg[1]);
237   }
238 
239   val->tdm.en = ~tdm_ctrl_reg.tdm_pd;
240   val->tdm.clk_pol = tdm_ctrl_reg.data_valid;
241   val->tdm.clk_edge = tdm_ctrl_reg.delayed;
242   val->tdm.mapping = tdm_ctrl_reg.wclk_fq;
243   val->tdm.cmax = tdm_cmax_h.tdm_cmax * 256U;
244   val->tdm.cmax += tdm_cmax_l.tdm_cmax;
245 
246   return ret;
247 }
248 
249 /**
250   * @brief  Sensor conversion parameters selection.[set]
251   *
252   * @param  ctx   communication interface handler.(ptr)
253   * @param  val   set the sensor conversion parameters by checking
254   *               the constraints of the device.(ptr)
255   *
256   * @retval       interface status (MANDATORY: return 0 -> no Error).
257   *
258   */
lis25ba_mode_set(const stmdev_ctx_t * ctx,lis25ba_md_t * val)259 int32_t lis25ba_mode_set(const stmdev_ctx_t *ctx, lis25ba_md_t *val)
260 {
261   lis25ba_axes_ctrl_reg_t axes_ctrl_reg;
262   lis25ba_tdm_ctrl_reg_t tdm_ctrl_reg;
263   lis25ba_ctrl_reg_t ctrl_reg;
264   uint8_t reg[2];
265   int32_t ret;
266 
267   ret = lis25ba_read_reg(ctx, LIS25BA_CTRL_REG, (uint8_t *)&ctrl_reg, 1);
268 
269   if (ret == 0)
270   {
271     ret = lis25ba_read_reg(ctx, LIS25BA_TDM_CTRL_REG, reg, 2);
272     bytecpy((uint8_t *)&tdm_ctrl_reg, &reg[0]);
273     bytecpy((uint8_t *)&axes_ctrl_reg,  &reg[1]);
274   }
275 
276   ctrl_reg.pd = (uint8_t)val->xl.odr & 0x01U;
277   tdm_ctrl_reg.wclk_fq = ((uint8_t)val->xl.odr & 0x06U) >> 1;
278   axes_ctrl_reg.odr_auto_en = ((uint8_t)val->xl.odr & 0x10U) >> 4;
279   axes_ctrl_reg.axisx_en = val->xl.axis.x;
280   axes_ctrl_reg.axisy_en = val->xl.axis.y;
281   axes_ctrl_reg.axisz_en = val->xl.axis.z;
282 
283   if (ret == 0)
284   {
285     ret = lis25ba_write_reg(ctx, LIS25BA_CTRL_REG, (uint8_t *)&ctrl_reg, 1);
286   }
287 
288   /* writing checked configuration */
289   bytecpy(&reg[0], (uint8_t *)&tdm_ctrl_reg);
290   bytecpy(&reg[1], (uint8_t *)&axes_ctrl_reg);
291 
292   if (ret == 0)
293   {
294     ret = lis25ba_write_reg(ctx, LIS25BA_TDM_CTRL_REG, (uint8_t *)&reg,
295                             2);
296   }
297 
298   return ret;
299 }
300 
301 /**
302   * @brief  Sensor conversion parameters selection.[get]
303   *
304   * @param  ctx   communication interface handler.(ptr)
305   * @param  val   get the sensor conversion parameters.(ptr)
306   *
307   * @retval       interface status (MANDATORY: return 0 -> no Error).
308   *
309   */
lis25ba_mode_get(const stmdev_ctx_t * ctx,lis25ba_md_t * val)310 int32_t lis25ba_mode_get(const stmdev_ctx_t *ctx, lis25ba_md_t *val)
311 {
312   lis25ba_axes_ctrl_reg_t axes_ctrl_reg;
313   lis25ba_tdm_ctrl_reg_t tdm_ctrl_reg;
314   lis25ba_ctrl_reg_t ctrl_reg;
315   uint8_t reg[2];
316   int32_t ret;
317 
318   ret = lis25ba_read_reg(ctx, LIS25BA_CTRL_REG, (uint8_t *)&ctrl_reg, 1);
319 
320   if (ret == 0)
321   {
322     ret = lis25ba_read_reg(ctx, LIS25BA_TDM_CTRL_REG, reg, 2);
323     bytecpy((uint8_t *)&tdm_ctrl_reg, &reg[0]);
324     bytecpy((uint8_t *)&axes_ctrl_reg,  &reg[1]);
325   }
326 
327   val->xl.axis.x = axes_ctrl_reg.axisx_en;
328   val->xl.axis.y = axes_ctrl_reg.axisy_en;
329   val->xl.axis.z = axes_ctrl_reg.axisz_en;
330 
331   switch ((axes_ctrl_reg.odr_auto_en << 4) | (tdm_ctrl_reg.wclk_fq <<
332                                               1) |
333           ctrl_reg.pd)
334   {
335     case LIS25BA_XL_OFF:
336       val->xl.odr = LIS25BA_XL_OFF;
337       break;
338 
339     case LIS25BA_XL_8kHz:
340       val->xl.odr = LIS25BA_XL_8kHz;
341       break;
342 
343     case LIS25BA_XL_16kHz:
344       val->xl.odr = LIS25BA_XL_16kHz;
345       break;
346 
347     case LIS25BA_XL_24kHz:
348       val->xl.odr = LIS25BA_XL_24kHz;
349       break;
350 
351     case LIS25BA_XL_HW_SEL:
352       val->xl.odr = LIS25BA_XL_HW_SEL;
353       break;
354 
355     default:
356       val->xl.odr = LIS25BA_XL_OFF;
357       break;
358   }
359 
360   return ret;
361 }
362 
363 /**
364   * @brief  Read data in engineering unit.[get]
365   *
366   * @param  tdm_stream  data stream from TDM interface.(ptr)
367   * @param  md          the TDM interface configuration.(ptr)
368   * @param  data        data read by the sensor.(ptr)
369   *
370   * @retval             interface status (MANDATORY: return 0 -> no Error).
371   *
372   */
lis25ba_data_get(uint16_t * tdm_stream,lis25ba_bus_mode_t * md,lis25ba_data_t * data)373 int32_t lis25ba_data_get(uint16_t *tdm_stream, lis25ba_bus_mode_t *md,
374                          lis25ba_data_t *data)
375 {
376   uint8_t offset;
377   uint8_t i;
378 
379   if (md->tdm.mapping == PROPERTY_DISABLE)
380   {
381     offset = 0; /* slot0-1-2 */
382   }
383 
384   else
385   {
386     offset = 4; /* slot4-5-6 */
387   }
388 
389   for (i = 0U; i < 3U; i++)
390   {
391     data->xl.raw[i] = (int16_t) tdm_stream[i + offset];
392     data->xl.mg[i] = lis25ba_from_raw_to_mg(data->xl.raw[i]);
393   }
394 
395   return 0;
396 }
397 
398 /**
399   * @brief  Linear acceleration sensor self-test enable.[set]
400   *
401   * @param  ctx      read / write interface definitions.(ptr)
402   * @param  val      enable/ disable selftest
403   *
404   * @retval          interface status (MANDATORY: return 0 -> no Error).
405   *
406   */
lis25ba_self_test_set(const stmdev_ctx_t * ctx,uint8_t val)407 int32_t lis25ba_self_test_set(const stmdev_ctx_t *ctx, uint8_t val)
408 {
409   lis25ba_test_reg_t test_reg;
410   int32_t ret;
411 
412   ret = lis25ba_read_reg(ctx, LIS25BA_TEST_REG, (uint8_t *)&test_reg, 1);
413 
414   if (ret == 0)
415   {
416     test_reg.st = val;
417     ret = lis25ba_write_reg(ctx, LIS25BA_TEST_REG, (uint8_t *)&test_reg, 1);
418   }
419 
420   return ret;
421 }
422 
423 /**
424   * @brief  Linear acceleration sensor self-test enable.[get]
425   *
426   * @param  ctx      read / write interface definitions.(ptr)
427   * @param  val      enable/ disable selftest.(ptr)
428   *
429   * @retval          interface status (MANDATORY: return 0 -> no Error).
430   *
431   */
lis25ba_self_test_get(const stmdev_ctx_t * ctx,uint8_t * val)432 int32_t lis25ba_self_test_get(const stmdev_ctx_t *ctx, uint8_t *val)
433 {
434   lis25ba_test_reg_t test_reg;
435   int32_t ret;
436 
437   ret = lis25ba_read_reg(ctx, LIS25BA_TEST_REG, (uint8_t *)&test_reg, 1);
438   *val = test_reg.st;
439 
440   return ret;
441 }
442 
443 /**
444   * @}
445   *
446   */
447 
448 /**
449   * @}
450   *
451   */
452 
453 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
454