1 /*
2  * Copyright (c) 2024 Analog Devices Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "adxl345.h"
8 
9 /** The q-scale factor will always be the same, as the nominal LSB/g
10  * changes at the same rate the selected shift parameter per range:
11  *
12  * - At 2G: 256 LSB/g, 10-bits resolution.
13  * - At 4g: 128 LSB/g, 10-bits resolution.
14  * - At 8g: 64 LSB/g, 10-bits resolution.
15  * - At 16g 32 LSB/g, 10-bits resolution.
16  */
17 static const uint32_t qscale_factor_no_full_res[] = {
18 	/* (1.0 / Resolution-LSB-per-g * (2^31 / 2^5) * SENSOR_G / 1000000 */
19 	[ADXL345_RANGE_2G] = UINT32_C(2570754),
20 	/* (1.0 / Resolution-LSB-per-g) * (2^31 / 2^6) * SENSOR_G / 1000000  */
21 	[ADXL345_RANGE_4G] = UINT32_C(2570754),
22 	/* (1.0 / Resolution-LSB-per-g) * (2^31 / 2^7) ) * SENSOR_G / 1000000 */
23 	[ADXL345_RANGE_8G] = UINT32_C(2570754),
24 	/* (1.0 / Resolution-LSB-per-g) * (2^31 / 2^8) ) * SENSOR_G / 1000000 */
25 	[ADXL345_RANGE_16G] = UINT32_C(2570754),
26 };
27 
28 
29 /** Sensitivities based on Range:
30  *
31  * - At 2G: 256 LSB/g, 10-bits resolution.
32  * - At 4g: 256 LSB/g, 11-bits resolution.
33  * - At 8g: 256 LSB/g, 12-bits resolution.
34  * - At 16g 256 LSB/g, 13-bits resolution.
35  */
36 static const uint32_t qscale_factor_full_res[] = {
37 	/* (1.0 / Resolution-LSB-per-g) * (2^31 / 2^5) * SENSOR_G / 1000000 */
38 	[ADXL345_RANGE_2G] = UINT32_C(2570754),
39 	/* (1.0 / Resolution-LSB-per-g) * (2^31 / 2^6) * SENSOR_G / 1000000  */
40 	[ADXL345_RANGE_4G] = UINT32_C(1285377),
41 	/* (1.0 / Resolution-LSB-per-g) * (2^31 / 2^7) ) * SENSOR_G / 1000000 */
42 	[ADXL345_RANGE_8G] = UINT32_C(642688),
43 	/* (1.0 / Resolution-LSB-per-g) * (2^31 / 2^8) ) * SENSOR_G / 1000000 */
44 	[ADXL345_RANGE_16G] = UINT32_C(321344),
45 };
46 
47 static const uint32_t range_to_shift[] = {
48 	[ADXL345_RANGE_2G] = 5,
49 	[ADXL345_RANGE_4G] = 6,
50 	[ADXL345_RANGE_8G] = 7,
51 	[ADXL345_RANGE_16G] = 8,
52 };
53 
adxl345_accel_convert_q31(q31_t * out,int16_t sample,int32_t range,uint8_t is_full_res)54 static inline void adxl345_accel_convert_q31(q31_t *out, int16_t sample, int32_t range,
55 					uint8_t is_full_res)
56 {
57 	if (is_full_res) {
58 		switch (range) {
59 		case ADXL345_RANGE_2G:
60 			if (sample & BIT(9)) {
61 				sample |= ADXL345_COMPLEMENT_MASK(10);
62 			}
63 			break;
64 		case ADXL345_RANGE_4G:
65 			if (sample & BIT(10)) {
66 				sample |= ADXL345_COMPLEMENT_MASK(11);
67 			}
68 			break;
69 		case ADXL345_RANGE_8G:
70 			if (sample & BIT(11)) {
71 				sample |= ADXL345_COMPLEMENT_MASK(12);
72 			}
73 			break;
74 		case ADXL345_RANGE_16G:
75 			if (sample & BIT(12)) {
76 				sample |= ADXL345_COMPLEMENT_MASK(13);
77 			}
78 			break;
79 		}
80 		*out = sample * qscale_factor_full_res[range];
81 	} else {
82 		if (sample & BIT(9)) {
83 			sample |= ADXL345_COMPLEMENT;
84 		}
85 		*out = sample * qscale_factor_no_full_res[range];
86 	}
87 }
88 
89 #ifdef CONFIG_ADXL345_STREAM
90 
91 #define SENSOR_SCALING_FACTOR (SENSOR_G / (16 * 1000 / 100))
92 
93 static const uint32_t accel_period_ns[] = {
94 	[ADXL345_ODR_12HZ] = UINT32_C(1000000000) / 12,
95 	[ADXL345_ODR_25HZ] = UINT32_C(1000000000) / 25,
96 	[ADXL345_ODR_50HZ] = UINT32_C(1000000000) / 50,
97 	[ADXL345_ODR_100HZ] = UINT32_C(1000000000) / 100,
98 	[ADXL345_ODR_200HZ] = UINT32_C(1000000000) / 200,
99 	[ADXL345_ODR_400HZ] = UINT32_C(1000000000) / 400,
100 };
101 
adxl345_decode_stream(const uint8_t * buffer,struct sensor_chan_spec chan_spec,uint32_t * fit,uint16_t max_count,void * data_out)102 static int adxl345_decode_stream(const uint8_t *buffer, struct sensor_chan_spec chan_spec,
103 				 uint32_t *fit, uint16_t max_count, void *data_out)
104 {
105 	const struct adxl345_fifo_data *enc_data = (const struct adxl345_fifo_data *)buffer;
106 	const uint8_t *buffer_end =
107 		buffer + sizeof(struct adxl345_fifo_data) + enc_data->fifo_byte_count;
108 	int count = 0;
109 	uint8_t sample_num = 0;
110 
111 	if ((uintptr_t)buffer_end <= *fit || chan_spec.chan_idx != 0) {
112 		return 0;
113 	}
114 
115 	struct sensor_three_axis_data *data = (struct sensor_three_axis_data *)data_out;
116 
117 	memset(data, 0, sizeof(struct sensor_three_axis_data));
118 	data->header.base_timestamp_ns = enc_data->timestamp;
119 	data->header.reading_count = 1;
120 	data->shift = range_to_shift[enc_data->selected_range];
121 
122 	buffer += sizeof(struct adxl345_fifo_data);
123 
124 	uint8_t sample_set_size = enc_data->sample_set_size;
125 	uint64_t period_ns = accel_period_ns[enc_data->accel_odr];
126 	uint8_t is_full_res = enc_data->is_full_res;
127 
128 	/* Calculate which sample is decoded. */
129 	if ((uint8_t *)*fit >= buffer) {
130 		sample_num = ((uint8_t *)*fit - buffer) / sample_set_size;
131 	}
132 
133 	while (count < max_count && buffer < buffer_end) {
134 		const uint8_t *sample_end = buffer;
135 
136 		sample_end += sample_set_size;
137 
138 		if ((uintptr_t)buffer < *fit) {
139 			/* This frame was already decoded, move on to the next frame */
140 			buffer = sample_end;
141 			continue;
142 		}
143 
144 		switch (chan_spec.chan_type) {
145 		case SENSOR_CHAN_ACCEL_XYZ:
146 			data->readings[count].timestamp_delta = sample_num * period_ns;
147 			uint8_t buff_offset = 0;
148 
149 			adxl345_accel_convert_q31(&data->readings[count].x, *(int16_t *)buffer,
150 					enc_data->selected_range, is_full_res);
151 			buff_offset = 2;
152 			adxl345_accel_convert_q31(&data->readings[count].y,
153 						*(int16_t *)(buffer + buff_offset),
154 							enc_data->selected_range, is_full_res);
155 			buff_offset += 2;
156 			adxl345_accel_convert_q31(&data->readings[count].z,
157 						*(int16_t *)(buffer + buff_offset),
158 							enc_data->selected_range, is_full_res);
159 			break;
160 		default:
161 			return -ENOTSUP;
162 		}
163 		buffer = sample_end;
164 		*fit = (uintptr_t)sample_end;
165 		count++;
166 	}
167 	return count;
168 }
169 
170 #endif /* CONFIG_ADXL345_STREAM */
171 
adxl345_decoder_get_frame_count(const uint8_t * buffer,struct sensor_chan_spec chan_spec,uint16_t * frame_count)172 static int adxl345_decoder_get_frame_count(const uint8_t *buffer, struct sensor_chan_spec chan_spec,
173 					   uint16_t *frame_count)
174 {
175 	int32_t ret = -ENOTSUP;
176 
177 	if (chan_spec.chan_idx != 0) {
178 		return ret;
179 	}
180 
181 #ifdef CONFIG_ADXL345_STREAM
182 	const struct adxl345_fifo_data *data = (const struct adxl345_fifo_data *)buffer;
183 
184 	if (!data->is_fifo) {
185 #endif /* CONFIG_ADXL345_STREAM */
186 		switch (chan_spec.chan_type) {
187 		case SENSOR_CHAN_ACCEL_X:
188 		case SENSOR_CHAN_ACCEL_Y:
189 		case SENSOR_CHAN_ACCEL_Z:
190 		case SENSOR_CHAN_ACCEL_XYZ:
191 			*frame_count = 1;
192 			ret = 0;
193 			break;
194 
195 		default:
196 			break;
197 		}
198 #ifdef CONFIG_ADXL345_STREAM
199 	} else {
200 		if (data->fifo_byte_count == 0) {
201 			*frame_count = 0;
202 			ret = 0;
203 		} else {
204 			switch (chan_spec.chan_type) {
205 			case SENSOR_CHAN_ACCEL_XYZ:
206 				*frame_count =
207 					data->fifo_byte_count / data->sample_set_size;
208 				ret = 0;
209 				break;
210 
211 			default:
212 				break;
213 			}
214 		}
215 	}
216 #endif /* CONFIG_ADXL345_STREAM */
217 
218 	return ret;
219 }
220 
adxl345_decode_sample(const struct adxl345_sample * data,struct sensor_chan_spec chan_spec,uint32_t * fit,uint16_t max_count,void * data_out)221 static int adxl345_decode_sample(const struct adxl345_sample *data,
222 				 struct sensor_chan_spec chan_spec, uint32_t *fit,
223 				 uint16_t max_count, void *data_out)
224 {
225 	struct sensor_three_axis_data *out = (struct sensor_three_axis_data *)data_out;
226 
227 	memset(out, 0, sizeof(struct sensor_three_axis_data));
228 	out->header.base_timestamp_ns = k_ticks_to_ns_floor64(k_uptime_ticks());
229 	out->header.reading_count = 1;
230 	out->shift = range_to_shift[data->selected_range];
231 
232 	if (*fit > 0) {
233 		return -ENOTSUP;
234 	}
235 
236 	switch (chan_spec.chan_type) {
237 	case SENSOR_CHAN_ACCEL_XYZ:
238 		adxl345_accel_convert_q31(&out->readings->x, data->x, data->selected_range,
239 					  data->is_full_res);
240 		adxl345_accel_convert_q31(&out->readings->y, data->y, data->selected_range,
241 					  data->is_full_res);
242 		adxl345_accel_convert_q31(&out->readings->z, data->z, data->selected_range,
243 					  data->is_full_res);
244 		break;
245 	default:
246 		return -ENOTSUP;
247 	}
248 
249 	*fit = 1;
250 
251 	return 1;
252 }
253 
adxl345_decoder_decode(const uint8_t * buffer,struct sensor_chan_spec chan_spec,uint32_t * fit,uint16_t max_count,void * data_out)254 static int adxl345_decoder_decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec,
255 				    uint32_t *fit, uint16_t max_count, void *data_out)
256 {
257 	const struct adxl345_sample *data = (const struct adxl345_sample *)buffer;
258 
259 #ifdef CONFIG_ADXL345_STREAM
260 	if (data->is_fifo) {
261 		return adxl345_decode_stream(buffer, chan_spec, fit, max_count, data_out);
262 	}
263 #endif /* CONFIG_ADXL345_STREAM */
264 
265 	return adxl345_decode_sample(data, chan_spec, fit, max_count, data_out);
266 }
267 
adxl345_decoder_has_trigger(const uint8_t * buffer,enum sensor_trigger_type trigger)268 static bool adxl345_decoder_has_trigger(const uint8_t *buffer, enum sensor_trigger_type trigger)
269 {
270 	const struct adxl345_fifo_data *data = (const struct adxl345_fifo_data *)buffer;
271 
272 	if (!data->is_fifo) {
273 		return false;
274 	}
275 
276 	switch (trigger) {
277 	case SENSOR_TRIG_FIFO_WATERMARK:
278 		return FIELD_GET(ADXL345_INT_MAP_WATERMARK_MSK, data->int_status);
279 	default:
280 		return false;
281 	}
282 }
283 
adxl345_get_size_info(struct sensor_chan_spec channel,size_t * base_size,size_t * frame_size)284 static int adxl345_get_size_info(struct sensor_chan_spec channel, size_t *base_size,
285 				 size_t *frame_size)
286 {
287 	__ASSERT_NO_MSG(base_size != NULL);
288 	__ASSERT_NO_MSG(frame_size != NULL);
289 
290 	if (channel.chan_type >= SENSOR_CHAN_ALL) {
291 		return -ENOTSUP;
292 	}
293 
294 	switch (channel.chan_type) {
295 	case SENSOR_CHAN_ACCEL_XYZ:
296 		*base_size = sizeof(struct sensor_three_axis_data);
297 		*frame_size = sizeof(struct sensor_three_axis_sample_data);
298 		return 0;
299 	default:
300 		break;
301 	}
302 
303 	return -ENOTSUP;
304 }
305 
306 SENSOR_DECODER_API_DT_DEFINE() = {
307 	.get_frame_count = adxl345_decoder_get_frame_count,
308 	.decode = adxl345_decoder_decode,
309 	.has_trigger = adxl345_decoder_has_trigger,
310 	.get_size_info = adxl345_get_size_info,
311 };
312 
adxl345_get_decoder(const struct device * dev,const struct sensor_decoder_api ** decoder)313 int adxl345_get_decoder(const struct device *dev, const struct sensor_decoder_api **decoder)
314 {
315 	ARG_UNUSED(dev);
316 	*decoder = &SENSOR_DECODER_NAME();
317 
318 	return 0;
319 }
320