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