1 /*
2  * Copyright (c) 2023 Google LLC
3  * Copyright (c) 2024 Florian Weber <Florian.Weber@live.de>
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_DRIVERS_SENSOR_AKM09918C_AKM09918C_H_
8 #define ZEPHYR_DRIVERS_SENSOR_AKM09918C_AKM09918C_H_
9 
10 #include <zephyr/device.h>
11 #include <zephyr/drivers/i2c.h>
12 #include <zephyr/drivers/sensor.h>
13 #include <zephyr/rtio/rtio.h>
14 
15 #include "akm09918c_reg.h"
16 
17 /* Time it takes to get a measurement in single-measure mode */
18 #define AKM09918C_MEASURE_TIME_US 9000
19 
20 /* Conversion values */
21 #define AKM09918C_MICRO_GAUSS_PER_BIT INT64_C(1500)
22 
23 /* Maximum and minimum raw register values for magnetometer data per datasheet */
24 #define AKM09918C_MAGN_MAX_DATA_REG (32752)
25 #define AKM09918C_MAGN_MIN_DATA_REG (-32752)
26 
27 /* Maximum and minimum magnetometer values in microgauss. +/-32752 is the maximum range of the
28  * data registers (slightly less than the range of int16). This works out to +/- 49,128,000 uGs
29  */
30 #define AKM09918C_MAGN_MAX_MICRO_GAUSS (AKM09918C_MAGN_MAX_DATA_REG * AKM09918C_MICRO_GAUSS_PER_BIT)
31 #define AKM09918C_MAGN_MIN_MICRO_GAUSS (AKM09918C_MAGN_MIN_DATA_REG * AKM09918C_MICRO_GAUSS_PER_BIT)
32 
33 struct akm09918c_data {
34 	int16_t x_sample;
35 	int16_t y_sample;
36 	int16_t z_sample;
37 	uint8_t mode;
38 #ifdef CONFIG_SENSOR_ASYNC_API
39 	struct akm09918c_async_fetch_ctx {
40 		struct rtio_iodev_sqe *iodev_sqe;
41 		uint64_t timestamp;
42 		struct k_work_delayable async_fetch_work;
43 	} work_ctx;
44 #endif
45 };
46 
47 struct akm09918c_config {
48 	struct i2c_dt_spec i2c;
49 };
50 
akm09918c_hz_to_reg(const struct sensor_value * val)51 static inline uint8_t akm09918c_hz_to_reg(const struct sensor_value *val)
52 {
53 	if (val->val1 >= 100) {
54 		return AKM09918C_CNTL2_CONTINUOUS_4;
55 	} else if (val->val1 >= 50) {
56 		return AKM09918C_CNTL2_CONTINUOUS_3;
57 	} else if (val->val1 >= 20) {
58 		return AKM09918C_CNTL2_CONTINUOUS_2;
59 	} else if (val->val1 > 0) {
60 		return AKM09918C_CNTL2_CONTINUOUS_1;
61 	} else {
62 		return AKM09918C_CNTL2_PWR_DOWN;
63 	}
64 }
65 
akm09918c_reg_to_hz(uint8_t reg,struct sensor_value * val)66 static inline void akm09918c_reg_to_hz(uint8_t reg, struct sensor_value *val)
67 {
68 	val->val1 = 0;
69 	val->val2 = 0;
70 	switch (reg) {
71 	case AKM09918C_CNTL2_CONTINUOUS_1:
72 		val->val1 = 10;
73 		break;
74 	case AKM09918C_CNTL2_CONTINUOUS_2:
75 		val->val1 = 20;
76 		break;
77 	case AKM09918C_CNTL2_CONTINUOUS_3:
78 		val->val1 = 50;
79 		break;
80 	case AKM09918C_CNTL2_CONTINUOUS_4:
81 		val->val1 = 100;
82 		break;
83 	}
84 }
85 int akm09918c_start_measurement(const struct device *dev, enum sensor_channel chan);
86 
87 int akm09918c_fetch_measurement(const struct device *dev, int16_t *x, int16_t *y, int16_t *z);
88 /*
89  * RTIO types
90  */
91 
92 struct akm09918c_decoder_header {
93 	uint64_t timestamp;
94 } __packed;
95 
96 struct akm09918c_encoded_data {
97 	struct akm09918c_decoder_header header;
98 	int16_t readings[3];
99 };
100 
101 void akm09918_async_fetch(struct k_work *work);
102 
103 int akm09918c_get_decoder(const struct device *dev, const struct sensor_decoder_api **decoder);
104 
105 void akm09918c_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe);
106 
107 #endif /* ZEPHYR_DRIVERS_SENSOR_AKM09918C_AKM09918C_H_ */
108