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