1 /*
2 * Copyright (c) 2021 Teslabs Engineering S.L.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT maxim_max6675
8
9 #include <zephyr/drivers/sensor.h>
10 #include <zephyr/drivers/spi.h>
11 #include <zephyr/sys/byteorder.h>
12
13 #include <zephyr/logging/log.h>
14 LOG_MODULE_REGISTER(max6675, CONFIG_SENSOR_LOG_LEVEL);
15
16 /** Thermocouple input bit (goes high if thermocouple is disconnected). */
17 #define THERMOCOUPLE_INPUT BIT(2)
18 /** Temperature position. */
19 #define TEMPERATURE_POS 3U
20 /** Temperature resolution (cDeg/LSB). */
21 #define TEMPERATURE_RES 25U
22
23 struct max6675_config {
24 struct spi_dt_spec spi;
25 };
26
27 struct max6675_data {
28 uint16_t sample;
29 };
30
max6675_sample_fetch(const struct device * dev,enum sensor_channel chan)31 static int max6675_sample_fetch(const struct device *dev,
32 enum sensor_channel chan)
33 {
34 struct max6675_data *data = dev->data;
35 const struct max6675_config *config = dev->config;
36
37 int ret;
38 uint8_t buf_rx[2];
39 const struct spi_buf rx_buf = {
40 .buf = buf_rx,
41 .len = ARRAY_SIZE(buf_rx)
42 };
43 const struct spi_buf_set rx_bufs = {
44 .buffers = &rx_buf,
45 .count = 1U
46 };
47
48 if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_AMBIENT_TEMP) {
49 return -ENOTSUP;
50 }
51
52 ret = spi_read_dt(&config->spi, &rx_bufs);
53 if (ret < 0) {
54 return ret;
55 }
56
57 data->sample = sys_get_be16(buf_rx);
58
59 if (data->sample & THERMOCOUPLE_INPUT) {
60 LOG_INF("Thermocouple not connected");
61 return -ENOENT;
62 }
63
64 return 0;
65 }
66
max6675_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)67 static int max6675_channel_get(const struct device *dev, enum sensor_channel chan,
68 struct sensor_value *val)
69 {
70 struct max6675_data *data = dev->data;
71
72 int32_t temperature;
73
74 if (chan != SENSOR_CHAN_AMBIENT_TEMP) {
75 return -ENOTSUP;
76 }
77
78 temperature = (data->sample >> TEMPERATURE_POS) * TEMPERATURE_RES;
79 val->val1 = temperature / 100;
80 val->val2 = (temperature - val->val1 * 100) * 10000;
81
82 return 0;
83 }
84
85 static DEVICE_API(sensor, max6675_api) = {
86 .sample_fetch = &max6675_sample_fetch,
87 .channel_get = &max6675_channel_get,
88 };
89
max6675_init(const struct device * dev)90 static int max6675_init(const struct device *dev)
91 {
92 const struct max6675_config *config = dev->config;
93
94 if (!spi_is_ready_dt(&config->spi)) {
95 LOG_ERR("SPI bus is not ready");
96 return -ENODEV;
97 }
98
99 return 0;
100 }
101
102 #define MAX6675_INIT(n) \
103 static struct max6675_data max6675_data_##n; \
104 static const struct max6675_config max6675_config_##n = { \
105 .spi = SPI_DT_SPEC_INST_GET(n, \
106 SPI_OP_MODE_MASTER | \
107 SPI_WORD_SET(8U), \
108 0U), \
109 }; \
110 SENSOR_DEVICE_DT_INST_DEFINE(n, &max6675_init, NULL, \
111 &max6675_data_##n, &max6675_config_##n, \
112 POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \
113 &max6675_api);
114
115 DT_INST_FOREACH_STATUS_OKAY(MAX6675_INIT)
116