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 LTR390_I2C_SLAVE_ADDR                           0x53
9 
10 #define LTR390_MAIN_CTRL                                0x00 /* Operation mode control */
11 #define LTR390_ALS_UVS_MEAS_RATE                        0x04 /* Measurement rate and resolution */
12 #define LTR390_ALS_UVS_GAIN                             0x05 /* Analog gain range*/
13 #define LTR390_PART_ID                                  0x06
14 #define LTR390_MAIN_STATUS                              0x07
15 #define LTR390_ALS_DATA_0                               0x0D
16 #define LTR390_ALS_DATA_1                               0x0E
17 #define LTR390_ALS_DATA_2                               0x0F
18 #define LTR390_UVS_DATA_0                               0x10
19 #define LTR390_UVS_DATA_1                               0x11
20 #define LTR390_UVS_DATA_2                               0x12
21 #define LTR390_INT_CFG                                  0x19
22 #define LTR390_INT_PST                                  0x1A /* Interrupt persist setting */
23 #define LTR390_ALS_UVS_THRES_UP_0                       0x21 /* Interrupt upper threshold, lower byte */
24 #define LTR390_ALS_UVS_THRES_UP_1                       0x22 /* Interrupt upper threshold, middle byte */
25 #define LTR390_ALS_UVS_THRES_UP_2                       0x23 /* Interrupt upper threshold, upper byte */
26 #define LTR390_ALS_UVS_THRES_LOW_0                      0x24 /* Interrupt lower threshold, lower byte */
27 #define LTR390_ALS_UVS_THRES_LOW_1                      0x25 /* Interrupt lower threshold, middle byte */
28 #define LTR390_ALS_UVS_THRES_LOW_2                      0x26 /* Interrupt lower threshold, upper byte */
29 
30 #define LTR390_ADDR_TRANS(n)                            ((n) << 1)
31 #define LTR390_I2C_ADDR                                 LTR390_ADDR_TRANS(LTR390_I2C_SLAVE_ADDR)
32 #define LTR390_PART_ID_VAL                              0xB2
33 
34 #define LTR390_MAIN_CTRL_REG_ALS_UVS_EN__POS            (1)
35 #define LTR390_MAIN_CTRL_REG_ALS_UVS_EN__MSK            (0x02)
36 #define LTR390_MAIN_CTRL_REG_ALS_UVS_EN__REG            (LTR390_MAIN_CTRL)
37 
38 #define LTR390_MAIN_CTRL_REG_UVS_MODE__POS              (3)
39 #define LTR390_MAIN_CTRL_REG_UVS_MODE__MSK              (0x08)
40 #define LTR390_MAIN_CTRL_REG_UVS_MODE__REG              (LTR390_MAIN_CTRL)
41 
42 #define LTR390_MAIN_CTRL_REG_SW_RESET__POS              (4)
43 #define LTR390_MAIN_CTRL_REG_SW_RESET__MSK              (0x10)
44 #define LTR390_MAIN_CTRL_REG_SW_RESET__REG              (LTR390_MAIN_CTRL)
45 
46 #define LTR390_ALS_UVS_MEAS_RATE_REG_MEAS_RATE__POS     (0)
47 #define LTR390_ALS_UVS_MEAS_RATE_REG_MEAS_RATE__MSK     (0x07)
48 #define LTR390_ALS_UVS_MEAS_RATE_REG_MEAS_RATE__REG     (LTR390_ALS_UVS_MEAS_RATE)
49 
50 #define LTR390_ALS_UVS_MEAS_RATE_REG_RESOLUTION__POS    (4)
51 #define LTR390_ALS_UVS_MEAS_RATE_REG_RESOLUTION__MSK    (0x70)
52 #define LTR390_ALS_UVS_MEAS_RATE_REG_RESOLUTION__REG    (LTR390_ALS_UVS_MEAS_RATE)
53 
54 #define LTR390_ALS_UVS_GAIN_REG_GAIN_RANGE__POS         (0)
55 #define LTR390_ALS_UVS_GAIN_REG_GAIN_RANGE__MSK         (0x07)
56 #define LTR390_ALS_UVS_GAIN_REG_GAIN_RANGE__REG         (LTR390_ALS_UVS_GAIN)
57 
58 #define LTR390_MAIN_STATUS_REG_ALS_UVS_DATA_STATUS__POS (3)
59 #define LTR390_MAIN_STATUS_REG_ALS_UVS_DATA_STATUS__MSK (0x08)
60 #define LTR390_MAIN_STATUS_REG_ALS_UVS_DATA_STATUS__REG (LTR390_MAIN_STATUS)
61 
62 #define LTR390_MAIN_STATUS_REG_ALS_UVS_INT_STATUS__POS  (4)
63 #define LTR390_MAIN_STATUS_REG_ALS_UVS_INT_STATUS__MSK  (0x10)
64 #define LTR390_MAIN_STATUS_REG_ALS_UVS_INT_STATUS__REG  (LTR390_MAIN_STATUS)
65 
66 #define LTR390_MAIN_STATUS_REG_POWER_ON_STATUS__POS     (5)
67 #define LTR390_MAIN_STATUS_REG_POWER_ON_STATUS__MSK     (0x20)
68 #define LTR390_MAIN_STATUS_REG_POWER_ON_STATUS__REG     (LTR390_MAIN_STATUS)
69 
70 #define LTR390_INT_CFG_REG_LS_INT_EN__POS               (2)
71 #define LTR390_INT_CFG_REG_LS_INT_EN__MSK               (0x04)
72 #define LTR390_INT_CFG_REG_LS_INT_EN__REG               (LTR390_INT_CFG)
73 
74 #define LTR390_INT_CFG_REG_LS_INT_SEL__POS              (4)
75 #define LTR390_INT_CFG_REG_LS_INT_SEL__MSK              (0x30)
76 #define LTR390_INT_CFG_REG_LS_INT_SEL__REG              (LTR390_INT_CFG)
77 
78 #define LTR390_INT_PST_REG_ALS_UV_PERSIST__POS          (4)
79 #define LTR390_INT_PST_REG_ALS_UV_PERSIST__MSK          (0xF0)
80 #define LTR390_INT_PST_REG_ALS_UV_PERSIST__REG          (LTR390_INT_PST)
81 
82 #define LTR390_GET_BITSLICE(regvar, bitname)            ((regvar & LTR390_##bitname##__MSK) >> LTR390_##bitname##__POS)
83 #define LTR390_SET_BITSLICE(regvar, bitname, val)       ((regvar & ~LTR390_##bitname##__MSK) | ((val<<LTR390_##bitname##__POS)&LTR390_##bitname##__MSK))
84 
85 #define LTR390_WAIT_TIME_PER_CHECK                      (10)
86 #define LTR390_WAIT_TIME_TOTAL                          (100)
87 
88 typedef enum {
89     LTR390_ALS_UVS_STANDBY = 0x00,
90     LTR390_ALS_UVS_ACTIVE = 0x01,
91 } LTR390_CFG_ALS_UVS_EN;
92 
93 typedef enum {
94     LTR390_ALS_MODE = 0x00,
95     LTR390_UVS_MODE = 0x01,
96 } LTR390_CFG_ALS_UVS_MODE;
97 
98 typedef enum {
99     LTR390_SW_RESET_FALSE = 0x00,
100     LTR390_SW_RESET_TRUE = 0x01,
101 } LTR390_CFG_SW_RESET;
102 
103 typedef enum {
104     LTR390_ALS_UVS_MEAS_RATE_25 = 0x00,                      /* Measurement Repeat Rate = 25ms */
105     LTR390_ALS_UVS_MEAS_RATE_50 = 0x01,                      /* Measurement Repeat Rate = 50ms */
106     LTR390_ALS_UVS_MEAS_RATE_100 = 0x02,                     /* Measurement Repeat Rate = 100ms (default) */
107     LTR390_ALS_UVS_MEAS_RATE_200 = 0x03,                     /* Measurement Repeat Rate = 200ms */
108     LTR390_ALS_UVS_MEAS_RATE_500 = 0x04,                     /* Measurement Repeat Rate = 500ms */
109     LTR390_ALS_UVS_MEAS_RATE_1000 = 0x05,                    /* Measurement Repeat Rate = 1000ms */
110     LTR390_ALS_UVS_MEAS_RATE_2000 = 0x06,                    /* Measurement Repeat Rate = 2000ms */
111 } LTR390_CFG_ALS_UVS_MEAS_RATE;
112 
113 typedef enum {
114     LTR390_ALS_UVS_RESOLUTION_20BIT = 0x00,                  /* 20 bit, conversion time = 400ms */
115     LTR390_ALS_UVS_RESOLUTION_19BIT = 0x01,                  /* 19 bit, conversion time = 200ms */
116     LTR390_ALS_UVS_RESOLUTION_18BIT = 0x02,                  /* 18 bit, conversion time = 100ms (default) */
117     LTR390_ALS_UVS_RESOLUTION_17BIT = 0x03,                  /* 17 bit, conversion time = 50ms */
118     LTR390_ALS_UVS_RESOLUTION_16BIT = 0x04,                  /* 16 bit, conversion time = 25ms */
119     LTR390_ALS_UVS_RESOLUTION_13BIT = 0x05,                  /* 13 bit, conversion time = 12.5ms */
120 } LTR390_CFG_ALS_UVS_RESOLUTION;
121 
122 typedef enum {
123     LTR390_ALS_UVS_GAIN_RANGE_1 = 0x00,
124     LTR390_ALS_UVS_GAIN_RANGE_3 = 0x01,
125     LTR390_ALS_UVS_GAIN_RANGE_6 = 0x02,
126     LTR390_ALS_UVS_GAIN_RANGE_9 = 0x03,
127     LTR390_ALS_UVS_GAIN_RANGE_18 = 0x04,
128 } LTR390_CFG_ALS_UVS_GAIN_RANGE;
129 
130 typedef enum {
131     LTR390_ALS_UVS_DATA_STATUS_OLD = 0x00,
132     LTR390_ALS_UVS_DATA_STATUS_NEW = 0x01,
133 } LTR390_CFG_ALS_UVS_DATA_STATUS;
134 
135 typedef enum {
136     LTR390_ALS_UVS_INT_STATUS_INACTIVE = 0x00,
137     LTR390_ALS_UVS_INT_STATUS_ACTIVE = 0x01,
138 } LTR390_CFG_ALS_UVS_INT_STATUS;
139 
140 typedef enum {
141     LTR390_ALS_UVS_POWER_ON_STATUS_FALSE = 0x00,
142     LTR390_ALS_UVS_POWER_ON_STATUS_TRUE = 0x01,
143 } LTR390_CFG_ALS_UVS_POWER_ON_STATUS;
144 
145 typedef enum {
146     LTR390_LS_INT_DISABLE = 0x00,
147     LTR390_LS_INT_ENABLE = 0x01,
148 } LTR390_CFG_LS_INT_EN;
149 
150 typedef enum {
151     LTR390_LS_INT_SEL_ALS_CHANNEL = 0x01,
152     LTR390_LS_INT_SEL_UVS_CHANNEL = 0x03,
153 } LTR390_CFG_LS_INT_SEL;
154 
155 i2c_dev_t ltr390_ctx = {
156     .port = 3,
157     .config.address_width = 8,
158     .config.freq = 100000,
159     .config.dev_addr = LTR390_I2C_ADDR,
160 };
161 
162 static uint8_t g_init_bitwise = 0;
163 
drv_uv_liteon_ltr390_validate_id(i2c_dev_t * drv,uint8_t part_id)164 static int drv_uv_liteon_ltr390_validate_id(i2c_dev_t* drv, uint8_t part_id)
165 {
166     int     ret = 0;
167     uint8_t part_id_value = 0;
168 
169     if (drv == NULL) {
170         return -1;
171     }
172 
173     ret = sensor_i2c_read(drv, LTR390_PART_ID, &part_id_value, I2C_DATA_LEN, I2C_OP_RETRIES);
174     if (unlikely(ret)) {
175         return ret;
176     }
177 
178     if (part_id_value != part_id) {
179         return -1;
180     }
181 
182     return 0;
183 }
184 
drv_uv_liteon_ltr390_set_power_mode(i2c_dev_t * drv,dev_power_mode_e mode)185 static int drv_uv_liteon_ltr390_set_power_mode(i2c_dev_t* drv, dev_power_mode_e mode)
186 {
187     int     ret = 0;
188     uint8_t dev_mode = 0;
189     uint8_t value = 0;
190 
191     ret = sensor_i2c_read(drv, LTR390_MAIN_CTRL, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
192     if (unlikely(ret)) {
193         return ret;
194     }
195 
196     switch (mode) {
197         case DEV_POWER_OFF:
198         case DEV_SLEEP:
199             dev_mode = LTR390_SET_BITSLICE(value, MAIN_CTRL_REG_ALS_UVS_EN, LTR390_ALS_UVS_STANDBY);
200             break;
201         case DEV_POWER_ON:
202             dev_mode = LTR390_SET_BITSLICE(value, MAIN_CTRL_REG_ALS_UVS_EN, LTR390_ALS_UVS_ACTIVE);
203             break;
204         default:
205             return -1;
206     }
207 
208     ret = sensor_i2c_write(drv, LTR390_MAIN_CTRL, &dev_mode, I2C_DATA_LEN, I2C_OP_RETRIES);
209     if (unlikely(ret)) {
210         return ret;
211     }
212 
213     return 0;
214 }
215 
drv_uv_liteon_ltr390_is_ready(i2c_dev_t * drv)216 UNUSED static int drv_uv_liteon_ltr390_is_ready(i2c_dev_t* drv)
217 {
218     int     ret = 0;
219     uint8_t value = 0;
220 
221     ret = sensor_i2c_read(drv, LTR390_MAIN_STATUS, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
222     if (unlikely(ret)) {
223         return 0;
224     }
225 
226     ret = (LTR390_GET_BITSLICE(value, MAIN_STATUS_REG_ALS_UVS_DATA_STATUS) == LTR390_ALS_UVS_DATA_STATUS_NEW) ? 1 : 0;
227 
228     return ret;
229 }
230 
drv_uv_liteon_ltr390_set_default_config(i2c_dev_t * drv)231 static int drv_uv_liteon_ltr390_set_default_config(i2c_dev_t* drv)
232 {
233     int     ret = 0;
234     uint8_t value = 0;
235 
236     ret = sensor_i2c_read(drv, LTR390_MAIN_CTRL, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
237     if (unlikely(ret)) {
238         return ret;
239     }
240     value = LTR390_SET_BITSLICE(value, MAIN_CTRL_REG_UVS_MODE, LTR390_UVS_MODE);
241     ret = sensor_i2c_write(drv, LTR390_MAIN_CTRL, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
242     if (unlikely(ret)) {
243         return ret;
244     }
245 
246     value = 0;
247     value = LTR390_SET_BITSLICE(value, ALS_UVS_MEAS_RATE_REG_MEAS_RATE, LTR390_ALS_UVS_MEAS_RATE_100);
248     value = LTR390_SET_BITSLICE(value, ALS_UVS_MEAS_RATE_REG_RESOLUTION, LTR390_ALS_UVS_RESOLUTION_16BIT);
249     ret = sensor_i2c_write(drv, LTR390_ALS_UVS_MEAS_RATE, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
250     if (unlikely(ret)) {
251         return ret;
252     }
253 
254     value = 0;
255     value = LTR390_SET_BITSLICE(value, ALS_UVS_GAIN_REG_GAIN_RANGE, LTR390_ALS_UVS_GAIN_RANGE_18);
256     ret = sensor_i2c_write(drv, LTR390_ALS_UVS_GAIN, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
257     if (unlikely(ret)) {
258         return ret;
259     }
260 
261     value = 0;
262     value = LTR390_SET_BITSLICE(value, INT_CFG_REG_LS_INT_EN, LTR390_LS_INT_DISABLE);
263     value = LTR390_SET_BITSLICE(value, INT_CFG_REG_LS_INT_SEL, LTR390_LS_INT_SEL_ALS_CHANNEL);
264     ret = sensor_i2c_write(drv, LTR390_INT_CFG, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
265     if (unlikely(ret)) {
266         return ret;
267     }
268 
269     return 0;
270 }
271 
drv_uv_liteon_ltr390_irq_handle(void)272 static void drv_uv_liteon_ltr390_irq_handle(void)
273 {
274     /* no handle so far */
275 }
276 
drv_uv_liteon_ltr390_open(void)277 static int drv_uv_liteon_ltr390_open(void)
278 {
279     int ret = 0;
280 
281     ret = drv_uv_liteon_ltr390_set_power_mode(&ltr390_ctx, DEV_POWER_ON);
282     if (unlikely(ret)) {
283         return -1;
284     }
285 
286     LOG("%s %s successfully \n", SENSOR_STR, __func__);
287     return 0;
288 
289 }
290 
drv_uv_liteon_ltr390_close(void)291 static int drv_uv_liteon_ltr390_close(void)
292 {
293     int ret = 0;
294 
295     ret = drv_uv_liteon_ltr390_set_power_mode(&ltr390_ctx, DEV_POWER_OFF);
296     if (unlikely(ret)) {
297         return -1;
298     }
299 
300     LOG("%s %s successfully \n", SENSOR_STR, __func__);
301     return 0;
302 }
303 
drv_uv_liteon_ltr390_read(void * buf,size_t len)304 static int drv_uv_liteon_ltr390_read(void *buf, size_t len)
305 {
306     int ret = 0;
307     size_t size;
308     uint8_t reg_data[3] = { 0 };
309     uv_data_t * pdata = (uv_data_t *) buf;
310 
311     if (buf == NULL) {
312         return -1;
313     }
314 
315     size = sizeof(uv_data_t);
316     if (len < size) {
317         return -1;
318     }
319 
320     ret = sensor_i2c_read(&ltr390_ctx, LTR390_UVS_DATA_0, &reg_data[0], I2C_DATA_LEN, I2C_OP_RETRIES);
321     if (unlikely(ret)) {
322         return -1;
323     }
324     ret = sensor_i2c_read(&ltr390_ctx, LTR390_UVS_DATA_1, &reg_data[1], I2C_DATA_LEN, I2C_OP_RETRIES);
325     if (unlikely(ret)) {
326         return -1;
327     }
328     ret = sensor_i2c_read(&ltr390_ctx, LTR390_UVS_DATA_2, &reg_data[2], I2C_DATA_LEN, I2C_OP_RETRIES);
329     if (unlikely(ret)) {
330         return -1;
331     }
332 
333     pdata->uvi = ((((uint16_t) (reg_data[1] & 0xFF)) << 8) | reg_data[0]);
334     pdata->timestamp = aos_now_ms();
335 
336     return (int) size;
337 }
338 
drv_uv_liteon_ltr390_write(const void * buf,size_t len)339 static int drv_uv_liteon_ltr390_write(const void *buf, size_t len)
340 {
341     (void) buf;
342     (void) len;
343 
344     return 0;
345 }
346 
drv_uv_liteon_ltr390_ioctl(int cmd,unsigned long arg)347 static int drv_uv_liteon_ltr390_ioctl(int cmd, unsigned long arg)
348 {
349     int ret = 0;
350 
351     switch (cmd) {
352         case SENSOR_IOCTL_SET_POWER: {
353             ret = drv_uv_liteon_ltr390_set_power_mode(&ltr390_ctx, arg);
354             if (unlikely(ret)) {
355                 return -1;
356             }
357         } break;
358         case SENSOR_IOCTL_GET_INFO: {
359             /* fill the dev info here */
360             dev_sensor_info_t *info = (dev_sensor_info_t *) arg;
361             info->vendor = DEV_SENSOR_VENDOR_LITEON;
362             info->model = "LTR390";
363             info->unit = lux;
364         } break;
365         default:
366             return -1;
367     }
368 
369     LOG("%s %s successfully \n", SENSOR_STR, __func__);
370     return 0;
371 }
372 
drv_uv_liteon_ltr390_init(void)373 int drv_uv_liteon_ltr390_init(void)
374 {
375     int ret = 0;
376     sensor_obj_t sensor_uv;
377     memset(&sensor_uv, 0, sizeof(sensor_uv));
378 
379     if (!g_init_bitwise) {
380         ret = drv_uv_liteon_ltr390_validate_id(&ltr390_ctx, LTR390_PART_ID_VAL);
381         if (unlikely(ret)) {
382             return -1;
383         }
384     }
385 
386     if (!g_init_bitwise) {
387         /* fill the sensor_uv obj parameters here */
388         sensor_uv.tag = TAG_DEV_UV;
389         sensor_uv.path = dev_uv_path;
390         sensor_uv.io_port = I2C_PORT;
391         sensor_uv.mode = DEV_POLLING;
392         sensor_uv.power = DEV_POWER_OFF;
393         sensor_uv.open = drv_uv_liteon_ltr390_open;
394         sensor_uv.close = drv_uv_liteon_ltr390_close;
395         sensor_uv.read = drv_uv_liteon_ltr390_read;
396         sensor_uv.write = drv_uv_liteon_ltr390_write;
397         sensor_uv.ioctl = drv_uv_liteon_ltr390_ioctl;
398         sensor_uv.irq_handle = drv_uv_liteon_ltr390_irq_handle;
399 
400         ret = sensor_create_obj(&sensor_uv);
401         if (unlikely(ret)) {
402             return -1;
403         }
404 
405         ret = drv_uv_liteon_ltr390_set_default_config(&ltr390_ctx);
406         if (unlikely(ret)) {
407             return -1;
408         }
409 
410         g_init_bitwise = 1;
411     }
412 
413     LOG("%s %s successfully \n", SENSOR_STR, __func__);
414     return 0;
415 }
416 
417 SENSOR_DRV_ADD(drv_uv_liteon_ltr390_init);
418 
419