1 /*
2 * Copyright (c) 2024 Analog Devices Inc.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "adxl345.h"
8
9 #ifdef CONFIG_ADXL345_STREAM
10
11 #define SENSOR_SCALING_FACTOR (SENSOR_G / (16 * 1000 / 100))
12
13 static const uint32_t accel_period_ns[] = {
14 [ADXL345_ODR_12HZ] = UINT32_C(1000000000) / 12,
15 [ADXL345_ODR_25HZ] = UINT32_C(1000000000) / 25,
16 [ADXL345_ODR_50HZ] = UINT32_C(1000000000) / 50,
17 [ADXL345_ODR_100HZ] = UINT32_C(1000000000) / 100,
18 [ADXL345_ODR_200HZ] = UINT32_C(1000000000) / 200,
19 [ADXL345_ODR_400HZ] = UINT32_C(1000000000) / 400,
20 };
21
22 static const uint32_t range_to_shift[] = {
23 [ADXL345_RANGE_2G] = 5,
24 [ADXL345_RANGE_4G] = 6,
25 [ADXL345_RANGE_8G] = 7,
26 [ADXL345_RANGE_16G] = 8,
27 };
28
29 /* (1 / sensitivity) * (pow(2,31) / pow(2,shift)) * (unit_scaler) */
30 static const uint32_t qscale_factor_no_full_res[] = {
31 /* (1.0 / ADXL362_ACCEL_2G_LSB_PER_G) * (2^31 / 2^5) * SENSOR_G / 1000000 */
32 [ADXL345_RANGE_2G] = UINT32_C(2569011),
33 /* (1.0 / ADXL362_ACCEL_4G_LSB_PER_G) * (2^31 / 2^6) * SENSOR_G / 1000000 */
34 [ADXL345_RANGE_4G] = UINT32_C(642253),
35 /* (1.0 / ADXL362_ACCEL_8G_LSB_PER_G) * (2^31 / 2^7) ) * SENSOR_G / 1000000 */
36 [ADXL345_RANGE_8G] = UINT32_C(160563),
37 /* (1.0 / ADXL362_ACCEL_8G_LSB_PER_G) * (2^31 / 2^8) ) * SENSOR_G / 1000000 */
38 [ADXL345_RANGE_16G] = UINT32_C(40141),
39 };
40
41 /* (1 / sensitivity) * (pow(2,31) / pow(2,shift)) * (unit_scaler) */
42 static const uint32_t qscale_factor_full_res[] = {
43 /* (1.0 / ADXL362_ACCEL_2G_LSB_PER_G) * (2^31 / 2^5) * SENSOR_G / 1000000 */
44 [ADXL345_RANGE_2G] = UINT32_C(2569011),
45 /* (1.0 / ADXL362_ACCEL_4G_LSB_PER_G) * (2^31 / 2^6) * SENSOR_G / 1000000 */
46 [ADXL345_RANGE_4G] = UINT32_C(1284506),
47 /* (1.0 / ADXL362_ACCEL_8G_LSB_PER_G) * (2^31 / 2^7) ) * SENSOR_G / 1000000 */
48 [ADXL345_RANGE_8G] = UINT32_C(642253),
49 /* (1.0 / ADXL362_ACCEL_8G_LSB_PER_G) * (2^31 / 2^8) ) * SENSOR_G / 1000000 */
50 [ADXL345_RANGE_16G] = UINT32_C(321126),
51 };
52
adxl345_accel_convert_q31(q31_t * out,int16_t sample,int32_t range,uint8_t is_full_res)53 static inline void adxl345_accel_convert_q31(q31_t *out, int16_t sample, int32_t range,
54 uint8_t is_full_res)
55 {
56 if (is_full_res) {
57 switch (range) {
58 case ADXL345_RANGE_2G:
59 if (sample & BIT(9)) {
60 sample |= ADXL345_COMPLEMENT_MASK(10);
61 }
62 break;
63 case ADXL345_RANGE_4G:
64 if (sample & BIT(10)) {
65 sample |= ADXL345_COMPLEMENT_MASK(11);
66 }
67 break;
68 case ADXL345_RANGE_8G:
69 if (sample & BIT(11)) {
70 sample |= ADXL345_COMPLEMENT_MASK(12);
71 }
72 break;
73 case ADXL345_RANGE_16G:
74 if (sample & BIT(12)) {
75 sample |= ADXL345_COMPLEMENT_MASK(13);
76 }
77 break;
78 }
79 } else {
80 if (sample & BIT(9)) {
81 sample |= ADXL345_COMPLEMENT;
82 }
83 }
84
85 *out = sample * qscale_factor_no_full_res[range];
86 }
87
adxl345_decode_stream(const uint8_t * buffer,struct sensor_chan_spec chan_spec,uint32_t * fit,uint16_t max_count,void * data_out)88 static int adxl345_decode_stream(const uint8_t *buffer, struct sensor_chan_spec chan_spec,
89 uint32_t *fit, uint16_t max_count, void *data_out)
90 {
91 const struct adxl345_fifo_data *enc_data = (const struct adxl345_fifo_data *)buffer;
92 const uint8_t *buffer_end =
93 buffer + sizeof(struct adxl345_fifo_data) + enc_data->fifo_byte_count;
94 int count = 0;
95 uint8_t sample_num = 0;
96
97 if ((uintptr_t)buffer_end <= *fit || chan_spec.chan_idx != 0) {
98 return 0;
99 }
100
101 struct sensor_three_axis_data *data = (struct sensor_three_axis_data *)data_out;
102
103 memset(data, 0, sizeof(struct sensor_three_axis_data));
104 data->header.base_timestamp_ns = enc_data->timestamp;
105 data->header.reading_count = 1;
106 data->shift = range_to_shift[enc_data->selected_range];
107
108 buffer += sizeof(struct adxl345_fifo_data);
109
110 uint8_t sample_set_size = enc_data->sample_set_size;
111 uint64_t period_ns = accel_period_ns[enc_data->accel_odr];
112 uint8_t is_full_res = enc_data->is_full_res;
113
114 /* Calculate which sample is decoded. */
115 if ((uint8_t *)*fit >= buffer) {
116 sample_num = ((uint8_t *)*fit - buffer) / sample_set_size;
117 }
118
119 while (count < max_count && buffer < buffer_end) {
120 const uint8_t *sample_end = buffer;
121
122 sample_end += sample_set_size;
123
124 if ((uintptr_t)buffer < *fit) {
125 /* This frame was already decoded, move on to the next frame */
126 buffer = sample_end;
127 continue;
128 }
129
130 switch (chan_spec.chan_type) {
131 case SENSOR_CHAN_ACCEL_XYZ:
132 data->readings[count].timestamp_delta = sample_num * period_ns;
133 uint8_t buff_offset = 0;
134
135 adxl345_accel_convert_q31(&data->readings[count].x, *(int16_t *)buffer,
136 enc_data->selected_range, is_full_res);
137 buff_offset = 2;
138 adxl345_accel_convert_q31(&data->readings[count].y,
139 *(int16_t *)(buffer + buff_offset),
140 enc_data->selected_range, is_full_res);
141 buff_offset += 2;
142 adxl345_accel_convert_q31(&data->readings[count].z,
143 *(int16_t *)(buffer + buff_offset),
144 enc_data->selected_range, is_full_res);
145 break;
146 default:
147 return -ENOTSUP;
148 }
149 buffer = sample_end;
150 *fit = (uintptr_t)sample_end;
151 count++;
152 }
153 return count;
154 }
155
156 #endif /* CONFIG_ADXL345_STREAM */
157
adxl345_decoder_get_frame_count(const uint8_t * buffer,struct sensor_chan_spec chan_spec,uint16_t * frame_count)158 static int adxl345_decoder_get_frame_count(const uint8_t *buffer, struct sensor_chan_spec chan_spec,
159 uint16_t *frame_count)
160 {
161 int32_t ret = -ENOTSUP;
162
163 if (chan_spec.chan_idx != 0) {
164 return ret;
165 }
166
167 #ifdef CONFIG_ADXL345_STREAM
168 const struct adxl345_fifo_data *data = (const struct adxl345_fifo_data *)buffer;
169
170 if (!data->is_fifo) {
171 #endif /* CONFIG_ADXL345_STREAM */
172 switch (chan_spec.chan_type) {
173 case SENSOR_CHAN_ACCEL_X:
174 case SENSOR_CHAN_ACCEL_Y:
175 case SENSOR_CHAN_ACCEL_Z:
176 case SENSOR_CHAN_ACCEL_XYZ:
177 *frame_count = 1;
178 ret = 0;
179 break;
180
181 default:
182 break;
183 }
184 #ifdef CONFIG_ADXL345_STREAM
185 } else {
186 if (data->fifo_byte_count == 0) {
187 *frame_count = 0;
188 ret = 0;
189 } else {
190 switch (chan_spec.chan_type) {
191 case SENSOR_CHAN_ACCEL_XYZ:
192 *frame_count =
193 data->fifo_byte_count / data->sample_set_size;
194 ret = 0;
195 break;
196
197 default:
198 break;
199 }
200 }
201 }
202 #endif /* CONFIG_ADXL345_STREAM */
203
204 return ret;
205 }
206
adxl345_decode_sample(const struct adxl345_sample * data,struct sensor_chan_spec chan_spec,uint32_t * fit,uint16_t max_count,void * data_out)207 static int adxl345_decode_sample(const struct adxl345_sample *data,
208 struct sensor_chan_spec chan_spec, uint32_t *fit,
209 uint16_t max_count, void *data_out)
210 {
211 struct sensor_value *out = (struct sensor_value *)data_out;
212
213 if (*fit > 0) {
214 return -ENOTSUP;
215 }
216
217 switch (chan_spec.chan_type) {
218 case SENSOR_CHAN_ACCEL_XYZ:
219 adxl345_accel_convert(out++, data->x);
220 adxl345_accel_convert(out++, data->y);
221 adxl345_accel_convert(out, data->z);
222 break;
223 default:
224 return -ENOTSUP;
225 }
226
227 *fit = 1;
228
229 return 0;
230 }
231
adxl345_decoder_decode(const uint8_t * buffer,struct sensor_chan_spec chan_spec,uint32_t * fit,uint16_t max_count,void * data_out)232 static int adxl345_decoder_decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec,
233 uint32_t *fit, uint16_t max_count, void *data_out)
234 {
235 const struct adxl345_sample *data = (const struct adxl345_sample *)buffer;
236
237 #ifdef CONFIG_ADXL345_STREAM
238 if (data->is_fifo) {
239 return adxl345_decode_stream(buffer, chan_spec, fit, max_count, data_out);
240 }
241 #endif /* CONFIG_ADXL345_STREAM */
242
243 return adxl345_decode_sample(data, chan_spec, fit, max_count, data_out);
244 }
245
adxl345_decoder_has_trigger(const uint8_t * buffer,enum sensor_trigger_type trigger)246 static bool adxl345_decoder_has_trigger(const uint8_t *buffer, enum sensor_trigger_type trigger)
247 {
248 const struct adxl345_fifo_data *data = (const struct adxl345_fifo_data *)buffer;
249
250 if (!data->is_fifo) {
251 return false;
252 }
253
254 switch (trigger) {
255 case SENSOR_TRIG_FIFO_WATERMARK:
256 return FIELD_GET(ADXL345_INT_MAP_WATERMARK_MSK, data->int_status);
257 default:
258 return false;
259 }
260 }
261
262 SENSOR_DECODER_API_DT_DEFINE() = {
263 .get_frame_count = adxl345_decoder_get_frame_count,
264 .decode = adxl345_decoder_decode,
265 .has_trigger = adxl345_decoder_has_trigger,
266 };
267
adxl345_get_decoder(const struct device * dev,const struct sensor_decoder_api ** decoder)268 int adxl345_get_decoder(const struct device *dev, const struct sensor_decoder_api **decoder)
269 {
270 ARG_UNUSED(dev);
271 *decoder = &SENSOR_DECODER_NAME();
272
273 return 0;
274 }
275