1 /*
2 * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3 */
4
5 #include "drv_als_ps_ir_liteon_ap3216c.h"
6 #include "ulog/ulog.h"
7 #include <aos/kernel.h>
8
9 static i2c_dev_t i2c_dev;
10
11 #define PKG_USING_AP3216C
12
13 #ifdef PKG_USING_AP3216C
14
15 #define AP3216C_I2C_PORT 1
16 #define AP3216C_ADDR 0x1e
17
18 // System Register
19 #define AP3216C_SYS_CONFIGURATION_REG 0x00
20 #define AP3216C_SYS_INT_STATUS_REG 0x01
21 #define AP3216C_SYS_INT_CLEAR_MANNER_REG 0x02
22 #define AP3216C_IR_DATA_L_REG 0x0A
23 #define AP3216C_IR_DATA_H_REG 0x0B
24 #define AP3216C_ALS_DATA_L_REG 0x0C
25 #define AP3216C_ALS_DATA_H_REG 0x0D
26 #define AP3216C_PS_DATA_L_REG 0x0E
27 #define AP3216C_PS_DATA_H_REG 0x0F
28
29 // ALS Register
30 #define AP3216C_ALS_CONFIGURATION_REG 0x10
31 #define AP3216C_ALS_CALIBRATION_REG 0x19
32 #define AP3216C_ALS_THRESHOLD_LOW_L_REG 0x1A
33 #define AP3216C_ALS_THRESHOLD_LOW_H_REG 0x1B
34 #define AP3216C_ALS_THRESHOLD_HIGH_L_REG 0x1C
35 #define AP3216C_ALS_THRESHOLD_HIGH_H_REG 0x1D
36
37 // PS Register
38 #define AP3216C_PS_CONFIGURATION_REG 0x20
39 #define AP3216C_PS_LED_DRIVER_REG 0x21
40 #define AP3216C_PS_INT_FORM_REG 0x22
41 #define AP3216C_PS_MEAN_TIME_REG 0x23
42 #define AP3216C_PS_LED_WAITING_TIME_REG 0x24
43 #define AP3216C_PS_CALIBRATION_L_REG 0x28
44 #define AP3216C_PS_CALIBRATION_H_REG 0x29
45 #define AP3216C_PS_THRESHOLD_LOW_L_REG 0x2A
46 #define AP3216C_PS_THRESHOLD_LOW_H_REG 0x2B
47 #define AP3216C_PS_THRESHOLD_HIGH_L_REG 0x2C
48 #define AP3216C_PS_THRESHOLD_HIGH_H_REG 0x2D
49
50 /* 写寄存器的值 */
write_reg(uint8_t reg,uint8_t data)51 static void write_reg(uint8_t reg, uint8_t data)
52 {
53 sensor_i2c_mem_write(AP3216C_I2C_PORT, AP3216C_ADDR, reg, 1, &data, 1, 100);
54 }
55
56 /* 读寄存器的值 */
read_regs(uint8_t reg,uint8_t len,uint8_t * buf)57 static void read_regs(uint8_t reg, uint8_t len, uint8_t *buf)
58 {
59 sensor_i2c_mem_read(AP3216C_I2C_PORT, AP3216C_ADDR, reg, 1, buf, len, 100);
60 }
61
62 /* 软件复位传感器 */
reset_sensor(void)63 static void reset_sensor(void)
64 {
65 write_reg(AP3216C_SYS_CONFIGURATION_REG, AP3216C_MODE_SW_RESET); // reset
66 }
67
68 /**
69 * This function is convenient to getting data except including high and low
70 * data for this sensor. note:after reading lower register first,reading higher
71 * add one.
72 */
read_low_and_high(uint8_t reg,uint8_t len)73 static uint32_t read_low_and_high(uint8_t reg, uint8_t len)
74 {
75 uint32_t data;
76 uint8_t buf = 0;
77
78 read_regs(reg, len, &buf); // 读低字节
79 data = buf;
80 read_regs(reg + 1, len, &buf); // 读高字节
81 data = data + (buf << len * 8); // 合并数据
82
83 return data;
84 }
85
86 /**
87 * This function is only used to set threshold without filtering times
88 *
89 * @param cmd first register , and other cmd count by it.
90 * @param threshold threshold and filtering times of als threshold
91 */
set_als_threshold(ap3216c_cmd_t cmd,ap3216c_threshold_t threshold)92 static void set_als_threshold(ap3216c_cmd_t cmd, ap3216c_threshold_t threshold)
93 {
94 uint8_t Resolution;
95 double DB = 1.0;
96
97 /* 读光照强度的范围 */
98 ap3216c_get_param(AP3216C_ALS_RANGE, &Resolution);
99
100 if (Resolution == AP3216C_ALS_RANGE_20661) {
101 // 光照强度范围 0 - 20661
102 DB = 0.35; // 光照强度的分辨率
103 } else if (Resolution == AP3216C_ALS_RANGE_5162) {
104 // 光照强度范围 0 - 5162
105 DB = 0.0788; // 光照强度的分辨率
106 } else if (Resolution == AP3216C_ALS_RANGE_1291) {
107 // 光照强度范围 0 - 1291
108 DB = 0.0197; // 光照强度的分辨率
109 } else if (Resolution == AP3216C_ALS_RANGE_323) {
110 // 光照强度范围 0 - 323
111 DB = 0.0049; // 光照强度的分辨率
112 }
113
114 threshold.min /= DB; // 根据不同的分辨率来设置
115 threshold.max /= DB;
116
117 ap3216c_set_param(cmd, (threshold.min & 0xff));
118 ap3216c_set_param((ap3216c_cmd_t)(cmd + 1), (threshold.min >> 8));
119 ap3216c_set_param((ap3216c_cmd_t)(cmd + 2), (threshold.max & 0xff));
120 ap3216c_set_param((ap3216c_cmd_t)(cmd + 3), threshold.max >> 8);
121 }
122
set_ps_threshold(ap3216c_cmd_t cmd,ap3216c_threshold_t threshold)123 static void set_ps_threshold(ap3216c_cmd_t cmd, ap3216c_threshold_t threshold)
124 {
125 if (threshold.min > 1020) {
126 // 大于1020 时需要设置低字节的低两位
127 ap3216c_set_param(cmd, (threshold.min - 1020 & 0x03));
128 }
129
130 ap3216c_set_param((ap3216c_cmd_t)(cmd + 1),
131 threshold.min / 4); // 设置高字节参数
132
133 if (threshold.max > 1020) {
134 // 大于1020 时需要设置低字节的低两位
135 ap3216c_set_param((ap3216c_cmd_t)(cmd + 2),
136 (threshold.max - 1020 & 0x03));
137 }
138
139 ap3216c_set_param((ap3216c_cmd_t)(cmd + 3),
140 threshold.max / 4); // 设置高字节参数
141 }
142
143 /**
144 * This function reads status register by ap3216c sensor measurement
145 *
146 * @param no
147 *
148 * @return status register value.
149 */
150
ap3216c_get_IntStatus(void)151 uint8_t ap3216c_get_IntStatus(void)
152 {
153 uint8_t IntStatus;
154
155 /* 读中断状态寄存器 */
156
157 read_regs(AP3216C_SYS_INT_STATUS_REG, 1, &IntStatus);
158 // IntStatus 第 0 位表示 ALS 中断,第 1 位表示 PS 中断。
159
160 return IntStatus; // 返回状态
161 }
162
ap3216c_int_init(void)163 static void ap3216c_int_init(void) { ; }
164
165 /**
166 * @brief 配置 中断输入引脚
167 * @param 无
168 * @retval 无
169 */
ap3216c_int_Config(void)170 void ap3216c_int_Config(void) { ; }
171
172 /**
173 * This function initializes ap3216c registered device driver
174 *
175 * @param no
176 *
177 * @return the ap3216c device.
178 */
ap3216c_init(void)179 void ap3216c_init(void)
180 {
181 int32_t ret = sensor_i2c_open(AP3216C_I2C_PORT, AP3216C_ADDR, I2C_BUS_BIT_RATES_100K, 0);
182 if (ret) {
183 LOGI("SENSOR", "sensor i2c open failed, ret:%d\n", ret);
184 return;
185 }
186
187 /* reset ap3216c */
188 reset_sensor();
189 aos_msleep(100);
190 ap3216c_set_param(AP3216C_SYSTEM_MODE, AP3216C_MODE_ALS_AND_PS);
191 aos_msleep(150); // delay at least 112.5ms
192
193 ap3216c_int_Config();
194 ap3216c_int_init();
195 }
196
ap3216c_deinit(void)197 void ap3216c_deinit(void)
198 {
199 int32_t ret = sensor_i2c_close(AP3216C_I2C_PORT);
200 if (ret) {
201 LOGE("SENSOR", "sensor i2c close failed, ret:%d\n", ret);
202 }
203
204 return;
205 }
206
207 /**
208 * This function reads light by ap3216c sensor measurement
209 *
210 * @param no
211 *
212 * @return the ambient light converted to float data.
213 */
ap3216c_read_ambient_light(void)214 uint16_t ap3216c_read_ambient_light(void)
215 {
216 uint16_t brightness = 0; // default error data
217 uint16_t read_data;
218 uint8_t range;
219
220 read_data = (uint16_t)read_low_and_high(AP3216C_ALS_DATA_L_REG, 1);
221 ap3216c_get_param(AP3216C_ALS_RANGE, &range);
222 if (range == AP3216C_ALS_RANGE_20661) {
223 brightness =
224 0.35 * read_data; // sensor ambient light converse to reality
225 } else if (range == AP3216C_ALS_RANGE_5162) {
226 brightness =
227 0.0788 * read_data; // sensor ambient light converse to reality
228 } else if (range == AP3216C_ALS_RANGE_1291) {
229 brightness =
230 0.0197 * read_data; // sensor ambient light converse to reality
231 } else if (range == AP3216C_ALS_RANGE_323) {
232 brightness =
233 0.0049 * read_data; // sensor ambient light converse to reality
234 }
235 return brightness;
236 }
237
238 /**
239 * This function reads proximity by ap3216c sensor measurement
240 *
241 * @param no
242 *
243 * @return the proximity data.
244 */
ap3216c_read_ps_data(void)245 uint16_t ap3216c_read_ps_data(void)
246 {
247 uint16_t proximity = 0;
248
249 uint32_t read_data;
250 read_data = read_low_and_high(AP3216C_PS_DATA_L_REG, 1); // read two data
251 // printf("ap3216c_read_ps_data read_data %d\n",read_data);
252 if (1 == ((read_data >> 6) & 0x01 || (read_data >> 14) & 0x01)) {
253 return proximity =
254 55555; // 红外过高(IR),PS无效 返回一个 55555 的无效数据
255 }
256
257 proximity =
258 (read_data & 0x000f) + (((read_data >> 8) & 0x3f)
259 << 4); // sensor proximity converse to reality
260
261 proximity |= read_data & 0x8000; // 取最高位,0 表示物体远离,1 表示物体靠近
262
263 return proximity; // proximity 后十位是数据位,最高位为状态位
264 }
265
266 /**
267 * This function reads ir by ap3216c sensor measurement
268 *
269 * @param no
270 *
271 * @return the ir data.
272 */
ap3216c_read_ir_data(void)273 uint16_t ap3216c_read_ir_data(void)
274 {
275 uint16_t proximity = 0;
276
277 uint32_t read_data;
278 read_data = read_low_and_high(AP3216C_IR_DATA_L_REG, 1); // read two data
279 // printf("ap3216c_read_ir_data read_data %d\n",read_data);
280 proximity =
281 (read_data & 0x0003) +
282 ((read_data >> 8) & 0xFF); // sensor proximity converse to reality
283
284 return proximity;
285 }
286
287 /**
288 * This function sets parameter of ap3216c sensor
289 *
290 * @param cmd the parameter cmd of device
291 * @param value for setting value in cmd register
292 *
293 * @return the setting parameter status,RT_EOK reprensents setting successfully.
294 */
ap3216c_set_param(ap3216c_cmd_t cmd,uint8_t value)295 void ap3216c_set_param(ap3216c_cmd_t cmd, uint8_t value)
296 {
297 switch (cmd) {
298 case AP3216C_SYSTEM_MODE:
299 {
300 /* default 000,power down */
301 write_reg(AP3216C_SYS_CONFIGURATION_REG, value);
302 break;
303 }
304 case AP3216C_INT_PARAM:
305 {
306 write_reg(AP3216C_SYS_INT_CLEAR_MANNER_REG, value);
307
308 break;
309 }
310
311 case AP3216C_ALS_RANGE:
312 {
313 uint8_t args;
314
315 read_regs(AP3216C_ALS_CONFIGURATION_REG, 1, &args);
316 args &= 0xcf;
317 args |= value << 4;
318 write_reg(AP3216C_ALS_CONFIGURATION_REG, args);
319
320 break;
321 }
322 case AP3216C_ALS_PERSIST:
323 {
324 uint8_t args = 0;
325
326 read_regs(AP3216C_ALS_CONFIGURATION_REG, 1, &args);
327 args &= 0xf0;
328 args |= value;
329 write_reg(AP3216C_ALS_CONFIGURATION_REG, args);
330
331 break;
332 }
333 case AP3216C_ALS_LOW_THRESHOLD_L:
334 {
335 write_reg(AP3216C_ALS_THRESHOLD_LOW_L_REG, value);
336
337 break;
338 }
339 case AP3216C_ALS_LOW_THRESHOLD_H:
340 {
341 write_reg(AP3216C_ALS_THRESHOLD_LOW_H_REG, value);
342
343 break;
344 }
345 case AP3216C_ALS_HIGH_THRESHOLD_L:
346 {
347 write_reg(AP3216C_ALS_THRESHOLD_HIGH_L_REG, value);
348
349 break;
350 }
351 case AP3216C_ALS_HIGH_THRESHOLD_H:
352 {
353 write_reg(AP3216C_ALS_THRESHOLD_HIGH_H_REG, value);
354
355 break;
356 }
357 case AP3216C_PS_GAIN:
358 {
359 uint8_t args = 0;
360
361 read_regs(AP3216C_PS_CONFIGURATION_REG, 1, &args);
362 args &= 0xf3;
363 args |= value;
364 write_reg(AP3216C_PS_CONFIGURATION_REG, args);
365
366 break;
367 }
368 case AP3216C_PS_PERSIST:
369 {
370 uint8_t args = 0;
371
372 read_regs(AP3216C_PS_CONFIGURATION_REG, 1, &args);
373 args &= 0xfc;
374 args |= value;
375 write_reg(AP3216C_PS_CONFIGURATION_REG, args);
376
377 break;
378 }
379 case AP3216C_PS_LOW_THRESHOLD_L:
380 {
381 write_reg(AP3216C_PS_THRESHOLD_LOW_L_REG, value);
382
383 break;
384 }
385 case AP3216C_PS_LOW_THRESHOLD_H:
386 {
387 write_reg(AP3216C_PS_THRESHOLD_LOW_H_REG, value);
388
389 break;
390 }
391 case AP3216C_PS_HIGH_THRESHOLD_L:
392 {
393 write_reg(AP3216C_PS_THRESHOLD_HIGH_L_REG, value);
394
395 break;
396 }
397 case AP3216C_PS_HIGH_THRESHOLD_H:
398 {
399 write_reg(AP3216C_PS_THRESHOLD_HIGH_H_REG, value);
400
401 break;
402 }
403
404 default:
405 {
406 break;
407 }
408 }
409 }
410
411 /**
412 * This function gets parameter of ap3216c sensor
413 *
414 * @param cmd the parameter cmd of device
415 * @param value to get value in cmd register
416 *
417 * @return the getting parameter status,RT_EOK reprensents getting successfully.
418 */
ap3216c_get_param(ap3216c_cmd_t cmd,uint8_t * value)419 void ap3216c_get_param(ap3216c_cmd_t cmd, uint8_t *value)
420 {
421 switch (cmd) {
422 case AP3216C_SYSTEM_MODE:
423 {
424 read_regs(AP3216C_SYS_CONFIGURATION_REG, 1, value);
425
426 break;
427 }
428 case AP3216C_INT_PARAM:
429 {
430 read_regs(AP3216C_SYS_INT_CLEAR_MANNER_REG, 1, value);
431
432 break;
433 }
434 case AP3216C_ALS_RANGE:
435 {
436 uint8_t temp;
437
438 read_regs(AP3216C_ALS_CONFIGURATION_REG, 1, value);
439 temp = (*value & 0xff) >> 4;
440
441 *value = temp;
442
443 break;
444 }
445 case AP3216C_ALS_PERSIST:
446 {
447 uint8_t temp;
448
449 read_regs(AP3216C_ALS_CONFIGURATION_REG, 1, value);
450 temp = *value & 0x0f;
451
452 *value = temp;
453
454 break;
455 }
456 case AP3216C_ALS_LOW_THRESHOLD_L:
457 {
458 read_regs(AP3216C_ALS_THRESHOLD_LOW_L_REG, 1, value);
459
460 break;
461 }
462 case AP3216C_ALS_LOW_THRESHOLD_H:
463 {
464 read_regs(AP3216C_ALS_THRESHOLD_LOW_H_REG, 1, value);
465
466 break;
467 }
468 case AP3216C_ALS_HIGH_THRESHOLD_L:
469 {
470 read_regs(AP3216C_ALS_THRESHOLD_HIGH_L_REG, 1, value);
471
472 break;
473 }
474 case AP3216C_ALS_HIGH_THRESHOLD_H:
475 {
476 read_regs(AP3216C_ALS_THRESHOLD_HIGH_H_REG, 1, value);
477
478 break;
479 }
480 case AP3216C_PS_GAIN:
481 {
482 uint8_t temp;
483
484 read_regs(AP3216C_PS_CONFIGURATION_REG, 1, &temp);
485
486 *value = (temp & 0xc) >> 2;
487
488 break;
489 }
490 case AP3216C_PS_PERSIST:
491 {
492 uint8_t temp;
493
494 read_regs(AP3216C_PS_CONFIGURATION_REG, 1, &temp);
495
496 *value = temp & 0x3;
497
498 break;
499 }
500 case AP3216C_PS_LOW_THRESHOLD_L:
501 {
502 read_regs(AP3216C_PS_THRESHOLD_LOW_L_REG, 1, value);
503
504 break;
505 }
506 case AP3216C_PS_LOW_THRESHOLD_H:
507 {
508 read_regs(AP3216C_PS_THRESHOLD_LOW_H_REG, 1, value);
509 break;
510 }
511 case AP3216C_PS_HIGH_THRESHOLD_L:
512 {
513 read_regs(AP3216C_PS_THRESHOLD_HIGH_L_REG, 1, value);
514
515 break;
516 }
517 case AP3216C_PS_HIGH_THRESHOLD_H:
518 {
519 read_regs(AP3216C_PS_THRESHOLD_HIGH_H_REG, 1, value);
520
521 break;
522 }
523
524 default:
525 {
526 break;
527 }
528 }
529 }
530
531 #endif /* PKG_USING_AP3216C */
532