1 /*
2  * Copyright (c) 2024 Würth Elektronik eiSos GmbH & Co. KG
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT we_wsen_pdus_25131308xxxxx
8 
9 #include <stdlib.h>
10 
11 #include <zephyr/sys/__assert.h>
12 #include <zephyr/sys/byteorder.h>
13 #include <zephyr/logging/log.h>
14 
15 #include "wsen_pdus_25131308XXXXX.h"
16 
17 LOG_MODULE_REGISTER(WSEN_PDUS_25131308XXXXX, CONFIG_SENSOR_LOG_LEVEL);
18 
pdus_25131308XXXXX_sample_fetch(const struct device * dev,enum sensor_channel chan)19 static int pdus_25131308XXXXX_sample_fetch(const struct device *dev, enum sensor_channel chan)
20 {
21 	struct pdus_25131308XXXXX_data *data = dev->data;
22 	uint16_t pressure_dummy;
23 
24 	switch (chan) {
25 	case SENSOR_CHAN_ALL: {
26 		if (PDUS_getRawPressureAndTemperature(&data->sensor_interface, &data->pressure,
27 						      &data->temperature) != WE_SUCCESS) {
28 			LOG_ERR("Failed to fetch data sample");
29 			return -EIO;
30 		}
31 		break;
32 	}
33 	case SENSOR_CHAN_AMBIENT_TEMP: {
34 		if (PDUS_getRawPressureAndTemperature(&data->sensor_interface, &pressure_dummy,
35 						      &data->temperature) != WE_SUCCESS) {
36 			LOG_ERR("Failed to fetch data sample");
37 			return -EIO;
38 		}
39 		break;
40 	}
41 	case SENSOR_CHAN_PRESS: {
42 		if (PDUS_getRawPressure(&data->sensor_interface, &data->pressure) != WE_SUCCESS) {
43 			LOG_ERR("Failed to fetch data sample");
44 			return -EIO;
45 		}
46 		break;
47 	}
48 	default:
49 		LOG_ERR("Fetching is not supported on channel %d.", chan);
50 		return -ENOTSUP;
51 	}
52 
53 	return 0;
54 }
55 
pdus_25131308XXXXX_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * value)56 static int pdus_25131308XXXXX_channel_get(const struct device *dev, enum sensor_channel chan,
57 					  struct sensor_value *value)
58 {
59 	struct pdus_25131308XXXXX_data *data = dev->data;
60 	const struct pdus_25131308XXXXX_config *config = dev->config;
61 
62 	switch (chan) {
63 	case SENSOR_CHAN_AMBIENT_TEMP: {
64 		int32_t temperature_mega = ((int32_t)(data->temperature - T_MIN_VAL_PDUS)) * 4272;
65 
66 		value->val1 = temperature_mega / 1000000;
67 		value->val2 = temperature_mega % 1000000;
68 		break;
69 	}
70 	case SENSOR_CHAN_PRESS: {
71 		int32_t pressure_temp = ((int32_t)(data->pressure - P_MIN_VAL_PDUS));
72 
73 		/*
74 		 * these values are conversion factors based on the sensor type defined in the user
75 		 * manual of the respective sensor
76 		 */
77 		switch (config->sensor_type) {
78 		case PDUS_pdus0:
79 			value->val1 = ((pressure_temp * 763) - 10000000) / 100000000;
80 			value->val2 = (((pressure_temp * 763) - 10000000) % 100000000) / 100;
81 			break;
82 		case PDUS_pdus1:
83 			value->val1 = ((pressure_temp * 763) - 10000000) / 10000000;
84 			value->val2 = (((pressure_temp * 763) - 10000000) % 10000000) / 10;
85 			break;
86 		case PDUS_pdus2:
87 			value->val1 = ((pressure_temp * 763) - 10000000) / 1000000;
88 			value->val2 = ((pressure_temp * 763) - 10000000) % 1000000;
89 			break;
90 		case PDUS_pdus3:
91 			value->val1 = (pressure_temp * 3815) / 1000000;
92 			value->val2 = (pressure_temp * 3815) % 1000000;
93 			break;
94 		case PDUS_pdus4:
95 			value->val1 = ((pressure_temp * 4196) - 10000000) / 100000;
96 			value->val2 =
97 				((pressure_temp * 4196) - 10000000) % 100000 * (1000000 / 100000);
98 			break;
99 		case PDUS_pdus5:
100 			value->val1 = (pressure_temp * 5722) / 100000;
101 			value->val2 = (pressure_temp * 5722) % 100000 * (1000000 / 100000);
102 			break;
103 		default:
104 			LOG_ERR("Sensor type doesn't exist");
105 			return -ENOTSUP;
106 		}
107 		break;
108 	}
109 	default:
110 		LOG_ERR("Channel not supported %d", chan);
111 		return -ENOTSUP;
112 	}
113 
114 	return 0;
115 }
116 
117 static DEVICE_API(sensor, pdus_25131308XXXXX_driver_api) = {
118 	.sample_fetch = pdus_25131308XXXXX_sample_fetch,
119 	.channel_get = pdus_25131308XXXXX_channel_get
120 };
121 
pdus_25131308XXXXX_init(const struct device * dev)122 static int pdus_25131308XXXXX_init(const struct device *dev)
123 {
124 	struct pdus_25131308XXXXX_data *data = dev->data;
125 	const struct pdus_25131308XXXXX_config *config = dev->config;
126 
127 	/* Initialize WE sensor interface */
128 	PDUS_getDefaultInterface(&data->sensor_interface);
129 	data->sensor_interface.interfaceType = WE_i2c;
130 
131 	if (!i2c_is_ready_dt(&config->bus_cfg.i2c)) {
132 		LOG_ERR("I2C bus device not ready");
133 		return -ENODEV;
134 	}
135 
136 	data->sensor_interface.handle = (void *)&config->bus_cfg.i2c;
137 
138 	return 0;
139 }
140 
141 /*
142  * Main instantiation macro.
143  */
144 #define PDUS_25131308XXXXX_DEFINE(inst)                                                            \
145 	static struct pdus_25131308XXXXX_data pdus_25131308XXXXX_data_##inst;                      \
146 	static const struct pdus_25131308XXXXX_config pdus_25131308XXXXX_config_##inst = {         \
147 		.bus_cfg =                                                                         \
148 			{                                                                          \
149 				.i2c = I2C_DT_SPEC_INST_GET(inst),                                 \
150 			},                                                                         \
151 		.sensor_type = (PDUS_SensorType_t)DT_INST_ENUM_IDX(inst, sensor_type)};            \
152 	SENSOR_DEVICE_DT_INST_DEFINE(inst, pdus_25131308XXXXX_init, NULL,                          \
153 				     &pdus_25131308XXXXX_data_##inst,                              \
154 				     &pdus_25131308XXXXX_config_##inst, POST_KERNEL,               \
155 				     CONFIG_SENSOR_INIT_PRIORITY, &pdus_25131308XXXXX_driver_api);
156 
157 DT_INST_FOREACH_STATUS_OKAY(PDUS_25131308XXXXX_DEFINE)
158