1 /*
2  * Copyright (c) 2024 Intel Corporation
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #include "mmc56x3.h"
7 #include <math.h>
8 
mmc56x3_decoder_get_frame_count(const uint8_t * buffer,struct sensor_chan_spec chan_spec,uint16_t * frame_count)9 static int mmc56x3_decoder_get_frame_count(const uint8_t *buffer, struct sensor_chan_spec chan_spec,
10 					   uint16_t *frame_count)
11 {
12 	const struct mmc56x3_encoded_data *edata = (const struct mmc56x3_encoded_data *)buffer;
13 	int32_t ret = -ENOTSUP;
14 
15 	if (chan_spec.chan_idx != 0) {
16 		return ret;
17 	}
18 
19 	/* This sensor lacks a FIFO; there will always only be one frame at a time. */
20 	switch (chan_spec.chan_type) {
21 	case SENSOR_CHAN_AMBIENT_TEMP:
22 		*frame_count = edata->has_temp ? 1 : 0;
23 		break;
24 	case SENSOR_CHAN_MAGN_X:
25 		*frame_count = edata->has_magn_x ? 1 : 0;
26 		break;
27 	case SENSOR_CHAN_MAGN_Y:
28 		*frame_count = edata->has_magn_y ? 1 : 0;
29 		break;
30 	case SENSOR_CHAN_MAGN_Z:
31 		*frame_count = edata->has_magn_z ? 1 : 0;
32 		break;
33 	case SENSOR_CHAN_MAGN_XYZ:
34 		*frame_count =
35 			((edata->has_magn_x && edata->has_magn_y && edata->has_magn_z) ? 1 : 0);
36 		break;
37 	default:
38 		return ret;
39 	}
40 
41 	if (*frame_count > 0) {
42 		ret = 0;
43 	}
44 
45 	return ret;
46 }
47 
mmc56x3_decoder_get_size_info(struct sensor_chan_spec chan_spec,size_t * base_size,size_t * frame_size)48 static int mmc56x3_decoder_get_size_info(struct sensor_chan_spec chan_spec, size_t *base_size,
49 					 size_t *frame_size)
50 {
51 	switch (chan_spec.chan_type) {
52 	case SENSOR_CHAN_AMBIENT_TEMP:
53 	case SENSOR_CHAN_MAGN_X:
54 	case SENSOR_CHAN_MAGN_Y:
55 	case SENSOR_CHAN_MAGN_Z:
56 		*base_size = sizeof(struct sensor_q31_sample_data);
57 		*frame_size = sizeof(struct sensor_q31_sample_data);
58 	case SENSOR_CHAN_MAGN_XYZ:
59 		*base_size = sizeof(struct sensor_three_axis_data);
60 		*frame_size = sizeof(struct sensor_three_axis_sample_data);
61 		return 0;
62 	default:
63 		return -ENOTSUP;
64 	}
65 }
66 
mmc56x3_decoder_decode(const uint8_t * buffer,struct sensor_chan_spec chan_spec,uint32_t * fit,uint16_t max_count,void * data_out)67 static int mmc56x3_decoder_decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec,
68 				  uint32_t *fit, uint16_t max_count, void *data_out)
69 {
70 	const struct mmc56x3_encoded_data *edata = (const struct mmc56x3_encoded_data *)buffer;
71 	const struct mmc56x3_data *data = &edata->data;
72 
73 	if (*fit != 0) {
74 		return 0;
75 	}
76 
77 	switch (chan_spec.chan_type) {
78 	case SENSOR_CHAN_AMBIENT_TEMP:
79 		if (edata->has_temp) {
80 			struct sensor_q31_data *out = data_out;
81 
82 			out->header.base_timestamp_ns = edata->header.timestamp;
83 			out->header.reading_count = 1;
84 			out->readings[0].temperature = MMC56X3_TEMP_CONV_Q7_24_BASE +
85 						       data->temp * MMC56X3_TEMP_CONV_Q7_24_RES;
86 			out->shift = MMC56X3_TEMP_SHIFT;
87 		} else {
88 			return -ENODATA;
89 		}
90 		break;
91 	case SENSOR_CHAN_MAGN_X:
92 		if (edata->has_magn_x) {
93 			struct sensor_q31_data *out = data_out;
94 
95 			out->header.base_timestamp_ns = edata->header.timestamp;
96 			out->header.reading_count = 1;
97 			out->readings[0].value = data->magn_x * MMC56X3_MAGN_CONV_Q5_26_20B;
98 			out->shift = MMC56X3_MAGN_SHIFT;
99 		} else {
100 			return -ENODATA;
101 		}
102 		break;
103 	case SENSOR_CHAN_MAGN_Y:
104 		if (edata->has_magn_y) {
105 			struct sensor_q31_data *out = data_out;
106 
107 			out->header.base_timestamp_ns = edata->header.timestamp;
108 			out->header.reading_count = 1;
109 			out->readings[0].value = data->magn_y * MMC56X3_MAGN_CONV_Q5_26_20B;
110 			out->shift = MMC56X3_MAGN_SHIFT;
111 		} else {
112 			return -ENODATA;
113 		}
114 		break;
115 	case SENSOR_CHAN_MAGN_Z:
116 		if (edata->has_magn_z) {
117 			struct sensor_q31_data *out = data_out;
118 
119 			out->header.base_timestamp_ns = edata->header.timestamp;
120 			out->header.reading_count = 1;
121 			out->readings[0].value = data->magn_z * MMC56X3_MAGN_CONV_Q5_26_20B;
122 			out->shift = MMC56X3_MAGN_SHIFT;
123 		} else {
124 			return -ENODATA;
125 		}
126 		break;
127 	case SENSOR_CHAN_MAGN_XYZ: {
128 		if (edata->has_magn_x && edata->has_magn_y && edata->has_magn_z) {
129 			struct sensor_three_axis_data *out_3 = data_out;
130 
131 			out_3->header.base_timestamp_ns = edata->header.timestamp;
132 			out_3->header.reading_count = 1;
133 			out_3->shift = MMC56X3_MAGN_SHIFT;
134 
135 			out_3->readings[0].v[0] = data->magn_x * MMC56X3_MAGN_CONV_Q5_26_20B;
136 			out_3->readings[0].v[1] = data->magn_y * MMC56X3_MAGN_CONV_Q5_26_20B;
137 			out_3->readings[0].v[2] = data->magn_z * MMC56X3_MAGN_CONV_Q5_26_20B;
138 		} else {
139 			return -ENODATA;
140 		}
141 		break;
142 	}
143 	default:
144 		return -EINVAL;
145 	}
146 
147 	*fit = 1;
148 	return 1;
149 }
150 
151 SENSOR_DECODER_API_DT_DEFINE() = {
152 	.get_frame_count = mmc56x3_decoder_get_frame_count,
153 	.get_size_info = mmc56x3_decoder_get_size_info,
154 	.decode = mmc56x3_decoder_decode,
155 };
156 
mmc56x3_get_decoder(const struct device * dev,const struct sensor_decoder_api ** decoder)157 int mmc56x3_get_decoder(const struct device *dev, const struct sensor_decoder_api **decoder)
158 {
159 	ARG_UNUSED(dev);
160 	*decoder = &SENSOR_DECODER_NAME();
161 
162 	return 0;
163 }
164