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