1 /* Bosch BMI08X inertial measurement unit driver
2  *
3  * Copyright (c) 2022 Meta Platforms, Inc. and its affiliates
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <zephyr/kernel.h>
9 #include "bmi08x.h"
10 
11 /*
12  * Output data rate map with allowed frequencies:
13  * freq = freq_int + freq_milli / 1000
14  *
15  * Since we don't need a finer frequency resolution than milliHz, use uint16_t
16  * to save some flash.
17  */
18 static const struct {
19 	uint16_t freq_int;
20 	uint16_t freq_milli; /* User should convert to uHz before setting the
21 			      * SENSOR_ATTR_SAMPLING_FREQUENCY attribute.
22 			      */
23 } bmi08x_odr_map[] = {
24 	{0, 0},	 {0, 780}, {1, 562}, {3, 120}, {6, 250}, {12, 500}, {25, 0},
25 	{50, 0}, {100, 0}, {200, 0}, {400, 0}, {800, 0}, {1600, 0}, {3200, 0},
26 };
27 
bmi08x_freq_to_odr_val(uint16_t freq_int,uint16_t freq_milli)28 int bmi08x_freq_to_odr_val(uint16_t freq_int, uint16_t freq_milli)
29 {
30 	size_t i;
31 
32 	/* An ODR of 0 Hz is not allowed */
33 	if (freq_int == 0U && freq_milli == 0U) {
34 		return -EINVAL;
35 	}
36 
37 	for (i = 0; i < ARRAY_SIZE(bmi08x_odr_map); i++) {
38 		if (freq_int < bmi08x_odr_map[i].freq_int ||
39 		    (freq_int == bmi08x_odr_map[i].freq_int &&
40 		     freq_milli <= bmi08x_odr_map[i].freq_milli)) {
41 			return i;
42 		}
43 	}
44 
45 	return -EINVAL;
46 }
47 
bmi08x_range_to_reg_val(uint16_t range,const struct bmi08x_range * range_map,uint16_t range_map_size)48 int32_t bmi08x_range_to_reg_val(uint16_t range, const struct bmi08x_range *range_map,
49 				       uint16_t range_map_size)
50 {
51 	int i;
52 
53 	for (i = 0; i < range_map_size; i++) {
54 		if (range <= range_map[i].range) {
55 			return range_map[i].reg_val;
56 		}
57 	}
58 
59 	return -EINVAL;
60 }
61 
bmi08x_reg_val_to_range(uint8_t reg_val,const struct bmi08x_range * range_map,uint16_t range_map_size)62 int32_t bmi08x_reg_val_to_range(uint8_t reg_val, const struct bmi08x_range *range_map,
63 				       uint16_t range_map_size)
64 {
65 	int i;
66 
67 	for (i = 0; i < range_map_size; i++) {
68 		if (reg_val == range_map[i].reg_val) {
69 			return range_map[i].range;
70 		}
71 	}
72 
73 	return -EINVAL;
74 }
75