1 /*
2  * Copyright (C) 2015-2017 Alibaba Group Holding Limited
3  *
4  *
5  */
6 
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include "aos/kernel.h"
11 #include "sensor_drv_api.h"
12 #include "sensor_hal.h"
13 
14 /************ define parameter for register ************/
15 #define REG_SP_INT_RESET (0xE1)
16 #define REG_SP_IMM_STOP (0xE2)
17 #define REG_SP_IMM_START (0xE3)
18 #define REG_SP_SW_RESET (0xE4)
19 
20 /* REG_ALSCONTROL(0x00) */
21 #define MEAS_SERIAL (0 << 3)
22 #define MEAS_UNIT (1 << 3)
23 #define TYPE_BOTH (0 << 2)
24 #define TYPE_ONLY (1 << 2)
25 #define CTL_STANDBY (0)
26 #define CTL_STANDALONE (3)
27 #define CONTROL_MAX (16)
28 
29 /* REG_INTERRUPT(0x02) */
30 #define INT_NONSTOP (0 << 6)
31 #define INT_STOP (1 << 6)
32 #define INT_DISABLE (0 << 4)
33 #define INT_ENABLE (1 << 4)
34 #define INT_PER_MAX (16)
35 #define INTRRUPT_MASK (0x5F)
36 
37 /* REG_ALSGAIN(0x07) */
38 #define GAIN_X001 (0)
39 #define GAIN_X002 (1)
40 #define GAIN_X064 (2)
41 #define GAIN_X128 (3)
42 #define GAIN_MAX (4)
43 
44 
45 #define ALS_SET_CONTROL (MEAS_SERIAL)
46 #define ALS_SET_TIMING (218)
47 #define ALS_SET_INTR_PERSIST (1)
48 #define ALS_SET_INTR (INT_NONSTOP | INT_DISABLE | ALS_SET_INTR_PERSIST)
49 #define ALS_SET_ALSTH_UP_L (0xFF)
50 #define ALS_SET_ALSTH_UP_H (0xFF)
51 
52 #define ALS_SET_ALSTH_LOW_L (0x00)
53 #define ALS_SET_ALSTH_LOW_H (0x00)
54 
55 #define ALS_SET_GAIN (0x00)
56 
57 
58 /************ definition to dependent on sensor IC ************/
59 #define BH1730_I2C_NAME "bh1730_i2c"
60 #define BH1730_I2C_ADDRESS1 (0x29) // 7 bits slave address 010 1001
61 #define BH1730_ADDR_TRANS(n) ((n) << 1)
62 #define BH1730_I2C_ADDRESS BH1730_ADDR_TRANS(BH1730_I2C_ADDRESS1)
63 #define BH1730_PART_ID_NUMBER \
64     0x07 // PART_ID:  part number 3:0   revision id
65          // 7:4
66 
67 /************ define register for IC ************/
68 /* BH1730 REGSTER */
69 #define REG_ALSCONTROL (0x80)
70 #define REG_ALSTIMING (0x81)
71 #define REG_ALSINTERRUPT (0x82)
72 #define REG_ALSTHLOW (0x83)
73 #define REG_ALSTHLLOW (0x83)
74 #define REG_ALSTHLHIGH (0x84)
75 #define REG_ALSTHHIGH (0x85)
76 #define REG_ALSTHHLOW (0x85)
77 #define REG_ALSTHHHIGH (0x86)
78 #define REG_ALSGAIN (0x87)
79 #define REG_ID (0x92)
80 #define REG_ALSDATA0 (0x94)
81 #define REG_ALSDATA0_LOW (0x94)
82 #define REG_ALSDATA0_HIGH (0x95)
83 #define REG_ALSDATA1 (0x96)
84 #define REG_ALSDATA1_LOW (0x96)
85 #define REG_ALSDATA1_HIGH (0x97)
86 
87 /************ command definition of ioctl ************/
88 #define IOCTL_APP_SET_TIMER (10)
89 #define IOCTL_APP_SET_PWRSET_ALS (11)
90 #define IOCTL_APP_SET_ALS_TH_UP (15)
91 #define IOCTL_APP_SET_ALS_TH_LOW (16)
92 #define IOCTL_APP_SET_INT_OUTRST (20)
93 #define IOCTL_APP_SET_SW_RST (21)
94 #define IOCTL_APP_SET_TIMING (22)
95 #define IOCTL_APP_SET_GAIN (23)
96 #define IOCTL_APP_SET_GENERAL (253)
97 #define IOCTL_APP_READ_GENERAL (254)
98 #define IOCTL_APP_READ_DRIVER_VER (255)
99 
100 #define COEFFICIENT (4)
101 
102 const unsigned long data0_coefficient[COEFFICIENT] = { 1290, 795, 510, 276 };
103 const unsigned long data1_coefficient[COEFFICIENT] = { 2733, 859, 345, 130 };
104 const unsigned long judge_coefficient[COEFFICIENT] = { 26, 55, 109, 213 };
105 
106 /* value to calcrate  */
107 #define DECIMAL_BIT (14)
108 
109 
110 i2c_dev_t bh1730_ctx = {
111     .config.dev_addr = BH1730_I2C_ADDRESS,
112 };
113 
114 typedef struct
115 {
116     uint8_t als_data0_low;  /* data value of ALS data0 low from sensor */
117     uint8_t als_data0_high; /* data value of ALS data0 high from sensor */
118     uint8_t als_data1_low;  /* data value of ALS data1 low from sensor */
119     uint8_t als_data1_high; /* data value of ALS data1 high from sensor */
120 } READ_DATA_BUF;
121 
122 /************************************************************
123  *                      logic function                      *
124  ***********************************************************/
125 /******************************************************************************
126  * NAME       : measure_calc_als
127  * FUNCTION   : calculate illuminance data for BH1730
128  * REMARKS    : final_data format
129  *            :+-----------+-------------------------+------------------------+
130  *            :| sign 1bit | positive values : 17bit | decimal values : 14bit |
131  *            :+-----------+-------------------------+------------------------+
132  *****************************************************************************/
measure_calc_als(uint32_t * final_data)133 static int measure_calc_als(uint32_t *final_data)
134 {
135 
136 #define ITIME_CYCLE_BASE (256)
137 #define ITIME_CYCLE_UNIT (27)
138 #define JUDGE_FIXED_COEF (100)
139 #define MAX_OUTRANGE (100000)
140 #define DEVICE_OUTMAX (0xFFFF)
141 
142     READ_DATA_BUF data;
143     int           ret;
144     uint16_t      als_data0;
145     uint16_t      als_data1;
146     uint8_t       gain, read_time;
147     uint32_t      calc_judge, calc_data, gain_time, timing;
148     uint32_t      positive, decimal;
149     const uint8_t gain_table[GAIN_MAX] = { 1, 2, 64, 128 };
150     (void)decimal;
151     ret = sensor_i2c_read(&bh1730_ctx, REG_ALSGAIN, &gain, sizeof(gain),
152                           I2C_OP_RETRIES);
153     if (unlikely(ret)) {
154         return ret;
155     }
156     ret = sensor_i2c_read(&bh1730_ctx, REG_ALSTIMING, &read_time,
157                           sizeof(read_time), I2C_OP_RETRIES);
158     if (unlikely(ret)) {
159         return ret;
160     }
161     ret = sensor_i2c_read(&bh1730_ctx, REG_ALSDATA0, (uint8_t*)&data, sizeof(data),
162                           I2C_OP_RETRIES);
163     if (unlikely(ret)) {
164         return ret;
165     }
166     als_data0 = data.als_data0_low | (data.als_data0_high << 8);
167     als_data1 = data.als_data1_low | (data.als_data1_high << 8);
168 
169     /* calculate data */
170     if (als_data0 == DEVICE_OUTMAX) {
171         positive = MAX_OUTRANGE;
172         decimal  = 0;
173     } else {
174         timing     = (ITIME_CYCLE_BASE - read_time) * ITIME_CYCLE_UNIT;
175         gain_time  = timing * gain_table[gain & GAIN_X128];
176         calc_judge = als_data1 * JUDGE_FIXED_COEF;
177         if (calc_judge < (als_data0 * judge_coefficient[0])) {
178             calc_data = (data0_coefficient[0] * als_data0) -
179                         (data1_coefficient[0] * als_data1);
180         } else if (calc_judge < (als_data0 * judge_coefficient[1])) {
181             calc_data = (data0_coefficient[1] * als_data0) -
182                         (data1_coefficient[1] * als_data1);
183         } else if (calc_judge < (als_data0 * judge_coefficient[2])) {
184             calc_data = (data0_coefficient[2] * als_data0) -
185                         (data1_coefficient[2] * als_data1);
186         } else if (calc_judge < (als_data0 * judge_coefficient[3])) {
187             calc_data = (data0_coefficient[3] * als_data0) -
188                         (data1_coefficient[3] * als_data1);
189         } else {
190             calc_data = 0;
191         }
192 
193         /* calculate a positive number */
194         positive = calc_data / gain_time;
195         decimal  = 0;
196 
197         if (positive < MAX_OUTRANGE) {
198             /* calculate over plus and shift 16bit */
199             calc_data = calc_data - (positive * gain_time);
200             if (calc_data != 0) {
201                 calc_data = calc_data << DECIMAL_BIT;
202 
203                 /* calculate a decimal number */
204                 decimal = calc_data / gain_time;
205             }
206         } else {
207             positive = MAX_OUTRANGE;
208         }
209     }
210     //*final_data = (uint32_t)(positive << DECIMAL_BIT) + decimal;
211     *final_data = positive;
212     return (0);
213 
214 #undef ITIME_CYCLE_BASE
215 #undef ITIME_CYCLE_UNIT
216 #undef JUDGE_FIXED_COEF
217 #undef MAX_OUTRANGE
218 }
219 
220 
221 /******************************************************************************
222  * NAME       : als_driver_read_power_state
223  * FUNCTION   : read the value of ALS status in BH1730
224  * REMARKS    :
225  *****************************************************************************/
als_driver_read_control_state(uint8_t * con_st)226 static int als_driver_read_control_state(uint8_t *con_st)
227 {
228     uint8_t result;
229     int     ret;
230     /* read register to BH1730 via i2c */
231     ret = sensor_i2c_read(&bh1730_ctx, REG_ALSCONTROL, &result, sizeof(result),
232                           I2C_OP_RETRIES);
233     if (unlikely(ret)) {
234         return -1;
235     }
236     *con_st = result;
237     return (ret);
238 }
239 
240 
drv_als_rohm_bh1730_set_power_mode(i2c_dev_t * drv,dev_power_mode_e mode)241 static int drv_als_rohm_bh1730_set_power_mode(i2c_dev_t *      drv,
242                                               dev_power_mode_e mode)
243 {
244     int     ret = 0;
245     uint8_t dev_con;
246     ret = als_driver_read_control_state(&dev_con);
247     if (unlikely(ret)) {
248         return ret;
249     }
250     switch (mode) {
251         case DEV_POWER_OFF:
252             dev_con = dev_con | CTL_STANDBY;
253             break;
254         case DEV_POWER_ON:
255             dev_con = dev_con | CTL_STANDALONE;
256             break;
257         default:
258             return -1;
259     }
260     ret = sensor_i2c_write(drv, REG_ALSCONTROL, &dev_con, sizeof(dev_con),
261                            I2C_OP_RETRIES);
262     if (unlikely(ret)) {
263         return -1;
264     }
265     return 0;
266 }
267 
drv_als_rohm_bh1730_open(void)268 static int drv_als_rohm_bh1730_open(void)
269 {
270 
271     int ret = 0;
272     ret     = drv_als_rohm_bh1730_set_power_mode(&bh1730_ctx, DEV_POWER_ON);
273     if (unlikely(ret)) {
274         return -1;
275     }
276     LOG("%s %s successfully \n", SENSOR_STR, __func__);
277     return 0;
278 }
279 
drv_als_rohm_bh1730_close(void)280 static int drv_als_rohm_bh1730_close(void)
281 {
282 
283     int ret = 0;
284     ret     = drv_als_rohm_bh1730_set_power_mode(&bh1730_ctx, DEV_POWER_OFF);
285     if (unlikely(ret)) {
286         return -1;
287     }
288     LOG("%s %s successfully \n", SENSOR_STR, __func__);
289     return 0;
290 
291     return 0;
292 }
293 
drv_als_rohm_bh1730_read(void * buf,size_t len)294 static int drv_als_rohm_bh1730_read(void *buf, size_t len)
295 {
296 
297     als_data_t *pdata = (als_data_t *)buf;
298     if (buf == NULL) {
299         return -1;
300     }
301     measure_calc_als(&(pdata->lux));
302     pdata->timestamp = aos_now_ms();
303     return sizeof(humidity_data_t);
304 }
305 
306 
drv_als_rohm_bh1730_write(const void * buf,size_t len)307 static int drv_als_rohm_bh1730_write(const void *buf, size_t len)
308 {
309     return 0;
310 }
311 
drv_als_rohm_bh1730_ioctl(int cmd,unsigned long arg)312 static int drv_als_rohm_bh1730_ioctl(int cmd, unsigned long arg)
313 {
314     int ret = 0;
315 
316     switch (cmd) {
317         case SENSOR_IOCTL_SET_POWER: {
318             ret = drv_als_rohm_bh1730_set_power_mode(&bh1730_ctx, arg);
319             if (unlikely(ret)) {
320                 return -1;
321             }
322         } break;
323         case SENSOR_IOCTL_GET_INFO: {
324             /* fill the dev info here */
325             dev_sensor_info_t *info = (dev_sensor_info_t *)arg;
326             info->model             = "BH1730";
327             info->unit              = lux;
328         } break;
329         default:
330             break;
331     }
332 
333     LOG("%s %s successfully \n", SENSOR_STR, __func__);
334     return 0;
335 }
336 
drv_als_rohm_bh1730_handle(void)337 static void drv_als_rohm_bh1730_handle(void)
338 {
339     /* no handle so far */
340 }
341 
drv_als_rohm_bh1730_validate_id(i2c_dev_t * drv,uint8_t id_val)342 static int drv_als_rohm_bh1730_validate_id(i2c_dev_t *drv, uint8_t id_val)
343 {
344     int     ret           = 0;
345     uint8_t part_id_value = 0;
346 
347     if (drv == NULL) {
348         return -1;
349     }
350 
351     ret = sensor_i2c_read(drv, REG_ID, &part_id_value, I2C_DATA_LEN,
352                           I2C_OP_RETRIES);
353     if (unlikely(ret)) {
354         return ret;
355     }
356     if ((part_id_value >> 4) != id_val) {
357         return -1;
358     }
359 
360     return 0;
361 }
362 
drv_als_rohm_bh1730_init(void)363 int drv_als_rohm_bh1730_init(void)
364 {
365     int          ret = 0;
366     sensor_obj_t sensor;
367 
368     memset(&sensor, 0, sizeof(sensor));
369 
370     ret = drv_als_rohm_bh1730_validate_id(&bh1730_ctx, BH1730_PART_ID_NUMBER);
371 
372     struct init_func_write_data
373     {
374         uint8_t control;
375         uint8_t timing;
376         uint8_t intr;
377         uint8_t alsth_ll;
378         uint8_t alsth_lh;
379         uint8_t alsth_hl;
380         uint8_t alsth_hh;
381         uint8_t als_gain;
382     } write_data;
383 
384     write_data.control  = ALS_SET_CONTROL;
385     write_data.timing   = ALS_SET_TIMING;
386     write_data.intr     = ALS_SET_INTR;
387     write_data.alsth_hl = ALS_SET_ALSTH_UP_L;
388     write_data.alsth_hh = ALS_SET_ALSTH_UP_H;
389     write_data.alsth_ll = ALS_SET_ALSTH_LOW_L;
390     write_data.alsth_lh = ALS_SET_ALSTH_LOW_H;
391     write_data.als_gain = ALS_SET_GAIN;
392     ret = sensor_i2c_write(&bh1730_ctx, REG_ALSCONTROL, (uint8_t *)&write_data,
393                            sizeof(write_data), I2C_OP_RETRIES);
394     if (unlikely(ret)) {
395         return -1;
396     }
397 
398     /* fill the sensor obj parameters here */
399     sensor.tag        = TAG_DEV_ALS;
400     sensor.path       = dev_als_path;
401     sensor.io_port    = I2C_PORT;
402     sensor.open       = drv_als_rohm_bh1730_open;
403     sensor.close      = drv_als_rohm_bh1730_close;
404     sensor.read       = drv_als_rohm_bh1730_read;
405     sensor.write      = drv_als_rohm_bh1730_write;
406     sensor.ioctl      = drv_als_rohm_bh1730_ioctl;
407     sensor.irq_handle = drv_als_rohm_bh1730_handle;
408 
409 
410     ret = sensor_create_obj(&sensor);
411     if (unlikely(ret)) {
412         return -1;
413     }
414 
415 
416     LOG("%s %s successfully \n", SENSOR_STR, __func__);
417 
418     return 0;
419 }
420 
421 
422 
423 SENSOR_DRV_ADD(drv_als_rohm_bh1730_init);
424 
425