1 /*
2  * Copyright (c) 2020 Richard Osterloh
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_DRIVERS_SENSOR_VCNL4040_VCNL4040_H_
8 #define ZEPHYR_DRIVERS_SENSOR_VCNL4040_VCNL4040_H_
9 
10 #include <zephyr/drivers/sensor.h>
11 #include <zephyr/drivers/i2c.h>
12 #include <zephyr/drivers/gpio.h>
13 #include <zephyr/kernel.h>
14 
15 /* Registers all 16 bits */
16 #define VCNL4040_REG_ALS_CONF		0x00
17 #define VCNL4040_REG_ALS_THDH		0x01
18 #define VCNL4040_REG_ALS_THDL		0x02
19 #define VCNL4040_REG_PS_CONF		0x03
20 #define VCNL4040_REG_PS_MS		0x04
21 #define VCNL4040_REG_PS_CANC		0x05
22 #define VCNL4040_REG_PS_THDL		0x06
23 #define VCNL4040_REG_PS_THDH		0x07
24 #define VCNL4040_REG_PS_DATA		0x08
25 #define VCNL4040_REG_ALS_DATA		0x09
26 #define VCNL4040_REG_WHITE_DATA		0x0A
27 #define VCNL4040_REG_INT_FLAG		0x0B
28 #define VCNL4040_REG_DEVICE_ID		0x0C
29 
30 #define VCNL4040_RW_REG_COUNT		0x08 /* [0x00, 0x07] */
31 
32 #define VCNL4040_DEFAULT_ID		0x0186
33 
34 #define VCNL4040_LED_I_POS		8
35 #define VCNL4040_PS_HD_POS		11
36 #define VCNL4040_PS_HD_MASK		BIT(VCNL4040_PS_HD_POS)
37 #define VCNL4040_PS_DUTY_POS		6
38 #define VCNL4040_PS_IT_POS		1
39 #define VCNL4040_PS_SD_POS		0
40 #define VCNL4040_PS_SD_MASK		BIT(VCNL4040_PS_SD_POS)
41 #define VCNL4040_ALS_IT_POS		6
42 #define VCNL4040_ALS_INT_EN_POS		1
43 #define VCNL4040_ALS_INT_EN_MASK	BIT(VCNL4040_ALS_INT_EN_POS)
44 #define VCNL4040_ALS_SD_POS		0
45 #define VCNL4040_ALS_SD_MASK		BIT(VCNL4040_ALS_SD_POS)
46 
47 enum led_current {
48 	VCNL4040_LED_CURRENT_50MA,
49 	VCNL4040_LED_CURRENT_75MA,
50 	VCNL4040_LED_CURRENT_100MA,
51 	VCNL4040_LED_CURRENT_120MA,
52 	VCNL4040_LED_CURRENT_140MA,
53 	VCNL4040_LED_CURRENT_160MA,
54 	VCNL4040_LED_CURRENT_180MA,
55 	VCNL4040_LED_CURRENT_200MA,
56 };
57 
58 enum led_duty_cycle {
59 	VCNL4040_LED_DUTY_1_40,
60 	VCNL4040_LED_DUTY_1_80,
61 	VCNL4040_LED_DUTY_1_160,
62 	VCNL4040_LED_DUTY_1_320,
63 };
64 
65 enum ambient_integration_time {
66 	VCNL4040_AMBIENT_INTEGRATION_TIME_80MS,
67 	VCNL4040_AMBIENT_INTEGRATION_TIME_160MS,
68 	VCNL4040_AMBIENT_INTEGRATION_TIME_320MS,
69 	VCNL4040_AMBIENT_INTEGRATION_TIME_640MS,
70 };
71 
72 enum proximity_integration_time {
73 	VCNL4040_PROXIMITY_INTEGRATION_TIME_1T,
74 	VCNL4040_PROXIMITY_INTEGRATION_TIME_1_5T,
75 	VCNL4040_PROXIMITY_INTEGRATION_TIME_2T,
76 	VCNL4040_PROXIMITY_INTEGRATION_TIME_2_5T,
77 	VCNL4040_PROXIMITY_INTEGRATION_TIME_3T,
78 	VCNL4040_PROXIMITY_INTEGRATION_TIME_3_5T,
79 	VCNL4040_PROXIMITY_INTEGRATION_TIME_4T,
80 	VCNL4040_PROXIMITY_INTEGRATION_TIME_8T,
81 };
82 
83 enum proximity_type {
84 	VCNL4040_PROXIMITY_INT_DISABLE,
85 	VCNL4040_PROXIMITY_INT_CLOSE,
86 	VCNL4040_PROXIMITY_INT_AWAY,
87 	VCNL4040_PROXIMITY_INT_CLOSE_AWAY,
88 };
89 
90 enum interrupt_type {
91 	VCNL4040_PROXIMITY_AWAY = 1,
92 	VCNL4040_PROXIMITY_CLOSE,
93 	VCNL4040_AMBIENT_HIGH = 4,
94 	VCNL4040_AMBIENT_LOW,
95 };
96 
97 struct vcnl4040_config {
98 	struct i2c_dt_spec i2c;
99 #ifdef CONFIG_VCNL4040_TRIGGER
100 	struct gpio_dt_spec int_gpio;
101 #endif
102 	enum led_current led_i;
103 	enum led_duty_cycle led_dc;
104 	enum ambient_integration_time als_it;
105 	enum proximity_integration_time proxy_it;
106 	enum proximity_type proxy_type;
107 };
108 
109 struct vcnl4040_data {
110 	struct k_mutex mutex;
111 #ifdef CONFIG_VCNL4040_TRIGGER
112 	const struct device *dev;
113 	struct gpio_callback gpio_cb;
114 	enum interrupt_type int_type;
115 	sensor_trigger_handler_t proxy_handler;
116 	const struct sensor_trigger *proxy_trigger;
117 	sensor_trigger_handler_t als_handler;
118 	const struct sensor_trigger *als_trigger;
119 #endif
120 #ifdef CONFIG_VCNL4040_TRIGGER_OWN_THREAD
121 	K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_VCNL4040_THREAD_STACK_SIZE);
122 	struct k_thread thread;
123 	struct k_sem trig_sem;
124 #endif
125 #ifdef CONFIG_VCNL4040_TRIGGER_GLOBAL_THREAD
126 	struct k_work work;
127 #endif
128 	uint16_t proximity;
129 	uint16_t light;
130 	float sensitivity;
131 };
132 
133 int vcnl4040_read(const struct device *dev, uint8_t reg, uint16_t *out);
134 int vcnl4040_write(const struct device *dev, uint8_t reg, uint16_t value);
135 
136 #ifdef CONFIG_VCNL4040_TRIGGER
137 int vcnl4040_trigger_init(const struct device *dev);
138 
139 int vcnl4040_attr_set(const struct device *dev,
140 		      enum sensor_channel chan,
141 		      enum sensor_attribute attr,
142 		      const struct sensor_value *val);
143 
144 int vcnl4040_trigger_set(const struct device *dev,
145 			 const struct sensor_trigger *trig,
146 			 sensor_trigger_handler_t handler);
147 #endif
148 
149 #endif
150