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 		return 0;
59 	case SENSOR_CHAN_MAGN_XYZ:
60 		*base_size = sizeof(struct sensor_three_axis_data);
61 		*frame_size = sizeof(struct sensor_three_axis_sample_data);
62 		return 0;
63 	default:
64 		return -ENOTSUP;
65 	}
66 }
67 
mmc56x3_decoder_decode(const uint8_t * buffer,struct sensor_chan_spec chan_spec,uint32_t * fit,uint16_t max_count,void * data_out)68 static int mmc56x3_decoder_decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec,
69 				  uint32_t *fit, uint16_t max_count, void *data_out)
70 {
71 	const struct mmc56x3_encoded_data *edata = (const struct mmc56x3_encoded_data *)buffer;
72 	const struct mmc56x3_data *data = &edata->data;
73 
74 	if (*fit != 0) {
75 		return 0;
76 	}
77 
78 	switch (chan_spec.chan_type) {
79 	case SENSOR_CHAN_AMBIENT_TEMP:
80 		if (edata->has_temp) {
81 			struct sensor_q31_data *out = data_out;
82 
83 			out->header.base_timestamp_ns = edata->header.timestamp;
84 			out->header.reading_count = 1;
85 			out->readings[0].temperature = MMC56X3_TEMP_CONV_Q7_24_BASE +
86 						       data->temp * MMC56X3_TEMP_CONV_Q7_24_RES;
87 			out->shift = MMC56X3_TEMP_SHIFT;
88 		} else {
89 			return -ENODATA;
90 		}
91 		break;
92 	case SENSOR_CHAN_MAGN_X:
93 		if (edata->has_magn_x) {
94 			struct sensor_q31_data *out = data_out;
95 
96 			out->header.base_timestamp_ns = edata->header.timestamp;
97 			out->header.reading_count = 1;
98 			out->readings[0].value = data->magn_x * MMC56X3_MAGN_CONV_Q5_26_20B;
99 			out->shift = MMC56X3_MAGN_SHIFT;
100 		} else {
101 			return -ENODATA;
102 		}
103 		break;
104 	case SENSOR_CHAN_MAGN_Y:
105 		if (edata->has_magn_y) {
106 			struct sensor_q31_data *out = data_out;
107 
108 			out->header.base_timestamp_ns = edata->header.timestamp;
109 			out->header.reading_count = 1;
110 			out->readings[0].value = data->magn_y * MMC56X3_MAGN_CONV_Q5_26_20B;
111 			out->shift = MMC56X3_MAGN_SHIFT;
112 		} else {
113 			return -ENODATA;
114 		}
115 		break;
116 	case SENSOR_CHAN_MAGN_Z:
117 		if (edata->has_magn_z) {
118 			struct sensor_q31_data *out = data_out;
119 
120 			out->header.base_timestamp_ns = edata->header.timestamp;
121 			out->header.reading_count = 1;
122 			out->readings[0].value = data->magn_z * MMC56X3_MAGN_CONV_Q5_26_20B;
123 			out->shift = MMC56X3_MAGN_SHIFT;
124 		} else {
125 			return -ENODATA;
126 		}
127 		break;
128 	case SENSOR_CHAN_MAGN_XYZ: {
129 		if (edata->has_magn_x && edata->has_magn_y && edata->has_magn_z) {
130 			struct sensor_three_axis_data *out_3 = data_out;
131 
132 			out_3->header.base_timestamp_ns = edata->header.timestamp;
133 			out_3->header.reading_count = 1;
134 			out_3->shift = MMC56X3_MAGN_SHIFT;
135 
136 			out_3->readings[0].v[0] = data->magn_x * MMC56X3_MAGN_CONV_Q5_26_20B;
137 			out_3->readings[0].v[1] = data->magn_y * MMC56X3_MAGN_CONV_Q5_26_20B;
138 			out_3->readings[0].v[2] = data->magn_z * MMC56X3_MAGN_CONV_Q5_26_20B;
139 		} else {
140 			return -ENODATA;
141 		}
142 		break;
143 	}
144 	default:
145 		return -EINVAL;
146 	}
147 
148 	*fit = 1;
149 	return 1;
150 }
151 
152 SENSOR_DECODER_API_DT_DEFINE() = {
153 	.get_frame_count = mmc56x3_decoder_get_frame_count,
154 	.get_size_info = mmc56x3_decoder_get_size_info,
155 	.decode = mmc56x3_decoder_decode,
156 };
157 
mmc56x3_get_decoder(const struct device * dev,const struct sensor_decoder_api ** decoder)158 int mmc56x3_get_decoder(const struct device *dev, const struct sensor_decoder_api **decoder)
159 {
160 	ARG_UNUSED(dev);
161 	*decoder = &SENSOR_DECODER_NAME();
162 
163 	return 0;
164 }
165