1 /*
2 * Copyright (c) 2021 Pete Dietl
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT maxim_max31875
8
9 #include <zephyr/device.h>
10 #include <zephyr/drivers/i2c.h>
11 #include <zephyr/sys/byteorder.h>
12 #include <zephyr/sys/util.h>
13 #include <zephyr/kernel.h>
14 #include <zephyr/drivers/sensor.h>
15 #include <zephyr/sys/__assert.h>
16 #include <zephyr/logging/log.h>
17
18 LOG_MODULE_REGISTER(MAX31875, CONFIG_SENSOR_LOG_LEVEL);
19
20 /* Conversions per second */
21 #define MAX31875_CONV_PER_SEC_SHIFT 0x01
22 #define MAX31875_CONV_PER_SEC_0_25 0x00
23 #define MAX31875_CONV_PER_SEC_1 0x01
24 #define MAX31875_CONV_PER_SEC_4 0x02
25 #define MAX31875_CONV_PER_SEC_8 0x03
26
27 #define MAX31875_CONV_PER_SEC_MASK (BIT_MASK(2) << MAX31875_CONV_PER_SEC_SHIFT)
28
29 /* Data format */
30 #define MAX31875_DATA_FORMAT_SHIFT 0x07
31
32 #define MAX31875_DATA_FORMAT_NORMAL 0x00
33 #define MAX31875_DATA_FORMAT_EXTENDED 0x01
34
35 /* These are for shifting the data received */
36 #define MAX31875_DATA_FORMAT_EXTENDED_SHIFT 0x03
37 #define MAX31875_DATA_FORMAT_NORMAL_SHIFT 0x04
38
39 /* Resolution in bits */
40 #define MAX31875_RESOLUTION_SHIFT 0x05
41
42 #define MAX31875_RESOLUTION_8_BITS 0x00
43 #define MAX31875_RESOLUTION_9_BITS 0x01
44 #define MAX31875_RESOLUTION_10_BITS 0x02
45 #define MAX31875_RESOLUTION_12_BITS 0x03
46
47 #define MAX31875_TEMP_SCALE 62500
48
49 /**
50 * @brief Macro for creating the MAX31875 configuration register value
51 *
52 * @param mode Data format
53 * @param res Resolution (number of bits)
54 * @param convs Conversions per second
55 */
56 #define MAX31875_CONFIG(format, res, convs) \
57 (((format) << (MAX31875_DATA_FORMAT_SHIFT)) | ((res) << (MAX31875_RESOLUTION_SHIFT)) | \
58 ((convs) << (MAX31875_CONV_PER_SEC_SHIFT)))
59
60 #define MAX31875_REG_TEMPERATURE 0x00
61 #define MAX31875_REG_CONFIG 0x01
62
63 struct max31875_data {
64 int16_t sample;
65 uint16_t config_reg;
66 };
67
68 struct max31875_config {
69 const struct i2c_dt_spec bus;
70 uint8_t conversions_per_second;
71 uint8_t data_format;
72 uint8_t resolution;
73 };
74
max31875_reg_read(const struct max31875_config * cfg,uint8_t reg,uint16_t * val)75 static int max31875_reg_read(const struct max31875_config *cfg,
76 uint8_t reg, uint16_t *val)
77 {
78 int ret;
79
80 ret = i2c_burst_read_dt(&cfg->bus, reg, (uint8_t *)val, sizeof(*val));
81 if (ret < 0) {
82 return ret;
83 }
84
85 *val = sys_be16_to_cpu(*val);
86 return 0;
87 }
88
max31875_reg_write(const struct max31875_config * cfg,uint8_t reg,uint16_t val)89 static int max31875_reg_write(const struct max31875_config *cfg,
90 uint8_t reg, uint16_t val)
91 {
92 uint16_t val_be = sys_cpu_to_be16(val);
93
94 return i2c_burst_write_dt(&cfg->bus, reg, (uint8_t *)&val_be, 2);
95 }
96
set_config_flags(struct max31875_data * data,uint16_t mask,uint16_t value)97 static uint16_t set_config_flags(struct max31875_data *data, uint16_t mask,
98 uint16_t value)
99 {
100 return (data->config_reg & ~mask) | (value & mask);
101 }
102
max31875_update_config(const struct device * dev,uint16_t mask,uint16_t val)103 static int max31875_update_config(const struct device *dev, uint16_t mask, uint16_t val)
104 {
105 int rc;
106 const struct max31875_config *cfg = dev->config;
107 struct max31875_data *data = dev->data;
108 const uint16_t new_val = set_config_flags(data, mask, val);
109
110 rc = max31875_reg_write(cfg, MAX31875_REG_CONFIG, new_val);
111
112 /* don't update if write failed */
113 if (rc == 0) {
114 data->config_reg = new_val;
115 }
116
117 return rc;
118 }
119
max31875_attr_set(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)120 static int max31875_attr_set(const struct device *dev,
121 enum sensor_channel chan,
122 enum sensor_attribute attr,
123 const struct sensor_value *val)
124 {
125 int ret;
126 uint16_t value;
127 uint16_t cr;
128
129 if (chan != SENSOR_CHAN_AMBIENT_TEMP) {
130 return -ENOTSUP;
131 }
132
133 switch (attr) {
134 case SENSOR_ATTR_FULL_SCALE:
135 /* the sensor supports two ranges -50 to 128 and -50 to 150 */
136 /* the value contains the upper limit */
137 if (val->val1 == 128) {
138 value = MAX31875_DATA_FORMAT_NORMAL << MAX31875_DATA_FORMAT_SHIFT;
139 } else if (val->val1 == 150) {
140 value = MAX31875_DATA_FORMAT_EXTENDED << MAX31875_DATA_FORMAT_SHIFT;
141 } else {
142 return -ENOTSUP;
143 }
144
145 ret = max31875_update_config(dev, MAX31875_DATA_FORMAT_SHIFT, value);
146 if (ret < 0) {
147 LOG_ERR("Failed to set attribute!");
148 return ret;
149 }
150 break;
151 case SENSOR_ATTR_SAMPLING_FREQUENCY:
152 /* conversion rate in mHz */
153 cr = val->val1 * 1000 + val->val2 / 1000;
154
155 /* the sensor supports 0.25Hz, 1Hz, 4Hz and 8Hz */
156 /* conversion rate */
157 switch (cr) {
158 case 250:
159 value = MAX31875_CONV_PER_SEC_0_25 << MAX31875_CONV_PER_SEC_SHIFT;
160 break;
161
162 case 1000:
163 value = MAX31875_CONV_PER_SEC_1 << MAX31875_CONV_PER_SEC_SHIFT;
164 break;
165
166 case 4000:
167 value = MAX31875_CONV_PER_SEC_4 << MAX31875_CONV_PER_SEC_SHIFT;
168 break;
169
170 case 8000:
171 value = MAX31875_CONV_PER_SEC_8 << MAX31875_CONV_PER_SEC_SHIFT;
172 break;
173
174 default:
175 return -ENOTSUP;
176 }
177
178 ret = max31875_update_config(dev, MAX31875_CONV_PER_SEC_MASK, value);
179 if (ret < 0) {
180 LOG_ERR("Failed to set attribute!");
181 return ret;
182 }
183
184 break;
185
186 default:
187 return -ENOTSUP;
188 }
189
190 return 0;
191 }
192
max31875_sample_fetch(const struct device * dev,enum sensor_channel chan)193 static int max31875_sample_fetch(const struct device *dev,
194 enum sensor_channel chan)
195 {
196 struct max31875_data *data = dev->data;
197 const struct max31875_config *cfg = dev->config;
198 uint16_t val;
199 int ret;
200
201 if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_AMBIENT_TEMP) {
202 LOG_ERR("Invalid channel provided");
203 return -ENOTSUP;
204 }
205
206 ret = max31875_reg_read(cfg, MAX31875_REG_TEMPERATURE, &val);
207 if (ret < 0) {
208 return ret;
209 }
210
211 if (data->config_reg & BIT(MAX31875_DATA_FORMAT_SHIFT)) {
212 data->sample = arithmetic_shift_right((int16_t)val,
213 MAX31875_DATA_FORMAT_EXTENDED_SHIFT);
214 } else {
215 data->sample = arithmetic_shift_right((int16_t)val,
216 MAX31875_DATA_FORMAT_NORMAL_SHIFT);
217 }
218
219 return 0;
220 }
221
max31875_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)222 static int max31875_channel_get(const struct device *dev,
223 enum sensor_channel chan,
224 struct sensor_value *val)
225 {
226 struct max31875_data *data = dev->data;
227 int32_t uval;
228
229 if (chan != SENSOR_CHAN_AMBIENT_TEMP) {
230 return -ENOTSUP;
231 }
232
233 uval = data->sample * MAX31875_TEMP_SCALE;
234 val->val1 = uval / 1000000;
235 val->val2 = uval % 1000000;
236
237 return 0;
238 }
239
240 static const struct sensor_driver_api max31875_driver_api = {
241 .attr_set = max31875_attr_set,
242 .sample_fetch = max31875_sample_fetch,
243 .channel_get = max31875_channel_get,
244 };
245
max31875_init(const struct device * dev)246 static int max31875_init(const struct device *dev)
247 {
248 const struct max31875_config *cfg = dev->config;
249 struct max31875_data *data = dev->data;
250
251 if (!device_is_ready(cfg->bus.bus)) {
252 LOG_ERR("I2C dev %s not ready", cfg->bus.bus->name);
253 return -ENODEV;
254 }
255
256 data->config_reg = MAX31875_CONFIG(cfg->data_format, cfg->resolution,
257 cfg->conversions_per_second);
258
259 return max31875_update_config(dev, 0, 0);
260 }
261
262
263 #define MAX31875_INST(inst) \
264 static struct max31875_data max31875_data_##inst; \
265 static const struct max31875_config max31875_config_##inst = { \
266 .bus = I2C_DT_SPEC_INST_GET(inst), \
267 .conversions_per_second = DT_INST_ENUM_IDX(inst, conversions_per_second), \
268 .resolution = DT_INST_ENUM_IDX(inst, resolution), \
269 .data_format = DT_INST_PROP(inst, extended_mode), \
270 }; \
271 SENSOR_DEVICE_DT_INST_DEFINE(inst, max31875_init, NULL, &max31875_data_##inst, \
272 &max31875_config_##inst, POST_KERNEL, \
273 CONFIG_SENSOR_INIT_PRIORITY, &max31875_driver_api);
274
275 DT_INST_FOREACH_STATUS_OKAY(MAX31875_INST)
276