1 /*
2 * Copyright (c) 2024 MASSDRIVER EI (massdriver.space)
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT phosense_xbr818
8
9 #include <zephyr/device.h>
10 #include <zephyr/drivers/i2c.h>
11
12 #include <zephyr/logging/log.h>
13 LOG_MODULE_REGISTER(XBR818, CONFIG_SENSOR_LOG_LEVEL);
14
15 #include "xbr818.h"
16 #include <zephyr/drivers/sensor/xbr818.h>
17
xbr818_enable_i2c(const struct device * dev)18 static int xbr818_enable_i2c(const struct device *dev)
19 {
20 const struct xbr818_config *config = dev->config;
21 int ret;
22
23 if (config->i2c_en.port) {
24 ret = gpio_pin_set_dt(&config->i2c_en, 1);
25 if (ret != 0) {
26 LOG_ERR("%s: could not set i2c_en pin", dev->name);
27 }
28 k_usleep(10);
29 return ret;
30 }
31 return 0;
32 }
33
xbr818_disable_i2c(const struct device * dev)34 static int xbr818_disable_i2c(const struct device *dev)
35 {
36 const struct xbr818_config *config = dev->config;
37 int ret;
38
39 if (config->i2c_en.port) {
40 ret = gpio_pin_set_dt(&config->i2c_en, 0);
41 if (ret != 0) {
42 LOG_ERR("%s: could not unset i2c_en pin", dev->name);
43 }
44 return ret;
45 }
46 return 0;
47 }
48
xbr818_sample_fetch(const struct device * dev,enum sensor_channel chan)49 static int xbr818_sample_fetch(const struct device *dev, enum sensor_channel chan)
50 {
51 const struct xbr818_config *config = dev->config;
52 struct xbr818_data *data = dev->data;
53 int ret;
54
55 if (chan != SENSOR_CHAN_PROX && chan != SENSOR_CHAN_ALL) {
56 LOG_ERR("%s: requesting unsupported channel %i", dev->name, chan);
57 return -ENOTSUP;
58 }
59
60 ret = gpio_pin_get_dt(&config->io_val);
61 if (ret < 0) {
62 return ret;
63 }
64 data->value = (ret == 1 ? true : false);
65
66 return 0;
67 }
68
xbr818_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)69 static int xbr818_channel_get(const struct device *dev, enum sensor_channel chan,
70 struct sensor_value *val)
71 {
72 struct xbr818_data *data = dev->data;
73
74 if (chan != SENSOR_CHAN_PROX) {
75 LOG_ERR("%s: requesting unsupported channel %i", dev->name, chan);
76 return -ENOTSUP;
77 }
78
79 val->val1 = (data->value ? 1 : 0);
80 val->val2 = 0;
81
82 return 0;
83 }
84
xbr818_attr_set(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)85 static int xbr818_attr_set(const struct device *dev, enum sensor_channel chan,
86 enum sensor_attribute attr, const struct sensor_value *val)
87 {
88 const struct xbr818_config *config = dev->config;
89 int ret;
90 uint8_t tmp[3];
91 uint64_t tmpf;
92
93 if (chan != SENSOR_CHAN_PROX) {
94 LOG_ERR("%s: requesting unsupported channel %i", dev->name, chan);
95 return -ENOTSUP;
96 }
97
98 if (val->val1 < 0) {
99 return -EINVAL;
100 }
101
102 ret = xbr818_enable_i2c(dev);
103 if (ret != 0) {
104 return ret;
105 }
106
107 if (attr == SENSOR_ATTR_LOWER_THRESH) {
108 if (val->val1 > 0xFFFF || val->val1 < 0) {
109 return -EINVAL;
110 }
111 tmp[0] = val->val1 & 0xFF;
112 tmp[1] = (val->val1 & 0xFF00) >> 8;
113 ret = i2c_burst_write_dt(&config->i2c, XBR818_THRESHOLD_1, tmp, 2);
114 } else if ((enum sensor_attribute_xbr818)attr == SENSOR_ATTR_XBR818_NOISE_FLOOR) {
115 if (val->val1 > 0xFFFF || val->val1 < 0) {
116 return -EINVAL;
117 }
118 tmp[0] = val->val1 & 0xFF;
119 tmp[1] = (val->val1 & 0xFF00) >> 8;
120 ret = i2c_burst_write_dt(&config->i2c, XBR818_THRESHOLD_NOISE_1, tmp, 2);
121 } else if ((enum sensor_attribute_xbr818)attr == SENSOR_ATTR_XBR818_DELAY_TIME) {
122 if (val->val1 < 0 || val->val2 < 0) {
123 return -EINVAL;
124 }
125 tmpf = (uint64_t)val->val1 * 1000000 + (uint64_t)val->val2;
126 tmpf = (tmpf * SENSOR_XBR818_CLOCKRATE) / 1000000;
127 if (tmpf > 0xFFFFFF) {
128 return -EINVAL;
129 }
130 tmp[0] = tmpf & 0xFF;
131 tmp[1] = (tmpf & 0xFF00) >> 8;
132 tmp[2] = (tmpf & 0xFF0000) >> 16;
133 ret = i2c_burst_write_dt(&config->i2c, XBR818_DELAY_TIME_1, tmp, 3);
134 } else if ((enum sensor_attribute_xbr818)attr == SENSOR_ATTR_XBR818_LOCK_TIME) {
135 if (val->val1 < 0 || val->val2 < 0) {
136 return -EINVAL;
137 }
138 tmpf = (uint64_t)val->val1 * 1000000 + (uint64_t)val->val2;
139 tmpf = (tmpf * SENSOR_XBR818_CLOCKRATE) / 1000000;
140 if (tmpf > 0xFFFFFF) {
141 return -EINVAL;
142 }
143 tmp[0] = tmpf & 0xFF;
144 tmp[1] = (tmpf & 0xFF00) >> 8;
145 tmp[2] = (tmpf & 0xFF0000) >> 16;
146 ret = i2c_burst_write_dt(&config->i2c, XBR818_LOCK_TIME_1, tmp, 3);
147 } else if ((enum sensor_attribute_xbr818)attr == SENSOR_ATTR_XBR818_RF_POWER) {
148 if (val->val1 > 0x7 || val->val1 < 0) {
149 return -EINVAL;
150 }
151 tmp[0] = val->val1 & 0x7;
152 ret = i2c_reg_write_byte_dt(&config->i2c, XBR818_RF_POWER, tmp[0]);
153 } else if (attr == SENSOR_ATTR_SAMPLING_FREQUENCY) {
154 if (val->val1 > SENSOR_XBR818_CLOCKRATE || val->val1 <= 0) {
155 return -EINVAL;
156 }
157 tmp[0] = SENSOR_XBR818_CLOCKRATE / val->val1;
158 if (tmp[0] > 0xFF) {
159 return -EINVAL;
160 }
161 ret = i2c_reg_write_byte_dt(&config->i2c, XBR818_SAMPLE_RATE_DIVIDER, tmp[0]);
162 } else {
163 ret = xbr818_disable_i2c(dev);
164 if (ret != 0) {
165 return ret;
166 }
167 return -ENODEV;
168 }
169
170 if (ret != 0) {
171 return ret;
172 }
173
174 ret = xbr818_disable_i2c(dev);
175
176 return ret;
177 }
178
xbr818_attr_get(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,struct sensor_value * val)179 static int xbr818_attr_get(const struct device *dev, enum sensor_channel chan,
180 enum sensor_attribute attr, struct sensor_value *val)
181 {
182 const struct xbr818_config *config = dev->config;
183 int ret;
184 uint8_t tmp[3];
185 uint64_t tmpf;
186
187 if (chan != SENSOR_CHAN_PROX) {
188 LOG_ERR("%s: requesting unsupported channel %i", dev->name, chan);
189 return -ENOTSUP;
190 }
191
192 ret = xbr818_enable_i2c(dev);
193 if (ret != 0) {
194 return ret;
195 }
196
197 if (attr == SENSOR_ATTR_LOWER_THRESH) {
198 ret = i2c_burst_read_dt(&config->i2c, XBR818_THRESHOLD_1, tmp, 2);
199 if (ret != 0) {
200 return ret;
201 }
202 val->val1 = tmp[0] & 0xFF;
203 val->val1 |= (uint32_t)tmp[1] << 8;
204 } else if ((enum sensor_attribute_xbr818)attr == SENSOR_ATTR_XBR818_NOISE_FLOOR) {
205 ret = i2c_burst_read_dt(&config->i2c, XBR818_THRESHOLD_NOISE_1, tmp, 2);
206 if (ret != 0) {
207 return ret;
208 }
209 val->val1 = tmp[0] & 0xFF;
210 val->val1 |= (uint32_t)tmp[1] << 8;
211 } else if ((enum sensor_attribute_xbr818)attr == SENSOR_ATTR_XBR818_DELAY_TIME) {
212 ret = i2c_burst_read_dt(&config->i2c, XBR818_DELAY_TIME_1, tmp, 3);
213 if (ret != 0) {
214 return ret;
215 }
216 val->val1 = tmp[0] & 0xFF;
217 val->val1 |= (uint32_t)tmp[1] << 8;
218 val->val1 |= (uint32_t)tmp[2] << 16;
219 tmpf = (uint64_t)val->val1 * 1000000;
220 tmpf /= SENSOR_XBR818_CLOCKRATE;
221 val->val1 = tmpf / 1000000;
222 val->val2 = tmpf - val->val1 * 1000000;
223 } else if ((enum sensor_attribute_xbr818)attr == SENSOR_ATTR_XBR818_LOCK_TIME) {
224 ret = i2c_burst_read_dt(&config->i2c, XBR818_LOCK_TIME_1, tmp, 3);
225 if (ret != 0) {
226 return ret;
227 }
228 val->val1 = tmp[0] & 0xFF;
229 val->val1 |= (uint32_t)tmp[1] << 8;
230 val->val1 |= (uint32_t)tmp[2] << 16;
231 tmpf = (uint64_t)val->val1 * 1000000;
232 tmpf /= SENSOR_XBR818_CLOCKRATE;
233 val->val1 = tmpf / 1000000;
234 val->val2 = tmpf - val->val1 * 1000000;
235 } else if ((enum sensor_attribute_xbr818)attr == SENSOR_ATTR_XBR818_RF_POWER) {
236 ret = i2c_reg_read_byte_dt(&config->i2c, XBR818_RF_POWER, tmp);
237 if (ret != 0) {
238 return ret;
239 }
240 val->val1 = *tmp & 0x7;
241 } else if (attr == SENSOR_ATTR_SAMPLING_FREQUENCY) {
242 ret = i2c_reg_read_byte_dt(&config->i2c, XBR818_SAMPLE_RATE_DIVIDER, tmp);
243 if (ret != 0) {
244 return ret;
245 }
246 val->val1 = SENSOR_XBR818_CLOCKRATE / *tmp;
247 } else {
248 ret = xbr818_disable_i2c(dev);
249 if (ret != 0) {
250 return ret;
251 }
252 return -ENODEV;
253 }
254
255 ret = xbr818_disable_i2c(dev);
256
257 return ret;
258 }
259
xbr818_work(struct k_work * work)260 static void xbr818_work(struct k_work *work)
261 {
262 struct xbr818_data *data = CONTAINER_OF(work, struct xbr818_data, work);
263
264 if (likely(data->handler != NULL)) {
265 data->handler(data->dev, data->trigger);
266 }
267 }
268
xbr818_gpio_callback(const struct device * dev,struct gpio_callback * cb,uint32_t pins)269 static void xbr818_gpio_callback(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
270 {
271 struct xbr818_data *data = CONTAINER_OF(cb, struct xbr818_data, gpio_cb);
272
273 k_work_submit(&data->work);
274 }
275
xbr818_trigger_set(const struct device * dev,const struct sensor_trigger * trig,sensor_trigger_handler_t handler)276 static int xbr818_trigger_set(const struct device *dev, const struct sensor_trigger *trig,
277 sensor_trigger_handler_t handler)
278 {
279 const struct xbr818_config *config = dev->config;
280 struct xbr818_data *data = dev->data;
281 int ret;
282
283 if (trig->chan != SENSOR_CHAN_PROX) {
284 LOG_ERR("%s: requesting unsupported channel %i", dev->name, trig->chan);
285 return -ENOTSUP;
286 }
287
288 if (trig->type != SENSOR_TRIG_MOTION) {
289 LOG_ERR("%s: requesting unsupported trigger %i", dev->name, trig->type);
290 return -ENOTSUP;
291 }
292
293 data->handler = handler;
294 data->trigger = trig;
295 ret = gpio_pin_interrupt_configure_dt(&config->io_val, GPIO_INT_EDGE_RISING);
296 if (ret < 0) {
297 return ret;
298 }
299
300 if (handler) {
301 ret = gpio_add_callback(config->io_val.port, &data->gpio_cb);
302 } else {
303 ret = gpio_remove_callback(config->io_val.port, &data->gpio_cb);
304 }
305
306 return ret;
307 }
308
xbr818_init_defaults(const struct device * dev)309 static int xbr818_init_defaults(const struct device *dev)
310 {
311 const struct xbr818_config *config = dev->config;
312 int ret = 0;
313 uint8_t data[3];
314
315 ret |= i2c_reg_write_byte_dt(&config->i2c, XBR818_IO_ACTIVE_VALUE_REG, 0x03);
316 __ASSERT(ret == 0, "Error sending XBR818 defaults for XBR818_IO_ACTIVE_VALUE_REG");
317 ret |= i2c_reg_write_byte_dt(&config->i2c, XBR818_RF_EN_SEL, 0x20);
318 __ASSERT(ret == 0, "Error sending XBR818 defaults for XBR818_RF_EN_SEL");
319 ret |= i2c_reg_write_byte_dt(&config->i2c, XBR818_SAMPLE_RATE_DIVIDER, 0x20);
320 __ASSERT(ret == 0, "Error sending XBR818 defaults for XBR818_SAMPLE_RATE_DIVIDER");
321 ret |= i2c_reg_write_byte_dt(&config->i2c, XBR818_RF_POWER, 0x45);
322 __ASSERT(ret == 0, "Error sending XBR818 defaults for XBR818_RF_POWER");
323 ret |= i2c_reg_write_byte_dt(&config->i2c, XBR818_TIMER_CTRL, 0x21);
324 __ASSERT(ret == 0, "Error sending XBR818 defaults for XBR818_TIMER_CTRL");
325
326 data[0] = 0x5a;
327 data[1] = 0x01;
328 ret |= i2c_burst_write_dt(&config->i2c, XBR818_THRESHOLD_1, data, 2);
329 __ASSERT(ret == 0, "Error sending XBR818 defaults for XBR818_THRESHOLD");
330
331 data[0] = 0x55;
332 data[1] = 0x01;
333 ret |= i2c_burst_write_dt(&config->i2c, XBR818_THRESHOLD_NOISE_1, data, 2);
334 __ASSERT(ret == 0, "Error sending XBR818 defaults for XBR818_THRESHOLD_NOISE");
335
336 /* 0.1 seconds */
337 data[0] = 0x80;
338 data[1] = 0x0C;
339 data[2] = 0x00;
340 ret |= i2c_burst_write_dt(&config->i2c, XBR818_DELAY_TIME_1, data, 3);
341 __ASSERT(ret == 0, "Error sending XBR818 defaults for XBR818_DELAY_TIME");
342
343 /* 0.5 seconds */
344 data[0] = 0x80;
345 data[1] = 0x3E;
346 data[2] = 0x00;
347 ret |= i2c_burst_write_dt(&config->i2c, XBR818_LOCK_TIME_1, data, 3);
348 __ASSERT(ret == 0, "Error sending XBR818 defaults for XBR818_LOCK_TIME");
349
350 ret |= i2c_reg_write_byte_dt(&config->i2c, XBR818_PIN_SETTINGS, 0x0C);
351 __ASSERT(ret == 0, "Error sending XBR818 defaults for XBR818_PIN_SETTINGS");
352
353 ret |= i2c_reg_write_byte_dt(&config->i2c, XBR818_I2C_OUT, 0x1);
354 __ASSERT(ret == 0, "Error sending XBR818 defaults for XBR818_I2C_OUT");
355
356 return ret;
357 }
358
xbr818_init(const struct device * dev)359 static int xbr818_init(const struct device *dev)
360 {
361 const struct xbr818_config *config = dev->config;
362 struct xbr818_data *data = dev->data;
363 int ret;
364
365 if (!i2c_is_ready_dt(&config->i2c)) {
366 LOG_ERR("I2C device not ready");
367 return -ENODEV;
368 }
369
370 data->dev = dev;
371 data->work.handler = xbr818_work;
372
373 ret = gpio_pin_configure_dt(&config->io_val, GPIO_INPUT);
374 if (ret != 0) {
375 LOG_ERR("%s: could not configure io_val(int) pin", dev->name);
376 return ret;
377 }
378
379 if (config->i2c_en.port) {
380 ret = gpio_pin_configure_dt(&config->i2c_en, GPIO_OUTPUT);
381 if (ret != 0) {
382 LOG_ERR("%s: could not configure i2c_en pin", dev->name);
383 return ret;
384 }
385 }
386
387 ret = xbr818_enable_i2c(dev);
388 if (ret != 0) {
389 return ret;
390 }
391
392 ret = xbr818_init_defaults(dev);
393 if (ret != 0) {
394 LOG_ERR("%s: unable to configure", dev->name);
395 }
396
397 ret = xbr818_disable_i2c(dev);
398 if (ret != 0) {
399 return ret;
400 }
401
402 ret = gpio_pin_interrupt_configure_dt(&config->io_val, GPIO_INT_DISABLE);
403 if (ret) {
404 LOG_ERR("%s: failed to configure gpio interrupt: %d", dev->name, ret);
405 return ret;
406 }
407
408 gpio_init_callback(&data->gpio_cb, xbr818_gpio_callback, BIT(config->io_val.pin));
409
410 return ret;
411 }
412
413 static DEVICE_API(sensor, xbr818_api) = {
414 .sample_fetch = xbr818_sample_fetch,
415 .channel_get = xbr818_channel_get,
416 .attr_set = xbr818_attr_set,
417 .attr_get = xbr818_attr_get,
418 .trigger_set = xbr818_trigger_set,
419 };
420
421 #define XBR818_INIT(inst) \
422 static const struct xbr818_config xbr818_##inst##_config = { \
423 .i2c = I2C_DT_SPEC_INST_GET(inst), \
424 .i2c_en = GPIO_DT_SPEC_GET_OR(DT_INST(inst, phosense_xbr818), i2c_en_gpios, {0}), \
425 .io_val = GPIO_DT_SPEC_GET(DT_INST(inst, phosense_xbr818), int_gpios), \
426 }; \
427 \
428 static struct xbr818_data xbr818_##inst##_data; \
429 \
430 SENSOR_DEVICE_DT_INST_DEFINE(inst, xbr818_init, NULL, &xbr818_##inst##_data, \
431 &xbr818_##inst##_config, POST_KERNEL, \
432 CONFIG_SENSOR_INIT_PRIORITY, &xbr818_api);
433
434 DT_INST_FOREACH_STATUS_OKAY(XBR818_INIT);
435