1 /*
2  * Copyright (c) 2022, Michal Morsisko
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT rohm_bh1750
8 
9 #include <zephyr/drivers/sensor.h>
10 #include <zephyr/drivers/i2c.h>
11 #include <zephyr/logging/log.h>
12 #include <zephyr/kernel.h>
13 #include <zephyr/devicetree.h>
14 #include <zephyr/sys/byteorder.h>
15 #include <zephyr/sys/__assert.h>
16 
17 LOG_MODULE_REGISTER(BH1750, CONFIG_SENSOR_LOG_LEVEL);
18 
19 #define BH1750_CONTINUOUS_HIGH_RES_MODE                 0x10
20 #define BH1750_CONTINUOUS_HIGH_RES_MODE_2               0x11
21 #define BH1750_CONTINUOUS_LOW_RES_MODE                  0x13
22 #define BH1750_ONE_TIME_HIGH_RES_MODE                   0x20
23 #define BH1750_ONE_TIME_HIGH_RES_MODE_2                 0x21
24 #define BH1750_ONE_TIME_LOW_RES_MODE                    0x23
25 #define BH1750_MTREG_HIGH_BYTE                          0x40
26 #define BH1750_MTREG_LOW_BYTE                           0x60
27 #define BH1750_MTREG_HIGH_BYTE_MASK                     0xE0
28 #define BH1750_MTREG_LOW_BYTE_MASK                      0x1F
29 
30 #define BH1750_DEFAULT_MTREG                            69U
31 #define BH1750_LOW_RES_MODE_MAX_WAIT                    24U
32 #define BH1750_HIGH_RES_MODE_MAX_WAIT                   180U
33 #define BH1750_LOW_RES_MODE_TYPICAL_WAIT                16U
34 #define BH1750_HIGH_RES_MODE_TYPICAL_WAIT               120U
35 
36 #define BH1750_LOW_RES_DTS_ENUM                         0U
37 #define BH1750_HIGH_RES_DTS_ENUM                        1U
38 #define BH1750_HIGH_RES_2_DTS_ENUM                      2U
39 
40 struct bh1750_dev_config {
41 	struct i2c_dt_spec bus;
42 	uint8_t resolution;
43 	uint8_t mtreg;
44 };
45 
46 struct bh1750_data {
47 	uint16_t sample;
48 };
49 
bh1750_opcode_read(const struct device * dev,uint8_t opcode,uint16_t * val)50 static int bh1750_opcode_read(const struct device *dev, uint8_t opcode,
51 			      uint16_t *val)
52 {
53 	const struct bh1750_dev_config *cfg = dev->config;
54 	int rc;
55 
56 	rc = i2c_burst_read_dt(&cfg->bus, opcode, (uint8_t *)val, 2);
57 	if (rc < 0) {
58 		return rc;
59 	}
60 
61 	*val = sys_be16_to_cpu(*val);
62 	return 0;
63 }
64 
bh1750_opcode_write(const struct device * dev,uint8_t opcode)65 static int bh1750_opcode_write(const struct device *dev, uint8_t opcode)
66 {
67 	const struct bh1750_dev_config *cfg = dev->config;
68 
69 	return i2c_write_dt(&cfg->bus, &opcode, 1);
70 }
71 
bh1750_mtreg_write(const struct device * dev,uint8_t mtreg)72 static int bh1750_mtreg_write(const struct device *dev, uint8_t mtreg)
73 {
74 	int rc;
75 	uint8_t high_byte = mtreg & BH1750_MTREG_HIGH_BYTE_MASK;
76 	uint8_t low_byte = mtreg & BH1750_MTREG_LOW_BYTE_MASK;
77 
78 	rc = bh1750_opcode_write(dev, BH1750_MTREG_HIGH_BYTE | (high_byte >> 5));
79 	if (rc < 0) {
80 		LOG_ERR("%s, Failed to write high byte of mtreg!",
81 			dev->name);
82 		return rc;
83 	}
84 
85 	rc = bh1750_opcode_write(dev, BH1750_MTREG_LOW_BYTE | low_byte);
86 	if (rc < 0) {
87 		LOG_ERR("%s, Failed to write low byte of mtreg!",
88 			dev->name);
89 		return rc;
90 	}
91 
92 	return 0;
93 }
94 
bh1750_get_mode_from_dts_device(const struct device * dev)95 static uint8_t bh1750_get_mode_from_dts_device(const struct device *dev)
96 {
97 	const struct bh1750_dev_config *cfg = dev->config;
98 
99 	if (cfg->resolution == BH1750_HIGH_RES_2_DTS_ENUM) {
100 		return BH1750_ONE_TIME_HIGH_RES_MODE_2;
101 	} else if (cfg->resolution == BH1750_HIGH_RES_DTS_ENUM) {
102 		return BH1750_ONE_TIME_HIGH_RES_MODE;
103 	} else {
104 		return BH1750_ONE_TIME_LOW_RES_MODE;
105 	}
106 }
107 
bh1750_get_wait_time_from_dts_device(const struct device * dev)108 static int bh1750_get_wait_time_from_dts_device(const struct device *dev)
109 {
110 	const struct bh1750_dev_config *cfg = dev->config;
111 
112 	if (cfg->resolution == BH1750_HIGH_RES_2_DTS_ENUM) {
113 		return BH1750_HIGH_RES_MODE_MAX_WAIT;
114 	} else if (cfg->resolution == BH1750_HIGH_RES_DTS_ENUM) {
115 		return BH1750_HIGH_RES_MODE_MAX_WAIT;
116 	} else {
117 		return BH1750_LOW_RES_MODE_MAX_WAIT;
118 	}
119 }
120 
bh1750_sample_fetch(const struct device * dev,enum sensor_channel chan)121 static int bh1750_sample_fetch(const struct device *dev,
122 			       enum sensor_channel chan)
123 {
124 	const struct bh1750_dev_config *cfg = dev->config;
125 	struct bh1750_data *drv_data = dev->data;
126 	const int max_wait = bh1750_get_wait_time_from_dts_device(dev);
127 	const uint8_t mode = bh1750_get_mode_from_dts_device(dev);
128 	int rc;
129 	int wait_time;
130 
131 	if (chan != SENSOR_CHAN_ALL &&
132 	    chan != SENSOR_CHAN_LIGHT) {
133 		return -ENOTSUP;
134 	}
135 
136 	/* Start the measurement */
137 	rc = bh1750_opcode_write(dev, mode);
138 	if (rc < 0) {
139 		LOG_ERR("%s, Failed to start measurement!",
140 			dev->name);
141 		return rc;
142 	}
143 
144 	/* Calculate measurement time */
145 	wait_time = (max_wait * (cfg->mtreg * 10000 / BH1750_DEFAULT_MTREG)) / 10000;
146 
147 	/* Wait for the measurement to be stored in the sensor memory */
148 	k_msleep(wait_time);
149 
150 	/* Fetch result */
151 	rc = bh1750_opcode_read(dev, mode, &drv_data->sample);
152 	if (rc < 0) {
153 		LOG_ERR("%s: Failed to read measurement result!",
154 			dev->name);
155 		return rc;
156 	}
157 
158 	return 0;
159 }
160 
bh1750_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)161 static int bh1750_channel_get(const struct device *dev,
162 			      enum sensor_channel chan,
163 			      struct sensor_value *val)
164 {
165 	const struct bh1750_dev_config *cfg = dev->config;
166 	struct bh1750_data *drv_data = dev->data;
167 	uint32_t tmp;
168 
169 	if (chan != SENSOR_CHAN_ALL &&
170 	    chan != SENSOR_CHAN_LIGHT) {
171 		return -ENOTSUP;
172 	}
173 
174 	/* See datasheet (Technical note 11046EDT01), page 11
175 	 * https://www.mouser.com/datasheet/2/348/Rohm_11162017_ROHMS34826-1-1279292.pdf
176 	 * for more information how to convert raw sample to lx
177 	 */
178 	tmp = (drv_data->sample * 1000 / 12) * (BH1750_DEFAULT_MTREG * 100 / cfg->mtreg);
179 
180 	if (cfg->resolution == BH1750_HIGH_RES_2_DTS_ENUM) {
181 		tmp /= 2;
182 	}
183 
184 	val->val1 = tmp / 10000;
185 	val->val2 = (tmp % 10000) * 100;
186 
187 	return 0;
188 }
189 
190 static const struct sensor_driver_api bh1750_driver_api = {
191 	.sample_fetch = bh1750_sample_fetch,
192 	.channel_get = bh1750_channel_get
193 };
194 
bh1750_init(const struct device * dev)195 static int bh1750_init(const struct device *dev)
196 {
197 	const struct bh1750_dev_config *cfg = dev->config;
198 
199 	if (!device_is_ready(cfg->bus.bus)) {
200 		LOG_ERR("I2C dev %s not ready", cfg->bus.bus->name);
201 		return -ENODEV;
202 	}
203 
204 	if (cfg->mtreg != BH1750_DEFAULT_MTREG) {
205 		bh1750_mtreg_write(dev, cfg->mtreg);
206 	}
207 
208 	return 0;
209 }
210 
211 #define DEFINE_BH1750(_num)							       \
212 	static struct bh1750_data bh1750_data_##_num;				       \
213 	static const struct bh1750_dev_config bh1750_config_##_num = {		       \
214 		.bus = I2C_DT_SPEC_INST_GET(_num),				       \
215 		.mtreg = DT_INST_PROP(_num, mtreg),				       \
216 		.resolution = DT_INST_PROP(_num, resolution)			       \
217 	};									       \
218 	SENSOR_DEVICE_DT_INST_DEFINE(_num, bh1750_init, NULL,				       \
219 			      &bh1750_data_##_num, &bh1750_config_##_num, POST_KERNEL, \
220 			      CONFIG_SENSOR_INIT_PRIORITY, &bh1750_driver_api);
221 
222 DT_INST_FOREACH_STATUS_OKAY(DEFINE_BH1750)
223