1 /*
2  * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3  *
4  *
5  */
6 
7 
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include "aos/kernel.h"
12 #include <aos/kernel.h>
13 #include "sensor_drv_api.h"
14 #include "sensor_hal.h"
15 
16 
17 /* AK9754 Register definitions */
18 #define AK9754_WIA1_REG        0x00 /* Company code */
19 #define AK9754_WIA2_REG        0x01 /* Device ID */
20 #define AK9754_INFO1_REG       0x02 /* Unused informatiln */
21 #define AK9754_INFO2_REG       0x03 /* Unused informatiln */
22 #define AK9754_ST1_REG         0x04 /* Status 1 */
23 #define AK9754_IRDL_REG        0x05 /* IR sensor data (lower) */
24 #define AK9754_IRDH_REG        0x06 /* IR sensor data (upper) */
25 #define AK9754_TMPL_REG        0x07 /* Integrated temperature sensor data (lower) */
26 #define AK9754_TMPH_REG        0x08 /* Integrated temperature sensor data (upper) */
27 #define AK9754_ST2_REG         0x09 /* Status 2 */
28 #define AK9754_ST3_REG         0x0A /* Status 3 */
29 #define AK9754_SB0L_REG        0x0B /* latest IR sensor data (lower) */
30 #define AK9754_SB0H_REG        0x0C /* latest IR sensor data (upper) */
31 #define AK9754_SB1L_REG        0x0D /* previous IR sensor data (lower) */
32 #define AK9754_SB1H_REG        0x0E /* previous IR sensor data (upper) */
33 #define AK9754_SB2L_REG        0x0F /* 2 previous IR sensor data (lower) */
34 #define AK9754_SB2H_REG        0x10 /* 2 previous IR sensor data (upper) */
35 #define AK9754_SB3L_REG        0x11 /* 3 previous IR sensor data (lower) */
36 #define AK9754_SB3H_REG        0x12 /* 3 previous IR sensor data (upper) */
37 #define AK9754_SB4L_REG        0x13 /* 4 previous IR sensor data (lower) */
38 #define AK9754_SB4H_REG        0x14 /* 4 previous IR sensor data (upper) */
39 #define AK9754_SB5L_REG        0x15 /* 5 previous IR sensor data (lower) */
40 #define AK9754_SB5H_REG        0x16 /* 5 previous IR sensor data (upper) */
41 #define AK9754_SB6L_REG        0x17 /* 6 previous IR sensor data (lower) */
42 #define AK9754_SB6H_REG        0x18 /* 6 previous IR sensor data (upper) */
43 #define AK9754_SB7L_REG        0x19 /* 7 previous IR sensor data (lower) */
44 #define AK9754_SB7H_REG        0x1A /* 7 previous IR sensor data (upper) */
45 #define AK9754_SB8L_REG        0x1B /* 8 previous IR sensor data (lower) */
46 #define AK9754_SB8H_REG        0x1C /* 8 previous IR sensor data (upper) */
47 #define AK9754_SB9L_REG        0x1D /* oldest IR sensor data (lower) */
48 #define AK9754_SB9H_REG        0x1E /* oldest IR sensor data (lower) */
49 #define AK9754_ST4_REG         0x1F /* Status 4 */
50 #define AK9754_CTRL1_REG       0x20 /* Software reset */
51 #define AK9754_CTRL2_REG       0x21 /* Sync mode setting */
52 #define AK9754_CTRL3_REG       0x22 /* Lownoise mode / odr / tmp_fc / ird_fc settings */
53 #define AK9754_CTRL4_REG       0x23 /* Track mode settings */
54 #define AK9754_CTRL5_REG       0x24 /* TMP offset settings */
55 #define AK9754_CTRL6_REG       0x25 /* IRD gain settings */
56 #define AK9754_CTRL7_REG       0x26 /* Invert mode / wait time settings */
57 #define AK9754_CTRL8_REG       0x27 /* NSAMPLE settings */
58 #define AK9754_CTRL9_REG       0x28 /* Threshold level settings (lower) */
59 #define AK9754_CTRL10_REG      0x29 /* Threshold level settings (upper) */
60 #define AK9754_CTRL11_REG      0x2A /* Enable/Disable settings */
61 #define AK9754_CTRL12_REG      0x2B /* Mode */
62 
63 /* Register helper values */
64 #define AK9754_COMPANY_ID      0x48 /* Company ID of AKM */
65 #define AK9754_DEVICE_ID       0x15 /* Device ID of AK9754 */
66 #define AK9754_WIA_VAL         0x1548
67 
68 #define AK9754_ST1_DRDY        0x01 /* bit mask of DRDY for ST1 */
69 #define AK9754_ST1_HBD_ONCE    0x10 /* bit mask of HBD_ONCE for ST1 */
70 
71 #define AK9754_CTRL1_SRST         1 /* bit mask of SRST for CTRL1 */
72 
73 #define AK9754_CTRL3_IRD_FC_SHIFT       0
74 #define AK9754_CTRL3_TMP_FC_SHIFT       2
75 #define AK9754_CTRL3_ODR_SHIFT          4
76 #define AK9754_CTRL3_LOWNOISEMODE_SHIFT 6
77 /* helper function to make CTRL3 register's value */
78 #define AK9754_CTRL3(lnmode, odr, tmpfc, irdfc) \
79     ((lnmode) << (AK9754_CTRL3_LOWNOISEMODE_SHIFT) | \
80      (odr) << (AK9754_CTRL3_ODR_SHIFT) | \
81      (tmpfc) << (AK9754_CTRL3_TMP_FC_SHIFT) | \
82      (irdfc) << (AK9754_CTRL3_IRD_FC_SHIFT))
83 
84 #define AK9754_CTRL7_HBD_INVERT_SHIFT   3
85 #define AK9754_CTRL7_HBD_WAITTIME_SHIFT 0
86 /* helper function to make CTRL7 register's value */
87 #define AK9754_CTRL7(invert, waittime) \
88     ((invert) << (AK9754_CTRL7_HBD_INVERT_SHIFT) | \
89      (waittime) << (AK9754_CTRL7_HBD_WAITTIME_SHIFT))
90 
91 /* helper function to make CTRL9 / CTRL10 register's value */
92 #define AK9754_CTRL9(thld) ((thld) & 0xff)
93 #define AK9754_CTRL10(thld) (((thld) & 0xff00) >> 8)
94 
95 #define AK9754_CNTL11_INT_ENABLE_DRDY 0x01
96 #define AK9754_CNTL11_INT_ENABLE_HBD  0x02
97 #define AK9754_CNTL11_SB_ENABLE       0x04
98 #define AK9754_CNTL11_SB_STOP_ON_HBD  0x08
99 #define AK9754_CNTL11_HBD_ENABLE      0x10
100 
101 #define AK9754_CTRL12_MODE_STANDBY 0x00 /* Standby mode */
102 #define AK9754_CTRL12_MODE_MEASURE 0x01 /* Continuous measurement mode */
103 
104 #define AK9754_SUPPORTED_ODR_POWER_DOWN 0
105 #define AK9754_SUPPORTED_ODR_1HZ        1
106 #define AK9754_SUPPORTED_ODR_2HZ        2
107 #define AK9754_SUPPORTED_ODR_10HZ       10
108 #define AK9754_SUPPORTED_ODR_50HZ       50
109 
110 /*
111  * The values below are generate automatically
112  */
113 /* CNTL3 values */
114 /* LOWNOISEMODE bit: valid value is 1 or 0 */
115 #define AK9754_LOWNOISEMODE_VAL    1
116 /* ODR bit: valid rang is [0x00, 0x03] 00 1Hz 01 2Hz 02 10Hz 03 50Hz*/
117 #define AK9754_ODR_VAL             0x02
118 /* TMP_FC bit: valid rang is [0x00, 0x02] */
119 #define AK9754_TMP_FC_VAL          0x01
120 /* IRD_FC bit: valid rang is [0x00, 0x02] */
121 #define AK9754_IRD_FC_VAL          0x01
122 
123 /* CNTL4 valus */
124 /* TRACKMODE bit: valid rang is [0x00, 0x07] */
125 #define AK9754_TRACKMODE_VAL       0x00
126 
127 /* CNTL5 values */
128 /* TMP_OFFSET bit: valid rang is [0xc0, 0x3f] ([-64, 63]) */
129 #define AK9754_TMP_OFFSET_VAL      0x80
130 
131 /* CNTL6 values */
132 /* IRD_GAIN bit: valid rang is [0xf0, 0x0f] ([-16, 15]) */
133 #define AK9754_IRD_GAIN_VAL        0xfa
134 
135 /* CNTL7 values */
136 /* HBD_INVERT bit: valid value is 1 or 0  */
137 #define AK9754_INVERT_VAL          0
138 /* HBD_WAITTIME bit: valid range is [0x00, 0x07] */
139 #define AK9754_WAITTIME_VAL        0
140 
141 /* CNTL8 values */
142 /* HBD_NSAMPLE bit: valid range is [0x00, 0x7f] */
143 #define AK9754_NSAMPLE_VAL         0x01
144 
145 /* CNTL9, 10 values */
146 /* HBD_THLD  bit: valid range is [0x0000, 0x7fff] ([0, 32767]) */
147 #define AK9754_THLD_VAL            75
148 
149 #define AK9754_DEVICE_NAME    "AK9754"
150 
151 #define AKM_SUCCESS           (0)
152 #define AKM_ERROR             (-1)
153 
154 #define MEASURE_WAIT_TIME     (20)
155 
156 #define AK9754_DEFAULT_MODE   AK9754_CTRL3(AK9754_LOWNOISEMODE_VAL, AK9754_ODR_VAL, AK9754_TMP_FC_VAL, AK9754_IRD_FC_VAL) /* Default 10Hz */
157 
158 #define AKM_DEVICE_NAME       AK9754_DEVICE_NAME
159 
160 #define AKM_LOG(format, ...)  LOG("%s %s %s " format, SENSOR_STR, \
161                                   AKM_DEVICE_NAME, __func__, \
162                                   ## __VA_ARGS__)
163 
164 /*************************************************
165 CAD1               CAD0            Slave Address
166 VSS                VSS                60H
167 VSS                non-connected      61H
168 VSS                VDD                62H
169 non-connected      VSS                64H
170 non-connected      non-connected      65H
171 non-connected      VDD                66H
172 VDD                VSS                68H
173 VDD                non-connected      69H
174 VDD                VDD              Do Not Use
175 ************************************************/
176 i2c_dev_t ak9754_dev = {
177     .port = 3,
178     .config.address_width = 8,
179     .config.dev_addr = 0x60 << 1,
180     .config.freq = 100,
181 };
182 
drv_ir_akm_ak9754_set_mode(i2c_dev_t * dev,const uint8_t mode)183 static int16_t drv_ir_akm_ak9754_set_mode(
184     i2c_dev_t *dev,
185     const uint8_t   mode)
186 {
187     int16_t ret = 0;
188     uint8_t i2c_data = mode;
189 
190     ret = sensor_i2c_write(dev, AK9754_CTRL12_REG, &i2c_data, 1, I2C_OP_RETRIES);
191     if (unlikely(ret)) {
192         return ret;
193     }
194 
195     return ret;
196 }
197 
drv_ir_akm_ak9754_soft_reset(i2c_dev_t * dev)198 static int drv_ir_akm_ak9754_soft_reset(i2c_dev_t *dev)
199 {
200     int     ret = 0;
201     uint8_t i2c_data = AK9754_CTRL1_SRST;
202 
203     ret = sensor_i2c_write(dev, AK9754_CTRL1_REG, &i2c_data, 1, I2C_OP_RETRIES);
204     if (unlikely(ret)) {
205         return ret;
206     }
207 
208     return ret;
209 }
210 
drv_ir_akm_ak9754_valid_id(i2c_dev_t * dev)211 static int16_t drv_ir_akm_ak9754_valid_id(i2c_dev_t *dev)
212 {
213     int      ret = 0;
214     uint8_t  i2c_data[2];
215     uint16_t id = 0;
216 
217     ret = sensor_i2c_read(dev, AK9754_WIA1_REG, i2c_data, 2, I2C_OP_RETRIES);
218     if (unlikely(ret)) {
219         return ret;
220     }
221 
222     id = (uint16_t)(((uint16_t)i2c_data[1] << 8) | i2c_data[0]);
223 
224     if (AK9754_WIA_VAL != id) {
225         AKM_LOG("invalid device.\n");
226         return AKM_ERROR;
227     }
228 
229     return 0;
230 }
231 
drv_ir_akm_ak9754_irq_handle(void)232 static void drv_ir_akm_ak9754_irq_handle(void)
233 {
234     /* no handle so far */
235 }
236 
drv_ir_akm_ak9754_open(void)237 static int drv_ir_akm_ak9754_open(void)
238 {
239     int16_t   ret = 0;
240     i2c_dev_t *dev = &ak9754_dev;
241 
242     ret = drv_ir_akm_ak9754_set_mode(dev, AK9754_CTRL12_MODE_MEASURE);
243     if (unlikely(ret)) {
244         return ret;
245     }
246 
247     AKM_LOG("successfully \n");
248     return ret;
249 }
250 
drv_ir_akm_ak9754_close(void)251 static int drv_ir_akm_ak9754_close(void)
252 {
253     int16_t   ret = 0;
254     i2c_dev_t *dev = &ak9754_dev;
255 
256     ret = drv_ir_akm_ak9754_set_mode(dev, AK9754_CTRL12_MODE_STANDBY);
257     if (unlikely(ret)) {
258         return ret;
259     }
260 
261     AKM_LOG("successfully \n");
262     return ret;
263 }
264 
drv_ir_akm_ak9754_read(void * buf,size_t len)265 static int drv_ir_akm_ak9754_read(
266     void   *buf,
267     size_t len)
268 {
269     //ir_data_t *ir_data = (ir_data_t *)buf;
270     ir_data_t *ir_data = (ir_data_t *)buf;
271     i2c_dev_t  *dev = &ak9754_dev;
272     size_t     size;
273     uint8_t    i2c_data[6];
274     int16_t    ret = 0;
275 
276     if (NULL == buf) {
277         return AKM_ERROR;
278     }
279 
280     size = sizeof(ir_data_t);
281 
282     if (len < size) {
283         return AKM_ERROR;
284     }
285 
286     /* Get measurement data from AK9754
287      * ST1 + (IRDL + IRDH) + (TMPL+ TMPH) + ST2 = 6bytes */
288     ret = sensor_i2c_read(dev, AK9754_ST1_REG, i2c_data, 6,
289                           I2C_OP_RETRIES);
290     if (unlikely(ret)) {
291         return ret;
292     }
293 
294     //ir_data->ir = (uint32_t)((int16_t)(i2c_data[1] | (((uint16_t)i2c_data[2]) << 8) + 32767);
295     ir_data->ir = (uint32_t)((int16_t)(i2c_data[1] | ((uint16_t)i2c_data[2] << 8)) + 32767);
296     ir_data->timestamp = aos_now_ms();
297 
298     return (int)size;
299 }
300 
drv_ir_akm_ak9754_write(const void * buf,size_t len)301 static int drv_ir_akm_ak9754_write(
302     const void *buf,
303     size_t     len)
304 {
305     (void)buf;
306     (void)len;
307     return 0;
308 }
309 
drv_ir_akm_ak9754_set_odr(i2c_dev_t * dev,const uint32_t odr)310 static int drv_ir_akm_ak9754_set_odr(
311     i2c_dev_t *dev,
312     const uint32_t  odr)
313 {
314     uint8_t ODR_VAL = 0;
315     int ret;
316 
317     if (odr == AK9754_SUPPORTED_ODR_POWER_DOWN) {
318         ret = drv_ir_akm_ak9754_close();
319         if (unlikely(ret)) {
320             return ret;
321         }
322     } else if (odr <= AK9754_SUPPORTED_ODR_1HZ) {
323         ODR_VAL = AK9754_CTRL3(AK9754_LOWNOISEMODE_VAL, 0x00, AK9754_TMP_FC_VAL,
324                                  AK9754_IRD_FC_VAL);
325     } else if (odr <= AK9754_SUPPORTED_ODR_2HZ) {
326         ODR_VAL = AK9754_CTRL3(AK9754_LOWNOISEMODE_VAL, 0x01, AK9754_TMP_FC_VAL,
327                                  AK9754_IRD_FC_VAL);
328     } else if (odr <= AK9754_SUPPORTED_ODR_10HZ) {
329         ODR_VAL = AK9754_CTRL3(AK9754_LOWNOISEMODE_VAL, AK9754_ODR_VAL, AK9754_TMP_FC_VAL,
330                                  AK9754_IRD_FC_VAL);
331     } else if (odr <= AK9754_SUPPORTED_ODR_50HZ) {
332         ODR_VAL = AK9754_CTRL3(AK9754_LOWNOISEMODE_VAL, 0x03, AK9754_TMP_FC_VAL,
333                                  AK9754_IRD_FC_VAL);
334     } else {
335         AKM_LOG("unsupported ODR : %d, set to default mode\n", odr);
336         ODR_VAL = AK9754_DEFAULT_MODE;
337     }
338 
339     ret = sensor_i2c_write(dev, AK9754_CTRL3_REG, &ODR_VAL, 1, I2C_OP_RETRIES);
340     if (unlikely(ret)) {
341         return ret;
342     }
343 
344     ret = drv_ir_akm_ak9754_open();
345     if (unlikely(ret)) {
346         return ret;
347     }
348 
349     return 0;
350 }
351 
drv_ir_akm_ak9754_get_info(dev_sensor_info_t * info)352 static void drv_ir_akm_ak9754_get_info(dev_sensor_info_t *info)
353 {
354     info->vendor = DEV_SENSOR_VENDOR_AKM;
355     info->model = AKM_DEVICE_NAME;
356     info->unit = cm;
357     info->range_max =  15000;
358     info->range_min = -15000;
359 
360     return;
361 }
362 
drv_ir_akm_ak9754_set_default_config(i2c_dev_t * dev)363 static int16_t drv_ir_akm_ak9754_set_default_config(i2c_dev_t *dev)
364 {
365     int16_t ret = 0;
366 
367     /*
368      * setup measurement conditions (CTRL3 ~ CTRL6)
369      */
370     /* CTRL3 : Lownoise mode / odr / tmpfc / irdfc settings */
371     uint8_t i2c_data = AK9754_CTRL3(AK9754_LOWNOISEMODE_VAL, AK9754_ODR_VAL, AK9754_TMP_FC_VAL,
372                                  AK9754_IRD_FC_VAL);
373 
374     ret = sensor_i2c_write(dev, AK9754_CTRL3_REG, &i2c_data, 1, I2C_OP_RETRIES);
375     if (unlikely(ret)) {
376         return ret;
377     }
378 
379     /* CTRL4 : Track mode settings */
380     i2c_data = AK9754_TRACKMODE_VAL;
381     ret = sensor_i2c_write(dev, AK9754_CTRL4_REG, &i2c_data, 1, I2C_OP_RETRIES);
382     if (unlikely(ret)) {
383         return ret;
384     }
385 
386     /* CTRL5 : TMP offset settings */
387     i2c_data = AK9754_TMP_OFFSET_VAL;
388     ret = sensor_i2c_write(dev, AK9754_CTRL5_REG, &i2c_data, 1, I2C_OP_RETRIES);
389     if (unlikely(ret)) {
390         return ret;
391     }
392 
393     /* CTRL6 : IRD gain settings */
394     i2c_data = AK9754_IRD_GAIN_VAL;
395     ret = sensor_i2c_write(dev, AK9754_CTRL6_REG, &i2c_data, 1, I2C_OP_RETRIES);
396     if (unlikely(ret)) {
397         return ret;
398     }
399 
400     /*
401      * setup parameteres for human body detection (CTRL7 ~ CTRL10)
402      */
403     /* CTRL7 : Invert mode / waittime settings */
404     i2c_data = AK9754_CTRL7(AK9754_INVERT_VAL, AK9754_WAITTIME_VAL);
405     ret = sensor_i2c_write(dev, AK9754_CTRL7_REG, &i2c_data, 1, I2C_OP_RETRIES);
406     if (unlikely(ret)) {
407         return ret;
408     }
409 
410     /* CTRL8 : NSAMPLE settings */
411     i2c_data = AK9754_NSAMPLE_VAL;
412     ret = sensor_i2c_write(dev, AK9754_CTRL8_REG, &i2c_data, 1, I2C_OP_RETRIES);
413     if (unlikely(ret)) {
414         return ret;
415     }
416 
417     /* CTRL9 : Threshold level settings (lower) */
418     i2c_data = AK9754_CTRL9(AK9754_THLD_VAL);
419     ret = sensor_i2c_write(dev, AK9754_CTRL9_REG, &i2c_data, 1, I2C_OP_RETRIES);
420     if (unlikely(ret)) {
421         return ret;
422     }
423 
424     /* CTRL10 : Threshold level settings (upper) */
425     i2c_data = AK9754_CTRL10(AK9754_THLD_VAL);
426     ret = sensor_i2c_write(dev, AK9754_CTRL10_REG, &i2c_data, 1, I2C_OP_RETRIES);
427     if (unlikely(ret)) {
428         return ret;
429     }
430 
431     /*
432      * device interrupt settings
433      *   In this codes, AK9754 rise interrupts when human is detected
434      */
435     /* CTRL11 : function's Enable / Disable settings */
436     i2c_data = AK9754_CNTL11_HBD_ENABLE | AK9754_CNTL11_INT_ENABLE_HBD;
437     ret = sensor_i2c_write(dev, AK9754_CTRL11_REG, &i2c_data, 1, I2C_OP_RETRIES);
438     if (unlikely(ret)) {
439         return ret;
440     }
441 
442     return ret;
443 }
444 
445 
446 
drv_ir_akm_ak9754_ioctl(int cmd,unsigned long arg)447 int drv_ir_akm_ak9754_ioctl(
448     int           cmd,
449     unsigned long arg)
450 {
451     int           ret = 0;
452     dev_sensor_info_t *info = (dev_sensor_info_t *) arg;
453 
454     switch (cmd) {
455     case SENSOR_IOCTL_ODR_SET:
456         ret = drv_ir_akm_ak9754_set_odr(&ak9754_dev, (int)arg);
457         if (unlikely(ret)) {
458             return AKM_ERROR;
459         }
460 
461         break;
462 
463     case SENSOR_IOCTL_RANGE_SET:
464         break;
465 
466     case SENSOR_IOCTL_GET_INFO:
467         drv_ir_akm_ak9754_get_info(info);
468         break;
469 
470     case SENSOR_IOCTL_BIST_PROCESS:
471         break;
472 
473     case SENSOR_IOCTL_WHO_AM_I:
474         break;
475 
476     case SENSOR_IOCTL_SET_POWER:
477         break;
478 
479     case SENSOR_IOCTL_GET_SENSOR_LIST:
480         break;
481 
482     case SENSOR_IOCTL_DTC_CYCLE_SET:
483         break;
484 
485     default:
486         break;
487     }
488 
489     return ret;
490 }
491 
drv_ir_akm_ak9754_init(void)492 int drv_ir_akm_ak9754_init(void)
493 {
494     int16_t      ret = 0;
495     sensor_obj_t sensor;
496     memset(&sensor, 0, sizeof(sensor));
497 
498     /* fill the sensor obj parameters here */
499     sensor.tag = TAG_DEV_IR;
500     sensor.path = dev_ir_path;
501     sensor.io_port = I2C_PORT;
502     sensor.open = drv_ir_akm_ak9754_open;
503     sensor.close = drv_ir_akm_ak9754_close;
504     sensor.read = drv_ir_akm_ak9754_read;
505     sensor.write = drv_ir_akm_ak9754_write;
506     sensor.ioctl = drv_ir_akm_ak9754_ioctl;
507     sensor.irq_handle = drv_ir_akm_ak9754_irq_handle;
508 
509     ret = sensor_create_obj(&sensor);
510     if (unlikely(ret)) {
511         return (int)ret;
512     }
513 
514     ret = drv_ir_akm_ak9754_valid_id(&ak9754_dev);
515     if (unlikely(ret)) {
516         return (int)ret;
517     }
518 
519     ret = drv_ir_akm_ak9754_soft_reset(&ak9754_dev);
520     if (unlikely(ret)) {
521         return (int)ret;
522     }
523 
524     ret = drv_ir_akm_ak9754_set_default_config(&ak9754_dev);
525     if (unlikely(ret)) {
526         return (int)ret;
527     }
528 
529     AKM_LOG("successfully.\n");
530     return (int)ret;
531 }
532 
533 SENSOR_DRV_ADD(drv_ir_akm_ak9754_init);
534 
535