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)&LTR690_##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(&ltr690_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(&ltr690_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(&ltr690_ctx, LTR690_PS_DATA_0, &reg_data[0], I2C_DATA_LEN, I2C_OP_RETRIES);
315     if (unlikely(ret)) {
316         return -1;
317     }
318     ret = sensor_i2c_read(&ltr690_ctx, LTR690_PS_DATA_1, &reg_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(&ltr690_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(&ltr690_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(&ltr690_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