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>© 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, ®[0]);
186 bytecpy((uint8_t *)&tdm_cmax_l, ®[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(®[0], (uint8_t *)&tdm_cmax_h);
204 bytecpy(®[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, ®[0]);
236 bytecpy((uint8_t *)&tdm_cmax_l, ®[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, ®[0]);
273 bytecpy((uint8_t *)&axes_ctrl_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(®[0], (uint8_t *)&tdm_ctrl_reg);
290 bytecpy(®[1], (uint8_t *)&axes_ctrl_reg);
291
292 if (ret == 0)
293 {
294 ret = lis25ba_write_reg(ctx, LIS25BA_TDM_CTRL_REG, (uint8_t *)®,
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, ®[0]);
324 bytecpy((uint8_t *)&axes_ctrl_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