1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include "aos/kernel.h"
5 #include "sensor_drv_api.h"
6 #include "sensor_hal.h"
7
8 #define LTR690_I2C_SLAVE_ADDR 0x23
9
10 #define LTR690_PS_CONTR 0x81 /* PS operation mode */
11 #define LTR690_PS_LED 0x82 /* LED pulse freq, current duty, peak current */
12 #define LTR690_PS_N_PULSES 0x83 /* PS number of pulses */
13 #define LTR690_PS_MEAS_RATE 0x84 /* measurement rate*/
14 #define LTR690_PART_ID 0x86
15 #define LTR690_MANUFAC_ID 0x87
16 #define LTR690_PS_STATUS 0x91
17 #define LTR690_PS_DATA_0 0x92
18 #define LTR690_PS_DATA_1 0x93
19 #define LTR690_INTERRUPT 0xA6
20 #define LTR690_INTR_PRST 0xA7 /* PS interrupt persist setting */
21 #define LTR690_PS_THRES_UP_0 0xA8 /* PS interrupt upper threshold, lower byte */
22 #define LTR690_PS_THRES_UP_1 0xA9 /* PS interrupt upper threshold, upper byte */
23 #define LTR690_PS_THRES_LOW_0 0xAA /* PS interrupt lower threshold, lower byte */
24 #define LTR690_PS_THRES_LOW_1 0xAB /* PS interrupt lower threshold, upper byte */
25 #define LTR690_PS_CROSSTALK_DATA_LSB 0xB0 /* PS crosstalk data, lower byte */
26 #define LTR690_PS_CROSSTALK_DATA_MSB 0xB1 /* PS crosstalk data, upper byte */
27
28 #define LTR690_ADDR_TRANS(n) ((n) << 1)
29 #define LTR690_I2C_ADDR LTR690_ADDR_TRANS(LTR690_I2C_SLAVE_ADDR)
30 #define LTR690_PART_ID_VAL 0x1E
31 #define LTR690_MANUFAC_ID_VAL 0x05
32
33 #define LTR690_PS_CONTR_REG_SW_RESET__POS (0)
34 #define LTR690_PS_CONTR_REG_SW_RESET__MSK (0x01)
35 #define LTR690_PS_CONTR_REG_SW_RESET__REG (LTR690_PS_CONTR)
36
37 #define LTR690_PS_CONTR_REG_PS_MODE__POS (1)
38 #define LTR690_PS_CONTR_REG_PS_MODE__MSK (0x02)
39 #define LTR690_PS_CONTR_REG_PS_MODE__REG (LTR690_PS_CONTR)
40
41 #define LTR690_PS_CONTR_REG_FTN_NTF_EN__POS (2)
42 #define LTR690_PS_CONTR_REG_FTN_NTF_EN__MSK (0x04)
43 #define LTR690_PS_CONTR_REG_FTN_NTF_EN__REG (LTR690_PS_CONTR)
44
45 #define LTR690_PS_CONTR_REG_PS_OS__POS (3)
46 #define LTR690_PS_CONTR_REG_PS_OS__MSK (0x08)
47 #define LTR690_PS_CONTR_REG_PS_OS__REG (LTR690_PS_CONTR)
48
49 #define LTR690_PS_LED_REG_LED_CURR__POS (0)
50 #define LTR690_PS_LED_REG_LED_CURR__MSK (0x07)
51 #define LTR690_PS_LED_REG_LED_CURR__REG (LTR690_PS_LED)
52
53 #define LTR690_PS_LED_REG_PULSE_WIDTH__POS (4)
54 #define LTR690_PS_LED_REG_PULSE_WIDTH__MSK (0x10)
55 #define LTR690_PS_LED_REG_PULSE_WIDTH__REG (LTR690_PS_LED)
56
57 #define LTR690_PS_N_PULSES_REG_PULSES__POS (0)
58 #define LTR690_PS_N_PULSES_REG_PULSES__MSK (0x0F)
59 #define LTR690_PS_N_PULSES_REG_PULSES__REG (LTR690_PS_N_PULSES)
60
61 #define LTR690_PS_N_PULSES_REG_SEQUENCE__POS (4)
62 #define LTR690_PS_N_PULSES_REG_SEQUENCE__MSK (0xF0)
63 #define LTR690_PS_N_PULSES_REG_SEQUENCE__REG (LTR690_PS_N_PULSES)
64
65 #define LTR690_PS_MEAS_RATE_REG_MEAS_RATE__POS (0)
66 #define LTR690_PS_MEAS_RATE_REG_MEAS_RATE__MSK (0x07)
67 #define LTR690_PS_MEAS_RATE_REG_MEAS_RATE__REG (LTR690_PS_MEAS_RATE)
68
69 #define LTR690_PS_STATUS_REG_PS_DATA_STATUS__POS (0)
70 #define LTR690_PS_STATUS_REG_PS_DATA_STATUS__MSK (0x01)
71 #define LTR690_PS_STATUS_REG_PS_DATA_STATUS__REG (LTR690_PS_STATUS)
72
73 #define LTR690_PS_STATUS_REG_PS_INT_STATUS__POS (1)
74 #define LTR690_PS_STATUS_REG_PS_INT_STATUS__MSK (0x02)
75 #define LTR690_PS_STATUS_REG_PS_INT_STATUS__REG (LTR690_PS_STATUS)
76
77 #define LTR690_PS_STATUS_REG_NTF__POS (6)
78 #define LTR690_PS_STATUS_REG_NTF__MSK (0x40)
79 #define LTR690_PS_STATUS_REG_NTF__REG (LTR690_PS_STATUS)
80
81 #define LTR690_PS_STATUS_REG_FTN__POS (7)
82 #define LTR690_PS_STATUS_REG_FTN__MSK (0x80)
83 #define LTR690_PS_STATUS_REG_FTN__REG (LTR690_PS_STATUS)
84
85 #define LTR690_GET_BITSLICE(regvar, bitname) ((regvar & LTR690_##bitname##__MSK) >> LTR690_##bitname##__POS)
86 #define LTR690_SET_BITSLICE(regvar, bitname, val) ((regvar & ~LTR690_##bitname##__MSK) | ((val<<LTR690_##bitname##__POS)<R690_##bitname##__MSK))
87
88 #define LTR690_WAIT_TIME_PER_CHECK (10)
89 #define LTR690_WAIT_TIME_TOTAL (50)
90
91 typedef enum {
92 LTR690_SW_RESET_NEG = 0x00,
93 LTR690_SW_RESET = 0x01,
94 } LTR690_CFG_SW_RESET;
95
96 typedef enum {
97 LTR690_PS_STANDBY = 0x00,
98 LTR690_PS_ACTIVE = 0x01,
99 } LTR690_CFG_PS_MODE;
100
101 typedef enum {
102 LTR690_FTN_NTF_EN_FALSE = 0x00,
103 LTR690_FTN_NTF_EN_TRUE = 0x01,
104 } LTR690_CFG_FTN_NTF_EN;
105
106 typedef enum {
107 LTR690_PS_OS_FALSE = 0x00,
108 LTR690_PS_OS_TRUE = 0x01,
109 } LTR690_CFG_PS_OS;
110
111 typedef enum {
112 LTR690_PS_LED_CURRENT_0 = 0x00, /* LED pulse current level = 0mA */
113 LTR690_PS_LED_CURRENT_20 = 0x01, /* LED pulse current level = 20mA */
114 LTR690_PS_LED_CURRENT_50 = 0x02, /* LED pulse current level = 50mA */
115 LTR690_PS_LED_CURRENT_100 = 0x03, /* LED pulse current level = 100mA (default) */
116 LTR690_PS_LED_CURRENT_150 = 0x04, /* LED pulse current level = 150mA */
117 LTR690_PS_LED_CURRENT_200 = 0x05, /* LED pulse current level = 200mA */
118 LTR690_PS_LED_CURRENT_250 = 0x06, /* LED pulse current level = 250mA */
119 LTR690_PS_LED_CURRENT_300 = 0x07, /* LED pulse current level = 300mA */
120 } LTR690_CFG_PS_LED_LED_CURRENT;
121
122 typedef enum {
123 LTR690_PS_PULSE_WIDTH_64 = 0x00, /* LED pulse width = 64us */
124 LTR690_PS_PULSE_WIDTH_16 = 0x02, /* LED pulse width = 16us */
125 LTR690_PS_PULSE_WIDTH_32 = 0x03, /* LED pulse width = 32us (default) */
126 } LTR690_CFG_PS_LED_PULSE_WIDTH;
127
128 typedef enum {
129 LTR690_PS_MEAS_RATE_6_125 = 0x00, /* PS Measurement Repeat Rate = 6.125ms */
130 LTR690_PS_MEAS_RATE_12_5 = 0x01, /* PS Measurement Repeat Rate = 12.5ms */
131 LTR690_PS_MEAS_RATE_25 = 0x02, /* PS Measurement Repeat Rate = 25ms */
132 LTR690_PS_MEAS_RATE_50 = 0x03, /* PS Measurement Repeat Rate = 50ms (default) */
133 LTR690_PS_MEAS_RATE_100 = 0x04, /* PS Measurement Repeat Rate = 100ms */
134 LTR690_PS_MEAS_RATE_200 = 0x05, /* PS Measurement Repeat Rate = 200ms */
135 LTR690_PS_MEAS_RATE_400 = 0x06, /* PS Measurement Repeat Rate = 400ms */
136 LTR690_PS_MEAS_RATE_800 = 0x07, /* PS Measurement Repeat Rate = 800ms */
137 } LTR690_CFG_PS_MEAS_RATE;
138
139 typedef enum {
140 LTR690_PS_DATA_STATUS_OLD = 0x00,
141 LTR690_PS_DATA_STATUS_NEW = 0x01,
142 } LTR690_CFG_PS_DATA_STATUS;
143
144 i2c_dev_t ltr690_ctx = {
145 .port = 3,
146 .config.address_width = 8,
147 .config.freq = 100000,
148 .config.dev_addr = LTR690_I2C_ADDR,
149 };
150
151 static uint8_t g_init_bitwise = 0;
152
drv_ps_liteon_ltr690_validate_id(i2c_dev_t * drv,uint8_t part_id,uint8_t manufac_id)153 static int drv_ps_liteon_ltr690_validate_id(i2c_dev_t* drv, uint8_t part_id, uint8_t manufac_id)
154 {
155 int ret = 0;
156 uint8_t part_id_value = 0;
157 uint8_t manufac_id_value = 0;
158
159 if (drv == NULL) {
160 return -1;
161 }
162
163 ret = sensor_i2c_read(drv, LTR690_PART_ID, &part_id_value, I2C_DATA_LEN, I2C_OP_RETRIES);
164 if (unlikely(ret)) {
165 return ret;
166 }
167
168 ret = sensor_i2c_read(drv, LTR690_MANUFAC_ID, &manufac_id_value, I2C_DATA_LEN, I2C_OP_RETRIES);
169 if (unlikely(ret)) {
170 return ret;
171 }
172
173 if (part_id_value != part_id || manufac_id_value != manufac_id) {
174 return -1;
175 }
176
177 return 0;
178 }
179
drv_ps_liteon_ltr690_set_power_mode(i2c_dev_t * drv,dev_power_mode_e mode)180 static int drv_ps_liteon_ltr690_set_power_mode(i2c_dev_t* drv, dev_power_mode_e mode)
181 {
182 int ret = 0;
183 uint8_t dev_mode = 0;
184 uint8_t value = 0;
185
186 ret = sensor_i2c_read(drv, LTR690_PS_CONTR, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
187 if (unlikely(ret)) {
188 return ret;
189 }
190
191 switch (mode) {
192 case DEV_POWER_OFF:
193 case DEV_SLEEP:
194 dev_mode = LTR690_SET_BITSLICE(value, PS_CONTR_REG_PS_MODE, LTR690_PS_STANDBY);
195 break;
196 case DEV_POWER_ON:
197 dev_mode = LTR690_SET_BITSLICE(value, PS_CONTR_REG_PS_MODE, LTR690_PS_ACTIVE);
198 break;
199 default:
200 return -1;
201 }
202
203 ret = sensor_i2c_write(drv, LTR690_PS_CONTR, &dev_mode, I2C_DATA_LEN, I2C_OP_RETRIES);
204 if (unlikely(ret)) {
205 return ret;
206 }
207
208 return 0;
209 }
210
drv_ps_liteon_ltr690_is_ready(i2c_dev_t * drv)211 UNUSED static int drv_ps_liteon_ltr690_is_ready(i2c_dev_t* drv)
212 {
213 int ret = 0;
214 uint8_t value = 0;
215
216 ret = sensor_i2c_read(drv, LTR690_PS_STATUS, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
217 if (unlikely(ret)) {
218 return 0;
219 }
220
221 ret = (LTR690_GET_BITSLICE(value, PS_STATUS_REG_PS_DATA_STATUS) == LTR690_PS_DATA_STATUS_NEW) ? 1 : 0;
222
223 return ret;
224 }
225
drv_ps_liteon_ltr690_set_default_config(i2c_dev_t * drv)226 static int drv_ps_liteon_ltr690_set_default_config(i2c_dev_t* drv)
227 {
228 int ret = 0;
229 uint8_t value = 0;
230
231 ret = sensor_i2c_read(drv, LTR690_PS_CONTR, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
232 if (unlikely(ret)) {
233 return ret;
234 }
235 value = LTR690_SET_BITSLICE(value, PS_CONTR_REG_FTN_NTF_EN, LTR690_FTN_NTF_EN_FALSE);
236 value = LTR690_SET_BITSLICE(value, PS_CONTR_REG_PS_OS, LTR690_PS_OS_FALSE);
237 ret = sensor_i2c_write(drv, LTR690_PS_CONTR, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
238 if (unlikely(ret)) {
239 return ret;
240 }
241
242 value = 0xC0;
243 value = LTR690_SET_BITSLICE(value, PS_LED_REG_LED_CURR, LTR690_PS_LED_CURRENT_100);
244 value = LTR690_SET_BITSLICE(value, PS_LED_REG_PULSE_WIDTH, LTR690_PS_PULSE_WIDTH_32);
245 ret = sensor_i2c_write(drv, LTR690_PS_LED, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
246 if (unlikely(ret)) {
247 return ret;
248 }
249
250 value = 0x88;
251 ret = sensor_i2c_write(drv, LTR690_PS_N_PULSES, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
252 if (unlikely(ret)) {
253 return ret;
254 }
255
256 value = 0x20;
257 value = LTR690_SET_BITSLICE(value, PS_MEAS_RATE_REG_MEAS_RATE, LTR690_PS_MEAS_RATE_100);
258 ret = sensor_i2c_write(drv, LTR690_PS_MEAS_RATE, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
259 if (unlikely(ret)) {
260 return ret;
261 }
262
263 return 0;
264 }
265
drv_ps_liteon_ltr690_irq_handle(void)266 static void drv_ps_liteon_ltr690_irq_handle(void)
267 {
268 /* no handle so far */
269 }
270
drv_ps_liteon_ltr690_open(void)271 static int drv_ps_liteon_ltr690_open(void)
272 {
273 int ret = 0;
274
275 ret = drv_ps_liteon_ltr690_set_power_mode(<r690_ctx, DEV_POWER_ON);
276 if (unlikely(ret)) {
277 return -1;
278 }
279
280 LOG("%s %s successfully \n", SENSOR_STR, __func__);
281 return 0;
282
283 }
284
drv_ps_liteon_ltr690_close(void)285 static int drv_ps_liteon_ltr690_close(void)
286 {
287 int ret = 0;
288
289 ret = drv_ps_liteon_ltr690_set_power_mode(<r690_ctx, DEV_POWER_OFF);
290 if (unlikely(ret)) {
291 return -1;
292 }
293
294 LOG("%s %s successfully \n", SENSOR_STR, __func__);
295 return 0;
296 }
297
drv_ps_liteon_ltr690_read(void * buf,size_t len)298 static int drv_ps_liteon_ltr690_read(void *buf, size_t len)
299 {
300 int ret = 0;
301 size_t size;
302 uint8_t reg_data[2] = { 0 };
303 proximity_data_t * pdata = (proximity_data_t *) buf;
304
305 if (buf == NULL) {
306 return -1;
307 }
308
309 size = sizeof(proximity_data_t);
310 if (len < size) {
311 return -1;
312 }
313
314 ret = sensor_i2c_read(<r690_ctx, LTR690_PS_DATA_0, ®_data[0], I2C_DATA_LEN, I2C_OP_RETRIES);
315 if (unlikely(ret)) {
316 return -1;
317 }
318 ret = sensor_i2c_read(<r690_ctx, LTR690_PS_DATA_1, ®_data[1], I2C_DATA_LEN, I2C_OP_RETRIES);
319 if (unlikely(ret)) {
320 return -1;
321 }
322
323 pdata->present = (((uint32_t) (reg_data[1] & 0xFF) << 8) | reg_data[0]);
324 pdata->timestamp = aos_now_ms();
325
326 return (int) size;
327 }
328
drv_ps_liteon_ltr690_write(const void * buf,size_t len)329 static int drv_ps_liteon_ltr690_write(const void *buf, size_t len)
330 {
331 (void) buf;
332 (void) len;
333
334 return 0;
335 }
336
drv_ps_liteon_ltr690_ioctl(int cmd,unsigned long arg)337 static int drv_ps_liteon_ltr690_ioctl(int cmd, unsigned long arg)
338 {
339 int ret = 0;
340
341 switch (cmd) {
342 case SENSOR_IOCTL_SET_POWER: {
343 ret = drv_ps_liteon_ltr690_set_power_mode(<r690_ctx, arg);
344 if (unlikely(ret)) {
345 return -1;
346 }
347 } break;
348 case SENSOR_IOCTL_GET_INFO: {
349 /* fill the dev info here */
350 dev_sensor_info_t *info = (dev_sensor_info_t *) arg;
351 info->vendor = DEV_SENSOR_VENDOR_LITEON;
352 info->model = "LTR690";
353 info->unit = cm;
354 } break;
355 default:
356 return -1;
357 }
358
359 LOG("%s %s successfully \n", SENSOR_STR, __func__);
360 return 0;
361 }
362
drv_ps_liteon_ltr690_init(void)363 int drv_ps_liteon_ltr690_init(void)
364 {
365 int ret = 0;
366 sensor_obj_t sensor_ps;
367 memset(&sensor_ps, 0, sizeof(sensor_ps));
368
369 if (!g_init_bitwise) {
370 ret = drv_ps_liteon_ltr690_validate_id(<r690_ctx, LTR690_PART_ID_VAL, LTR690_MANUFAC_ID_VAL);
371 if (unlikely(ret)) {
372 return -1;
373 }
374 }
375
376 if (!g_init_bitwise) {
377 /* fill the sensor_ps obj parameters here */
378 sensor_ps.tag = TAG_DEV_PS;
379 sensor_ps.path = dev_ps_path;
380 sensor_ps.io_port = I2C_PORT;
381 sensor_ps.mode = DEV_POLLING;
382 sensor_ps.power = DEV_POWER_OFF;
383 sensor_ps.open = drv_ps_liteon_ltr690_open;
384 sensor_ps.close = drv_ps_liteon_ltr690_close;
385 sensor_ps.read = drv_ps_liteon_ltr690_read;
386 sensor_ps.write = drv_ps_liteon_ltr690_write;
387 sensor_ps.ioctl = drv_ps_liteon_ltr690_ioctl;
388 sensor_ps.irq_handle = drv_ps_liteon_ltr690_irq_handle;
389
390 ret = sensor_create_obj(&sensor_ps);
391 if (unlikely(ret)) {
392 return -1;
393 }
394
395 ret = drv_ps_liteon_ltr690_set_default_config(<r690_ctx);
396 if (unlikely(ret)) {
397 return -1;
398 }
399
400 g_init_bitwise = 1;
401 }
402
403 LOG("%s %s successfully \n", SENSOR_STR, __func__);
404 return 0;
405 }
406
407 SENSOR_DRV_ADD(drv_ps_liteon_ltr690_init);
408
409