1 /*
2 * Copyright (c) 2024 Analog Devices Inc.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "adxl367.h"
8 #include <zephyr/sys/byteorder.h>
9
10 #ifdef CONFIG_ADXL367_STREAM
11
12 #define ADXL367_COMPLEMENT 0xC000
13 /* Scale factor is the same for all ranges. */
14 /* (1.0 / sensor sensitivity) * (2^31 / 2^sensor shift ) * SENSOR_G / 1000000 */
15 #define SENSOR_QSCALE_FACTOR UINT32_C(164584)
16
17 /* (2^31 / 2^8(shift) */
18 #define ADXL367_TEMP_QSCALE 8388608
19 #define ADXL367_TEMP_SENSITIVITY 54 /* LSB/C */
20 #define ADXL367_TEMP_BIAS_TEST_CONDITION 25 /*C*/
21
22 static const uint32_t accel_period_ns[] = {
23 [ADXL367_ODR_12P5HZ] = UINT32_C(10000000000) / 125,
24 [ADXL367_ODR_25HZ] = UINT32_C(1000000000) / 25,
25 [ADXL367_ODR_50HZ] = UINT32_C(1000000000) / 50,
26 [ADXL367_ODR_100HZ] = UINT32_C(1000000000) / 100,
27 [ADXL367_ODR_200HZ] = UINT32_C(1000000000) / 200,
28 [ADXL367_ODR_400HZ] = UINT32_C(1000000000) / 400,
29 };
30
31 static const uint32_t range_to_shift[] = {
32 [ADXL367_2G_RANGE] = 5,
33 [ADXL367_4G_RANGE] = 6,
34 [ADXL367_8G_RANGE] = 7,
35 };
36
37 enum adxl367_12b_packet_start {
38 ADXL367_12B_PACKET_ALIGNED = 0,
39 ADXL367_12B_PACKET_NOT_ALIGNED = 1,
40 };
41
adxl367_temp_convert_q31(q31_t * out,const uint8_t * buff,const enum adxl367_fifo_read_mode read_mode,uint8_t sample_aligned)42 static inline void adxl367_temp_convert_q31(q31_t *out, const uint8_t *buff,
43 const enum adxl367_fifo_read_mode read_mode, uint8_t sample_aligned)
44 {
45 int16_t data_in;
46 unsigned int convert_value = 0;
47
48 switch (read_mode) {
49 case ADXL367_8B:
50 /* Because full resolution is 14b and this is 8 MSB bits. */
51 data_in = ((*((int8_t *)buff)) << 6) & 0x3FC0;
52 convert_value = 1;
53 break;
54
55 case ADXL367_12B:
56 /* Sample starts from the bit 4 of a first byte in buff. */
57 if (sample_aligned == 0) {
58 data_in = ((int16_t)(*buff & 0x0F) << 8) | *(buff + 1);
59 } else {
60 data_in = ((int16_t)(*buff) << 4) | (*(buff + 1) >> 4);
61 }
62 /* Because full resolution is 14b and this is 12 MSB bits. */
63 data_in = (data_in << 2) & 0x3FFC;
64 convert_value = 1;
65 break;
66
67 case ADXL367_12B_CHID:
68 data_in = sys_le16_to_cpu(*((int16_t *)(buff)));
69 if (ADXL367_FIFO_HDR_CHECK_TEMP(data_in)) {
70 /* Remove channel ID. */
71 data_in &= 0x3FFF;
72 /* Because full resolution is 14b and this is 12 MSB bits. */
73 data_in = (data_in << 2) & 0x3FFC;
74 convert_value = 1;
75 }
76 break;
77
78 case ADXL367_14B_CHID:
79 uint16_t *tmp_buf = (uint16_t *)buff;
80
81 data_in = (int16_t)(((*tmp_buf >> 8) & 0xFF) | ((*tmp_buf << 8) & 0xFF00));
82 if (ADXL367_FIFO_HDR_CHECK_TEMP(data_in)) {
83 /* Remove channel ID. */
84 data_in &= 0x3FFF;
85 convert_value = 1;
86 }
87 break;
88
89 default:
90 break;
91 }
92
93 if (convert_value) {
94 if (data_in & BIT(13)) {
95 data_in |= ADXL367_COMPLEMENT;
96 }
97
98 *out = ((data_in - ADXL367_TEMP_25C) / ADXL367_TEMP_SENSITIVITY
99 + ADXL367_TEMP_BIAS_TEST_CONDITION) * ADXL367_TEMP_QSCALE;
100 }
101 }
102
adxl367_accel_convert_q31(q31_t * out,const uint8_t * buff,const enum adxl367_fifo_read_mode read_mode,uint8_t axis,uint8_t sample_aligned)103 static inline void adxl367_accel_convert_q31(q31_t *out, const uint8_t *buff,
104 const enum adxl367_fifo_read_mode read_mode, uint8_t axis, uint8_t sample_aligned)
105 {
106 int16_t data_in;
107 unsigned int convert_value = 0;
108
109 switch (read_mode) {
110 case ADXL367_8B:
111 /* Because full resolution is 14b and this is 8 MSB bits. */
112 data_in = ((*((int8_t *)buff)) << 6) & 0x3FC0;
113 convert_value = 1;
114 break;
115
116 case ADXL367_12B:
117 /* Sample starts from the bit 4 of a first byte in buff. */
118 if (sample_aligned == 0) {
119 data_in = ((int16_t)(*buff & 0x0F) << 8) | *(buff + 1);
120 } else {
121 data_in = ((int16_t)(*buff) << 4) | (*(buff + 1) >> 4);
122 }
123 /* Because full resolution is 14b and this is 12 MSB bits. */
124 data_in = (data_in << 2) & 0x3FFC;
125 convert_value = 1;
126 break;
127
128 case ADXL367_12B_CHID:
129 data_in = sys_le16_to_cpu(*((int16_t *)(buff)));
130 if (ADXL367_FIFO_HDR_GET_ACCEL_AXIS(data_in) == axis) {
131 /* Remove channel ID. */
132 data_in &= 0x3FFF;
133 /* Because full resolution is 14b and this is 12 MSB bits. */
134 data_in = (data_in << 2) & 0x3FFC;
135 convert_value = 1;
136 }
137 break;
138
139 case ADXL367_14B_CHID:
140 uint16_t *tmp_buf = (uint16_t *)buff;
141
142 data_in = (int16_t)(((*tmp_buf >> 8) & 0xFF) | ((*tmp_buf << 8) & 0xFF00));
143 if (ADXL367_FIFO_HDR_GET_ACCEL_AXIS(data_in) == axis) {
144 /* Remove channel ID. */
145 data_in &= 0x3FFF;
146 convert_value = 1;
147 }
148 break;
149
150 default:
151 break;
152 }
153
154 if (convert_value) {
155 if (data_in & BIT(13)) {
156 data_in |= ADXL367_COMPLEMENT;
157 }
158
159 *out = data_in * SENSOR_QSCALE_FACTOR;
160 }
161 }
162
adxl367_get_accel(const struct adxl367_fifo_data * enc_data,struct sensor_three_axis_data * data,const uint8_t * buffer,int count,uint8_t sample_size,struct sensor_chan_spec chan_spec,uint64_t period_ns,uint8_t sample_num)163 static int adxl367_get_accel(const struct adxl367_fifo_data *enc_data,
164 struct sensor_three_axis_data *data, const uint8_t *buffer, int count,
165 uint8_t sample_size, struct sensor_chan_spec chan_spec,
166 uint64_t period_ns, uint8_t sample_num)
167 {
168 int ret = 0;
169
170 switch (chan_spec.chan_type) {
171 case SENSOR_CHAN_ACCEL_X:
172 if (enc_data->has_x) {
173 data->readings[count].timestamp_delta =
174 sample_num * period_ns;
175 adxl367_accel_convert_q31(&data->readings[count].x,
176 buffer, enc_data->fifo_read_mode,
177 ADXL367_X_AXIS, 1);
178 }
179 break;
180 case SENSOR_CHAN_ACCEL_Y:
181 if (enc_data->has_y) {
182 uint8_t buff_offset = 0;
183
184 /* If packet has X channel, then Y channel has offset. */
185 if (enc_data->has_x) {
186 buff_offset = sample_size;
187 }
188 data->readings[count].timestamp_delta = sample_num * period_ns;
189 adxl367_accel_convert_q31(&data->readings[count].y,
190 (buffer + buff_offset), enc_data->fifo_read_mode,
191 ADXL367_Y_AXIS, 1);
192 }
193 break;
194 case SENSOR_CHAN_ACCEL_Z:
195 if (enc_data->has_z) {
196 uint8_t buff_offset = 0;
197
198 /* If packet has X channel and/or Y channel,
199 * then Z channel has offset.
200 */
201
202 if (enc_data->has_x) {
203 buff_offset = sample_size;
204 }
205
206 if (enc_data->has_y) {
207 buff_offset += sample_size;
208 }
209 data->readings[count].timestamp_delta =
210 sample_num * period_ns;
211 adxl367_accel_convert_q31(&data->readings[count].z,
212 (buffer + buff_offset), enc_data->fifo_read_mode,
213 ADXL367_Z_AXIS, 1);
214 }
215 break;
216 case SENSOR_CHAN_ACCEL_XYZ:
217 data->readings[count].timestamp_delta =
218 sample_num * period_ns;
219 uint8_t buff_offset = 0;
220
221 if (enc_data->has_x) {
222 adxl367_accel_convert_q31(&data->readings[count].x,
223 buffer, enc_data->fifo_read_mode,
224 ADXL367_X_AXIS, 1);
225 buff_offset = sample_size;
226 }
227
228 if (enc_data->has_y) {
229 adxl367_accel_convert_q31(&data->readings[count].y,
230 (buffer + buff_offset), enc_data->fifo_read_mode,
231 ADXL367_Y_AXIS, 1);
232
233 buff_offset += sample_size;
234 }
235
236 if (enc_data->has_z) {
237 adxl367_accel_convert_q31(&data->readings[count].z,
238 (buffer + buff_offset), enc_data->fifo_read_mode,
239 ADXL367_Z_AXIS, 1);
240 }
241 break;
242
243 default:
244 ret = -ENOTSUP;
245 break;
246 }
247
248 return ret;
249 }
250
adxl367_get_12b_accel(const struct adxl367_fifo_data * enc_data,struct sensor_three_axis_data * data,const uint8_t * buffer,int count,uint8_t packet_size,struct sensor_chan_spec chan_spec,uint8_t packet_alignment,uint64_t period_ns,uint8_t sample_num)251 static int adxl367_get_12b_accel(const struct adxl367_fifo_data *enc_data,
252 struct sensor_three_axis_data *data, const uint8_t *buffer, int count,
253 uint8_t packet_size, struct sensor_chan_spec chan_spec, uint8_t packet_alignment,
254 uint64_t period_ns, uint8_t sample_num)
255 {
256 int ret = 0;
257 uint8_t sample_aligned = 1;
258 uint8_t buff_offset = 0;
259 uint8_t samples_before = 0;
260
261 switch (chan_spec.chan_type) {
262 case SENSOR_CHAN_ACCEL_X:
263 if (enc_data->has_x) {
264 if (packet_alignment == ADXL367_12B_PACKET_NOT_ALIGNED) {
265 sample_aligned = 0;
266 }
267
268 data->readings[count].timestamp_delta = sample_num * period_ns;
269 adxl367_accel_convert_q31(&data->readings[count].x,
270 buffer, enc_data->fifo_read_mode,
271 ADXL367_X_AXIS, sample_aligned);
272 }
273 break;
274 case SENSOR_CHAN_ACCEL_Y:
275 if (enc_data->has_y) {
276 buff_offset = 0;
277
278 /* If packet has X channel,
279 * then Y channel has offset.
280 */
281 if (enc_data->has_x) {
282 buff_offset = 2;
283 if (packet_alignment == ADXL367_12B_PACKET_ALIGNED) {
284 sample_aligned = 0;
285 buff_offset = 1;
286 }
287 }
288 data->readings[count].timestamp_delta = sample_num * period_ns;
289 adxl367_accel_convert_q31(&data->readings[count].y,
290 (buffer + buff_offset), enc_data->fifo_read_mode,
291 ADXL367_Y_AXIS, sample_aligned);
292 }
293 break;
294 case SENSOR_CHAN_ACCEL_Z:
295 if (enc_data->has_z) {
296 buff_offset = 0;
297 samples_before = 0;
298
299 /* If packet has X channel and/or Y channel,
300 * then Z channel has offset.
301 */
302 if (enc_data->has_x) {
303 samples_before++;
304 }
305
306 if (enc_data->has_y) {
307 samples_before++;
308 }
309
310 if (samples_before == 0) {
311 if (packet_alignment == ADXL367_12B_PACKET_NOT_ALIGNED) {
312 sample_aligned = 0;
313 }
314 } else {
315 buff_offset = (samples_before * 12) / 8;
316 if (samples_before == 1) {
317 if (packet_alignment == ADXL367_12B_PACKET_ALIGNED) {
318 sample_aligned = 0;
319 } else {
320 buff_offset++;
321 }
322 } else {
323 if (packet_alignment == ADXL367_12B_PACKET_NOT_ALIGNED) {
324 sample_aligned = 0;
325 }
326 }
327 }
328 data->readings[count].timestamp_delta = sample_num * period_ns;
329 adxl367_accel_convert_q31(&data->readings[count].z,
330 (buffer + buff_offset), enc_data->fifo_read_mode,
331 ADXL367_Z_AXIS, sample_aligned);
332 }
333 break;
334 case SENSOR_CHAN_ACCEL_XYZ:
335 data->readings[count].timestamp_delta = sample_num * period_ns;
336 buff_offset = 0;
337 samples_before = 0;
338
339 if (enc_data->has_x) {
340 if (packet_alignment == ADXL367_12B_PACKET_NOT_ALIGNED) {
341 sample_aligned = 0;
342 }
343 samples_before++;
344
345 adxl367_accel_convert_q31(&data->readings[count].x,
346 buffer, enc_data->fifo_read_mode, ADXL367_X_AXIS,
347 sample_aligned);
348 }
349
350 if (enc_data->has_y) {
351 if (samples_before) {
352 if (packet_alignment == ADXL367_12B_PACKET_ALIGNED) {
353 buff_offset = 1;
354 sample_aligned = 0;
355 } else {
356 buff_offset = 2;
357 sample_aligned = 1;
358 }
359 } else {
360 if (packet_alignment == ADXL367_12B_PACKET_NOT_ALIGNED) {
361 sample_aligned = 0;
362 buff_offset = 0;
363 }
364 }
365 samples_before++;
366
367 adxl367_accel_convert_q31(&data->readings[count].y,
368 (buffer + buff_offset), enc_data->fifo_read_mode,
369 ADXL367_Y_AXIS, sample_aligned);
370 }
371
372 if (enc_data->has_z) {
373 /* Z can have 2 samples in the packet before it or 0. */
374 if (samples_before) {
375 if (packet_alignment == ADXL367_12B_PACKET_ALIGNED) {
376 sample_aligned = 1;
377 } else {
378 sample_aligned = 0;
379 }
380 buff_offset = 3;
381 } else {
382 if (packet_alignment == ADXL367_12B_PACKET_NOT_ALIGNED) {
383 sample_aligned = 0;
384 buff_offset = 0;
385 }
386 }
387
388 adxl367_accel_convert_q31(&data->readings[count].z,
389 (buffer + buff_offset), enc_data->fifo_read_mode,
390 ADXL367_Z_AXIS, sample_aligned);
391 }
392 break;
393
394 default:
395 ret = -ENOTSUP;
396 break;
397 }
398
399 return ret;
400 }
401
adxl367_get_12b_temp(const struct adxl367_fifo_data * enc_data,struct sensor_q31_data * data,const uint8_t * buffer,int count,uint8_t packet_size)402 static void adxl367_get_12b_temp(const struct adxl367_fifo_data *enc_data,
403 struct sensor_q31_data *data, const uint8_t *buffer, int count, uint8_t packet_size)
404 {
405 if (enc_data->has_tmp) {
406 uint8_t offset = ((packet_size - 1) * 12) / 8;
407 uint8_t start_offset = ((packet_size - 1) * 12) % 8;
408 uint8_t sample_aligned = 1;
409
410 if (start_offset) {
411 sample_aligned = 0;
412 }
413
414 adxl367_temp_convert_q31(&data->readings[count].temperature,
415 (buffer + offset), enc_data->fifo_read_mode,
416 sample_aligned);
417 }
418 }
419
adxl367_decode_12b_stream(const uint8_t * buffer,struct sensor_chan_spec chan_spec,uint32_t * fit,uint16_t max_count,void * data_out,const struct adxl367_fifo_data * enc_data)420 static int adxl367_decode_12b_stream(const uint8_t *buffer, struct sensor_chan_spec chan_spec,
421 uint32_t *fit, uint16_t max_count, void *data_out,
422 const struct adxl367_fifo_data *enc_data)
423 {
424 const uint8_t *buffer_end =
425 buffer + sizeof(struct adxl367_fifo_data) + enc_data->fifo_byte_count;
426 uint8_t packet_size = enc_data->packet_size;
427 uint64_t period_ns = accel_period_ns[enc_data->accel_odr];
428 uint8_t sample_num = 0;
429 int count = 0;
430 uint8_t packet_alignment = ADXL367_12B_PACKET_ALIGNED;
431
432 while (count < max_count && buffer < buffer_end) {
433 const uint8_t *sample_end = buffer;
434
435 /* For ADXL367_12B mode packet_size is number of samples in one
436 * packet. If packet size is not aligned, sample_end will be on
437 * the byte that contains part of a last sample.
438 */
439 if (packet_alignment == ADXL367_12B_PACKET_ALIGNED) {
440 sample_end += (packet_size * 12) / 8;
441 } else {
442 sample_end += (packet_size * 12) / 8 + 1;
443 }
444
445 /* If fit is larger than buffer this frame was already decoded,
446 * move on to the next frame.
447 */
448 if ((uintptr_t)buffer < *fit) {
449 /* If number of samples in one packet is odd number,
450 * alignment changes for each packet.
451 */
452 if (enc_data->packet_size % 2) {
453 if (packet_alignment == ADXL367_12B_PACKET_ALIGNED) {
454 packet_alignment = ADXL367_12B_PACKET_NOT_ALIGNED;
455 } else {
456 packet_alignment = ADXL367_12B_PACKET_ALIGNED;
457 }
458 }
459
460 buffer = sample_end;
461
462 sample_num++;
463 continue;
464 }
465
466 if (chan_spec.chan_type == SENSOR_CHAN_DIE_TEMP) {
467 struct sensor_q31_data *data = (struct sensor_q31_data *)data_out;
468
469 memset(data, 0, sizeof(struct sensor_three_axis_data));
470 data->header.base_timestamp_ns = enc_data->timestamp;
471 data->header.reading_count = 1;
472 data->shift = 8;
473
474 data->readings[count].timestamp_delta =
475 period_ns * sample_num;
476
477 adxl367_get_12b_temp(enc_data, data, buffer, count, packet_size);
478 } else {
479 struct sensor_three_axis_data *data =
480 (struct sensor_three_axis_data *)data_out;
481
482 memset(data, 0, sizeof(struct sensor_three_axis_data));
483 data->header.base_timestamp_ns = enc_data->timestamp;
484 data->header.reading_count = 1;
485 data->shift = range_to_shift[enc_data->range];
486
487 int ret = adxl367_get_12b_accel(enc_data, data, buffer, count, packet_size,
488 chan_spec, packet_alignment, period_ns, sample_num);
489
490 if (ret != 0) {
491 return ret;
492 }
493 }
494
495 buffer = sample_end;
496 *fit = (uintptr_t)sample_end;
497 count++;
498 }
499
500 return count;
501 }
502
adxl367_decode_stream(const uint8_t * buffer,struct sensor_chan_spec chan_spec,uint32_t * fit,uint16_t max_count,void * data_out)503 static int adxl367_decode_stream(const uint8_t *buffer, struct sensor_chan_spec chan_spec,
504 uint32_t *fit, uint16_t max_count, void *data_out)
505 {
506 const struct adxl367_fifo_data *enc_data = (const struct adxl367_fifo_data *)buffer;
507 const uint8_t *buffer_end =
508 buffer + sizeof(struct adxl367_fifo_data) + enc_data->fifo_byte_count;
509 int count = 0;
510 uint8_t sample_num = 0;
511
512 if ((uintptr_t)buffer_end <= *fit || chan_spec.chan_idx != 0) {
513 return 0;
514 }
515
516 buffer += sizeof(struct adxl367_fifo_data);
517
518 uint8_t packet_size = enc_data->packet_size;
519 uint64_t period_ns = accel_period_ns[enc_data->accel_odr];
520 uint8_t sample_size = 2;
521
522 if (enc_data->fifo_read_mode == ADXL367_8B) {
523 sample_size = 1;
524 }
525
526 if (enc_data->fifo_read_mode == ADXL367_12B) {
527 count = adxl367_decode_12b_stream(buffer, chan_spec, fit, max_count,
528 data_out, enc_data);
529 } else {
530 /* Calculate which sample is decoded. */
531 if ((uint8_t *)*fit >= buffer) {
532 sample_num = ((uint8_t *)*fit - buffer) / packet_size;
533 }
534
535 while (count < max_count && buffer < buffer_end) {
536 const uint8_t *sample_end = buffer;
537
538 sample_end += packet_size;
539
540 if ((uintptr_t)buffer < *fit) {
541 /* This frame was already decoded, move on to the next frame */
542 buffer = sample_end;
543 continue;
544 }
545
546 if (chan_spec.chan_type == SENSOR_CHAN_DIE_TEMP) {
547 struct sensor_q31_data *data = (struct sensor_q31_data *)data_out;
548
549 memset(data, 0, sizeof(struct sensor_three_axis_data));
550 data->header.base_timestamp_ns = enc_data->timestamp;
551 data->header.reading_count = 1;
552 data->shift = 8;
553
554 data->readings[count].timestamp_delta =
555 period_ns * sample_num;
556
557 if (enc_data->has_tmp) {
558 uint8_t offset = (packet_size - 1) * sample_size;
559
560 adxl367_temp_convert_q31(&data->readings[count].temperature,
561 (buffer + offset), enc_data->fifo_read_mode, 1);
562 }
563 } else {
564 struct sensor_three_axis_data *data =
565 (struct sensor_three_axis_data *)data_out;
566
567 memset(data, 0, sizeof(struct sensor_three_axis_data));
568 data->header.base_timestamp_ns = enc_data->timestamp;
569 data->header.reading_count = 1;
570 data->shift = range_to_shift[enc_data->range];
571
572 int ret = adxl367_get_accel(enc_data, data, buffer, count,
573 sample_size, chan_spec,
574 period_ns, sample_num);
575
576 if (ret != 0) {
577 return ret;
578 }
579 }
580
581 buffer = sample_end;
582 *fit = (uintptr_t)sample_end;
583 count++;
584 }
585 }
586
587 return count;
588 }
589
adxl367_get_frame_count(const struct adxl367_fifo_data * data)590 uint16_t adxl367_get_frame_count(const struct adxl367_fifo_data *data)
591 {
592 uint16_t frame_count = 0;
593
594 if (data->fifo_read_mode == ADXL367_12B) {
595 frame_count = data->fifo_byte_count * 8 / (data->packet_size * 12);
596 } else {
597 frame_count = data->fifo_byte_count / data->packet_size;
598 }
599
600 return frame_count;
601 }
602
603 #endif /* CONFIG_ADXL367_STREAM */
604
adxl367_decoder_get_frame_count(const uint8_t * buffer,struct sensor_chan_spec chan_spec,uint16_t * frame_count)605 static int adxl367_decoder_get_frame_count(const uint8_t *buffer,
606 struct sensor_chan_spec chan_spec,
607 uint16_t *frame_count)
608 {
609 int32_t ret = -ENOTSUP;
610
611 if (chan_spec.chan_idx != 0) {
612 return ret;
613 }
614
615 #ifdef CONFIG_ADXL367_STREAM
616 const struct adxl367_fifo_data *data = (const struct adxl367_fifo_data *)buffer;
617
618 if (!data->is_fifo) {
619 #endif /* CONFIG_ADXL367_STREAM */
620 switch (chan_spec.chan_type) {
621 case SENSOR_CHAN_ACCEL_X:
622 case SENSOR_CHAN_ACCEL_Y:
623 case SENSOR_CHAN_ACCEL_Z:
624 case SENSOR_CHAN_ACCEL_XYZ:
625 *frame_count = 1;
626 ret = 0;
627 break;
628
629 default:
630 break;
631 }
632 #ifdef CONFIG_ADXL367_STREAM
633 } else {
634 if (data->fifo_byte_count == 0) {
635 *frame_count = 0;
636 ret = 0;
637 } else {
638 switch (chan_spec.chan_type) {
639 case SENSOR_CHAN_ACCEL_X:
640 if (data->has_x) {
641 *frame_count = adxl367_get_frame_count(data);
642 ret = 0;
643 }
644 break;
645
646 case SENSOR_CHAN_ACCEL_Y:
647 if (data->has_y) {
648 *frame_count = adxl367_get_frame_count(data);
649 ret = 0;
650 }
651 break;
652
653 case SENSOR_CHAN_ACCEL_Z:
654 if (data->has_z) {
655 *frame_count = adxl367_get_frame_count(data);
656 ret = 0;
657 }
658 break;
659
660 case SENSOR_CHAN_ACCEL_XYZ:
661 if (data->has_x || data->has_y || data->has_z) {
662 *frame_count = adxl367_get_frame_count(data);
663 ret = 0;
664 }
665 break;
666
667 case SENSOR_CHAN_DIE_TEMP:
668 if (data->has_tmp) {
669 *frame_count = adxl367_get_frame_count(data);
670 ret = 0;
671 break;
672 }
673 break;
674
675 default:
676 break;
677 }
678 }
679 }
680 #endif /* CONFIG_ADXL367_STREAM */
681
682 return ret;
683 }
684
adxl367_decode_sample(const struct adxl367_sample_data * data,struct sensor_chan_spec chan_spec,uint32_t * fit,uint16_t max_count,void * data_out)685 static int adxl367_decode_sample(const struct adxl367_sample_data *data,
686 struct sensor_chan_spec chan_spec, uint32_t *fit, uint16_t max_count, void *data_out)
687 {
688 struct sensor_value *out = (struct sensor_value *) data_out;
689
690 if (*fit > 0) {
691 return -ENOTSUP;
692 }
693
694 switch (chan_spec.chan_type) {
695 case SENSOR_CHAN_ACCEL_X: /* Acceleration on the X axis, in m/s^2. */
696 adxl367_accel_convert(out, data->xyz.x, data->xyz.range);
697 break;
698 case SENSOR_CHAN_ACCEL_Y: /* Acceleration on the Y axis, in m/s^2. */
699 adxl367_accel_convert(out, data->xyz.y, data->xyz.range);
700 break;
701 case SENSOR_CHAN_ACCEL_Z: /* Acceleration on the Z axis, in m/s^2. */
702 adxl367_accel_convert(out, data->xyz.z, data->xyz.range);
703 break;
704 case SENSOR_CHAN_ACCEL_XYZ: /* Acceleration on the XYZ axis, in m/s^2. */
705 adxl367_accel_convert(out++, data->xyz.x, data->xyz.range);
706 adxl367_accel_convert(out++, data->xyz.y, data->xyz.range);
707 adxl367_accel_convert(out, data->xyz.z, data->xyz.range);
708 break;
709 case SENSOR_CHAN_DIE_TEMP: /* Temperature in degrees Celsius. */
710 adxl367_temp_convert(out, data->raw_temp);
711 break;
712 default:
713 return -ENOTSUP;
714 }
715
716 *fit = 1;
717
718 return 0;
719 }
720
adxl367_decoder_decode(const uint8_t * buffer,struct sensor_chan_spec chan_spec,uint32_t * fit,uint16_t max_count,void * data_out)721 static int adxl367_decoder_decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec,
722 uint32_t *fit, uint16_t max_count, void *data_out)
723 {
724 const struct adxl367_sample_data *data = (const struct adxl367_sample_data *)buffer;
725
726 #ifdef CONFIG_ADXL367_STREAM
727 if (data->is_fifo) {
728 return adxl367_decode_stream(buffer, chan_spec, fit, max_count, data_out);
729 }
730 #endif /* CONFIG_ADXL367_STREAM */
731
732 return adxl367_decode_sample(data, chan_spec, fit, max_count, data_out);
733 }
734
adxl367_decoder_has_trigger(const uint8_t * buffer,enum sensor_trigger_type trigger)735 static bool adxl367_decoder_has_trigger(const uint8_t *buffer, enum sensor_trigger_type trigger)
736 {
737 const struct adxl367_fifo_data *data = (const struct adxl367_fifo_data *)buffer;
738
739 if (!data->is_fifo) {
740 return false;
741 }
742
743 switch (trigger) {
744 case SENSOR_TRIG_DATA_READY:
745 return (ADXL367_STATUS_DATA_RDY & data->int_status);
746 case SENSOR_TRIG_FIFO_WATERMARK:
747 return (ADXL367_STATUS_FIFO_WATERMARK & data->int_status);
748 case SENSOR_TRIG_FIFO_FULL:
749 return (ADXL367_STATUS_FIFO_WATERMARK & data->int_status);
750 default:
751 return false;
752 }
753 }
754
755 SENSOR_DECODER_API_DT_DEFINE() = {
756 .get_frame_count = adxl367_decoder_get_frame_count,
757 .decode = adxl367_decoder_decode,
758 .has_trigger = adxl367_decoder_has_trigger,
759 };
760
adxl367_get_decoder(const struct device * dev,const struct sensor_decoder_api ** decoder)761 int adxl367_get_decoder(const struct device *dev, const struct sensor_decoder_api **decoder)
762 {
763 ARG_UNUSED(dev);
764 *decoder = &SENSOR_DECODER_NAME();
765
766 return 0;
767 }
768