1/*
2 * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3 */
4
5/*
6The driver for AP3216C chip, The AP3216C is an integrated ALS & PS module
7that includes a digital ambient light sensor [ALS], a proximity sensor [PS],
8and an IR LED in a single package.
9*/
10/*
11添加如下配置到app.json中:
12        "ap3216c": {
13            "type": "I2C",
14            "port": 1,
15            "addrWidth": 7,
16            "freq": 100000,
17            "mode": "master",
18            "devAddr": 30
19        }
20*/
21// Require libjs/lib/i2c.js module.
22
23const AP3216C_I2C_PORT = 1
24const AP3216C_ADDR      = 0x1e
25
26// System Register
27const AP3216C_SYS_CONFIGURATION_REG    = 0x00
28const AP3216C_SYS_INT_STATUS_REG       = 0x01
29const AP3216C_SYS_INT_CLEAR_MANNER_REG = 0x02
30const AP3216C_IR_DATA_L_REG            = 0x0A
31const AP3216C_IR_DATA_H_REG            = 0x0B
32const AP3216C_ALS_DATA_L_REG           = 0x0C
33const AP3216C_ALS_DATA_H_REG           = 0x0D
34const AP3216C_PS_DATA_L_REG            = 0x0E
35const AP3216C_PS_DATA_H_REG            = 0x0F
36
37// ALS Register
38const AP3216C_ALS_CONFIGURATION_REG    = 0x10
39const AP3216C_ALS_CALIBRATION_REG      = 0x19
40const AP3216C_ALS_THRESHOLD_LOW_L_REG  = 0x1A
41const AP3216C_ALS_THRESHOLD_LOW_H_REG  = 0x1B
42const AP3216C_ALS_THRESHOLD_HIGH_L_REG = 0x1C
43const AP3216C_ALS_THRESHOLD_HIGH_H_REG = 0x1D
44
45// PS Register
46const AP3216C_PS_CONFIGURATION_REG    = 0x20
47const AP3216C_PS_LED_DRIVER_REG       = 0x21
48const AP3216C_PS_INT_FORM_REG         = 0x22
49const AP3216C_PS_MEAN_TIME_REG        = 0x23
50const AP3216C_PS_LED_WAITING_TIME_REG = 0x24
51const AP3216C_PS_CALIBRATION_L_REG    = 0x28
52const AP3216C_PS_CALIBRATION_H_REG    = 0x29
53const AP3216C_PS_THRESHOLD_LOW_L_REG  = 0x2A
54const AP3216C_PS_THRESHOLD_LOW_H_REG  = 0x2B
55const AP3216C_PS_THRESHOLD_HIGH_L_REG = 0x2C
56const AP3216C_PS_THRESHOLD_HIGH_H_REG = 0x2D
57
58//mode value
59const AP3216C_MODE_POWER_DOWN    = 0x0
60const AP3216C_MODE_ALS           = 0x1
61const AP3216C_MODE_PS            = 0x2
62const AP3216C_MODE_ALS_AND_PS    = 0x3
63const AP3216C_MODE_SW_RESET      = 0x4
64const AP3216C_MODE_ALS_ONCE      = 0x5
65const AP3216C_MODE_PS_ONCE       = 0x6
66const AP3216C_MODE_ALS_AND_PS_ONCE  = 0x7
67
68//ap3216c_int_clear_manner
69const AP3216C_INT_CLEAR_MANNER_BY_READING    = 0x0
70const AP3216C_ALS_CLEAR_MANNER_BY_SOFTWARE   = 0x1
71
72//als_range
73const AP3216C_ALS_RANGE_20661    = 0x0
74const AP3216C_ALS_RANGE_5162     = 0x1
75const AP3216C_ALS_RANGE_1291     = 0x2
76const AP3216C_ALS_RANGE_323    = 0x3
77
78//als_range
79const AP3216C_PS_GAIN1    = 0x0
80const AP3216C_PS_GAIN2     = 0x1
81const AP3216C_PS_GAIN4     = 0x2
82const AP3216C_PS_GAIN8    = 0x3
83
84const AP3216C_SYSTEM_MODE          = 0x0
85const AP3216C_INT_PARAM            = 0x1
86const AP3216C_ALS_RANGE            = 0x2
87const AP3216C_ALS_PERSIST          = 0x3
88const AP3216C_ALS_CALIBRATION      = 0x4
89const AP3216C_ALS_LOW_THRESHOLD_L  = 0x5
90const AP3216C_ALS_LOW_THRESHOLD_H  = 0x6
91const AP3216C_ALS_HIGH_THRESHOLD_L = 0x7
92const AP3216C_ALS_HIGH_THRESHOLD_H = 0x8
93const AP3216C_PS_INTEGRATED_TIME   = 0x9
94const AP3216C_PS_GAIN              = 0xa
95const AP3216C_PS_PERSIST           = 0xb
96const AP3216C_PS_LED_CONTROL       = 0xc
97const AP3216C_PS_LED_DRIVER_RATIO  = 0xd
98const AP3216C_PS_INT_MODE          = 0xe
99const AP3216C_PS_MEAN_TIME         = 0xf
100const AP3216C_PS_WAITING_TIME      = 0x10
101const AP3216C_PS_CALIBRATION_L     = 0x11
102const AP3216C_PS_CALIBRATION_H     = 0x12
103const AP3216C_PS_LOW_THRESHOLD_L   = 0x13
104const AP3216C_PS_LOW_THRESHOLD_H   = 0x14
105const AP3216C_PS_HIGH_THRESHOLD_L  = 0x15
106const AP3216C_PS_HIGH_THRESHOLD_H  = 0x16
107
108var i2c = require('i2c');
109
110var ap3216cDev;
111
112function fakeSleep(ms) {
113    var date = new Date();
114    var curDate;
115    do {
116        curDate = new Date();
117    } while((curDate - date) < ms);
118}
119
120/* 写寄存器的值 */
121function write_reg(addr, data)
122{
123    var msgbuf = [data];
124    ap3216cDev.writeMem(addr, msgbuf);
125    console.log("--> write addr " + addr + ", value = " + msgbuf);
126}
127
128/* 读寄存器的值 */
129function read_regs(addr, len)
130{
131    buf = ap3216cDev.readMem(addr, len);
132    console.log("--> read addr " + addr + ", value = " + buf);
133    return buf;
134}
135
136/* 软件复位传感器 */
137function reset_sensor()
138{
139    write_reg(AP3216C_SYS_CONFIGURATION_REG, AP3216C_MODE_SW_RESET); // reset
140}
141
142/**
143 * This function is convenient to getting data except including high and low
144 * data for this sensor. note:after reading lower register first,reading higher
145 * add one.
146 */
147function read_low_and_high(reg, len)
148{
149    var data;
150    var buf0;
151    var buf1;
152
153    buf0 = read_regs(reg, len); // 读低字节
154    buf1 = read_regs(reg + 1, len);  // 读高字节
155    data = buf0 | (buf1 << len * 8); // 合并数据
156    data = data >>> 0
157
158    return data;
159}
160
161/**
162 * This function reads status register by ap3216c sensor measurement
163 *
164 * @param no
165 *
166 * @return status register value.
167 */
168
169function ap3216c_get_IntStatus()
170{
171    var IntStatus;
172
173    /* 读中断状态寄存器 */
174
175    IntStatus = read_regs(AP3216C_SYS_INT_STATUS_REG, 1);
176    // IntStatus 第 0 位表示 ALS 中断,第 1 位表示 PS 中断。
177
178    return IntStatus; // 返回状态
179}
180
181function ap3216c_int_init() { ; }
182
183/**
184 * @brief  配置 中断输入引脚
185 * @param  无
186 * @retval 无
187 */
188function ap3216c_int_Config() { ; }
189
190/**
191 * This function initializes ap3216c registered device driver
192 *
193 * @param no
194 *
195 * @return the ap3216c device.
196 */
197function init(i2cid)
198{
199    ap3216cDev = i2c.open({id: i2cid});
200    fakeSleep(30);
201
202    /* reset ap3216c */
203    reset_sensor();
204    fakeSleep(100);
205    ap3216c_set_param(AP3216C_SYSTEM_MODE, AP3216C_MODE_ALS_AND_PS);
206    fakeSleep(150); // delay at least 112.5ms
207
208    ap3216c_int_Config();
209    ap3216c_int_init();
210}
211
212function ap3216c_deinit() {
213    ap3216cDev.close();
214}
215
216/**
217 * This function reads light by ap3216c sensor measurement
218 *
219 * @param no
220 *
221 * @return the ambient light converted to float data.
222 */
223function ap3216c_read_ambient_light()
224{
225    var brightness; // default error data
226    var read_data;
227    var range;
228
229    read_data = read_low_and_high(AP3216C_ALS_DATA_L_REG, 1);
230    range = ap3216c_get_param(AP3216C_ALS_RANGE);
231    //console.log("ap3216c_read_ambient_light read_data is " , read_data, range);
232    if (range == AP3216C_ALS_RANGE_20661) {
233        brightness =
234            0.35 * read_data; // sensor ambient light converse to reality
235    } else if (range == AP3216C_ALS_RANGE_5162) {
236        brightness =
237            0.0788 * read_data; // sensor ambient light converse to reality
238    } else if (range == AP3216C_ALS_RANGE_1291) {
239        brightness =
240            0.0197 * read_data; // sensor ambient light converse to reality
241    } else if (range == AP3216C_ALS_RANGE_323) {
242        brightness =
243            0.0049 * read_data; // sensor ambient light converse to reality
244    }
245    return brightness;
246}
247
248/**
249 * This function reads proximity by ap3216c sensor measurement
250 *
251 * @param no
252 *
253 * @return the proximity data.
254 */
255function ap3216c_read_ps_data()
256{
257    var proximity = 0;
258
259    var read_data;
260    read_data = read_low_and_high(AP3216C_PS_DATA_L_REG, 1); // read two data
261    //console.log("ap3216c_read_ps_data read_data is " , read_data);
262    if (1 == ((read_data >> 6) & 0x01 || (read_data >> 14) & 0x01)) {
263        return proximity = 55555; // 红外过高(IR),PS无效 返回一个 55555 的无效数据
264    }
265
266    proximity = (read_data & 0x000f) + (((read_data >> 8) & 0x3f) << 4); // sensor proximity converse to reality
267
268    proximity = proximity >>> 0
269
270    proximity |= read_data & 0x8000; // 取最高位,0 表示物体远离,1 表示物体靠近
271
272    return proximity; // proximity 后十位是数据位,最高位为状态位
273}
274
275/**
276 * This function reads ir by ap3216c sensor measurement
277 *
278 * @param no
279 *
280 * @return the ir data.
281 */
282function ap3216c_read_ir_data()
283{
284    var proximity = 0;
285
286    var read_data;
287    read_data = read_low_and_high(AP3216C_IR_DATA_L_REG, 1); // read two data
288    //console.log("ap3216c_read_ir_data read_data is" , read_data);
289    proximity =
290        (read_data & 0x0003) +
291        ((read_data >> 8) & 0xFF); // sensor proximity converse to reality
292
293    proximity = proximity >>> 0
294
295    return proximity;
296}
297
298/**
299 * This function sets parameter of ap3216c sensor
300 *
301 * @param cmd the parameter cmd of device
302 * @param value for setting value in cmd register
303 *
304 * @return the setting parameter status,RT_EOK reprensents setting successfully.
305 */
306function ap3216c_set_param(cmd, value)
307{
308    switch (cmd) {
309        case AP3216C_SYSTEM_MODE:
310            {
311                /* default 000,power down */
312                write_reg(AP3216C_SYS_CONFIGURATION_REG, value);
313                break;
314            }
315        case AP3216C_INT_PARAM:
316            {
317                write_reg(AP3216C_SYS_INT_CLEAR_MANNER_REG, value);
318
319                break;
320            }
321
322        case AP3216C_ALS_RANGE:
323            {
324                var args = read_regs(AP3216C_ALS_CONFIGURATION_REG, 1);
325                args &= 0xcf;
326                args |= value << 4;
327                write_reg(AP3216C_ALS_CONFIGURATION_REG, args);
328
329                break;
330            }
331        case AP3216C_ALS_PERSIST:
332            {
333                var args = read_regs(AP3216C_ALS_CONFIGURATION_REG, 1);
334                args &= 0xf0;
335                args |= value;
336                write_reg(AP3216C_ALS_CONFIGURATION_REG, args);
337
338                break;
339            }
340        case AP3216C_ALS_LOW_THRESHOLD_L:
341            {
342                write_reg(AP3216C_ALS_THRESHOLD_LOW_L_REG, value);
343
344                break;
345            }
346        case AP3216C_ALS_LOW_THRESHOLD_H:
347            {
348                write_reg(AP3216C_ALS_THRESHOLD_LOW_H_REG, value);
349
350                break;
351            }
352        case AP3216C_ALS_HIGH_THRESHOLD_L:
353            {
354                write_reg(AP3216C_ALS_THRESHOLD_HIGH_L_REG, value);
355
356                break;
357            }
358        case AP3216C_ALS_HIGH_THRESHOLD_H:
359            {
360                write_reg(AP3216C_ALS_THRESHOLD_HIGH_H_REG, value);
361
362                break;
363            }
364        case AP3216C_PS_GAIN:
365            {
366                var args = read_regs(AP3216C_PS_CONFIGURATION_REG, 1);
367                args &= 0xf3;
368                args |= value;
369                write_reg(AP3216C_PS_CONFIGURATION_REG, args);
370
371                break;
372            }
373        case AP3216C_PS_PERSIST:
374            {
375                var args = read_regs(AP3216C_PS_CONFIGURATION_REG, 1);
376                args &= 0xfc;
377                args |= value;
378                write_reg(AP3216C_PS_CONFIGURATION_REG, args);
379
380                break;
381            }
382        case AP3216C_PS_LOW_THRESHOLD_L:
383            {
384                write_reg(AP3216C_PS_THRESHOLD_LOW_L_REG, value);
385
386                break;
387            }
388        case AP3216C_PS_LOW_THRESHOLD_H:
389            {
390                write_reg(AP3216C_PS_THRESHOLD_LOW_H_REG, value);
391
392                break;
393            }
394        case AP3216C_PS_HIGH_THRESHOLD_L:
395            {
396                write_reg(AP3216C_PS_THRESHOLD_HIGH_L_REG, value);
397
398                break;
399            }
400        case AP3216C_PS_HIGH_THRESHOLD_H:
401            {
402                write_reg(AP3216C_PS_THRESHOLD_HIGH_H_REG, value);
403
404                break;
405            }
406
407        default:
408            {
409            }
410    }
411}
412
413/**
414 * This function gets parameter of ap3216c sensor
415 *
416 * @param cmd the parameter cmd of device
417 * @param value to get value in cmd register
418 *
419 * @return the getting parameter status,RT_EOK reprensents getting successfully.
420 */
421function ap3216c_get_param(cmd)
422{
423    switch (cmd) {
424        case AP3216C_SYSTEM_MODE:
425            {
426                value = read_regs(AP3216C_SYS_CONFIGURATION_REG, 1);
427
428                break;
429            }
430        case AP3216C_INT_PARAM:
431            {
432                value = read_regs(AP3216C_SYS_INT_CLEAR_MANNER_REG, 1);
433
434                break;
435            }
436        case AP3216C_ALS_RANGE:
437            {
438                var value = read_regs(AP3216C_ALS_CONFIGURATION_REG, 1);
439                temp = (value & 0xff) >> 4;
440
441                value = temp;
442
443                break;
444            }
445        case AP3216C_ALS_PERSIST:
446            {
447                var temp = read_regs(AP3216C_ALS_CONFIGURATION_REG, 1);
448                temp = value & 0x0f;
449
450                value = temp;
451
452                break;
453            }
454        case AP3216C_ALS_LOW_THRESHOLD_L:
455            {
456                value = read_regs(AP3216C_ALS_THRESHOLD_LOW_L_REG, 1);
457
458                break;
459            }
460        case AP3216C_ALS_LOW_THRESHOLD_H:
461            {
462                value = read_regs(AP3216C_ALS_THRESHOLD_LOW_H_REG, 1);
463
464                break;
465            }
466        case AP3216C_ALS_HIGH_THRESHOLD_L:
467            {
468                value = read_regs(AP3216C_ALS_THRESHOLD_HIGH_L_REG, 1);
469
470                break;
471            }
472        case AP3216C_ALS_HIGH_THRESHOLD_H:
473            {
474                value = read_regs(AP3216C_ALS_THRESHOLD_HIGH_H_REG, 1);
475
476                break;
477            }
478        case AP3216C_PS_GAIN:
479            {
480                var temp = read_regs(AP3216C_PS_CONFIGURATION_REG, 1);
481
482                value = (temp & 0xc) >> 2;
483
484                break;
485            }
486        case AP3216C_PS_PERSIST:
487            {
488                var temp = read_regs(AP3216C_PS_CONFIGURATION_REG, 1);
489
490                value = temp & 0x3;
491
492                break;
493            }
494        case AP3216C_PS_LOW_THRESHOLD_L:
495            {
496                value = read_regs(AP3216C_PS_THRESHOLD_LOW_L_REG, 1);
497
498                break;
499            }
500        case AP3216C_PS_LOW_THRESHOLD_H:
501            {
502                value = read_regs(AP3216C_PS_THRESHOLD_LOW_H_REG, 1);
503                break;
504            }
505        case AP3216C_PS_HIGH_THRESHOLD_L:
506            {
507               value = read_regs(AP3216C_PS_THRESHOLD_HIGH_L_REG, 1);
508
509                break;
510            }
511        case AP3216C_PS_HIGH_THRESHOLD_H:
512            {
513                value = read_regs(AP3216C_PS_THRESHOLD_HIGH_H_REG, 1);
514
515                break;
516            }
517
518        default:
519            {
520            }
521    }
522    return value;
523}
524
525 // 初始化MPU6050
526// 返回值:0,成功
527// 其他,错误代码
528function init(i2cid) {
529
530    ap3216cDev = i2c.open({id: i2cid});
531    fakeSleep(100);
532
533    /* reset ap3216c */
534    reset_sensor();
535    fakeSleep(100);
536    ap3216c_set_param(AP3216C_SYSTEM_MODE, AP3216C_MODE_ALS_AND_PS);
537    fakeSleep(150); // delay at least 112.5ms
538
539    ap3216c_int_Config();
540    ap3216c_int_init();
541
542}
543
544// De-init qlc5883
545function deinit() {
546    ap3216cDev.close();
547}
548
549module.exports = {
550    init,
551    deinit,
552    ap3216c_read_ambient_light,
553    ap3216c_read_ps_data,
554    ap3216c_read_ir_data,
555    deinit,
556}