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
11 #include "aos/kernel.h"
12 #include "ulog/ulog.h"
13
14 #include <k_api.h>
15
16 #include "sensor_drv_api.h"
17 #include "sensor_hal.h"
18
19 #define MMC3680KJ_REG_DATA 0x00
20 #define MMC3680KJ_REG_XL 0x00
21 #define MMC3680KJ_REG_XH 0x01
22 #define MMC3680KJ_REG_YL 0x02
23 #define MMC3680KJ_REG_YH 0x03
24 #define MMC3680KJ_REG_ZL 0x04
25 #define MMC3680KJ_REG_ZH 0x05
26 #define MMC3680KJ_REG_TEMP 0x06
27 #define MMC3680KJ_REG_STATUS 0x07
28 #define MMC3680KJ_REG_CTRL0 0x08
29 #define MMC3680KJ_REG_CTRL1 0x09
30 #define MMC3680KJ_REG_CTRL2 0x0a
31 #define MMC3680KJ_REG_X_THD 0x0b
32 #define MMC3680KJ_REG_Y_THD 0x0c
33 #define MMC3680KJ_REG_Z_THD 0x0d
34 #define MMC3680KJ_REG_SELFTEST 0x0e
35 #define MMC3680KJ_REG_PASSWORD 0x0f
36 #define MMC3680KJ_REG_OTPMODE 0x12
37 #define MMC3680KJ_REG_TESTMODE 0x13
38 #define MMC3680KJ_REG_SR_PWIDTH 0x20
39 #define MMC3680KJ_REG_OTP 0x2a
40 #define MMC3680KJ_REG_PRODUCTID 0x2f
41
42 #define MMC3680KJ_CMD_REFILL 0x20
43 #define MMC3680KJ_CMD_RESET 0x10
44 #define MMC3680KJ_CMD_SET 0x08
45 #define MMC3680KJ_CMD_TM_M 0x01
46 #define MMC3680KJ_CMD_TM_T 0x02
47 #define MMC3680KJ_CMD_START_MDT 0x04
48 #define MMC3680KJ_CMD_100HZ 0x00
49 #define MMC3680KJ_CMD_200HZ 0x01
50 #define MMC3680KJ_CMD_400HZ 0x02
51 #define MMC3680KJ_CMD_600HZ 0x03
52 #define MMC3680KJ_CMD_CM_14HZ 0x01
53 #define MMC3680KJ_CMD_CM_5HZ 0x02
54 #define MMC3680KJ_CMD_CM_1HZ 0x04
55 #define MMC3680KJ_CMD_SW_RST 0x80
56 #define MMC3680KJ_CMD_PASSWORD 0xe1
57 #define MMC3680KJ_CMD_OTP_OPER 0x11
58 #define MMC3680KJ_CMD_OTP_MR 0x80
59 #define MMC3680KJ_CMD_OTP_ACT 0x80
60 #define MMC3680KJ_CMD_OTP_NACT 0x00
61 #define MMC3680KJ_CMD_STSET_OPEN 0x02
62 #define MMC3680KJ_CMD_STRST_OPEN 0x04
63 #define MMC3680KJ_CMD_ST_CLOSE 0x00
64 #define MMC3680KJ_CMD_INT_MD_EN 0x40
65 #define MMC3680KJ_CMD_INT_MDT_EN 0x20
66
67 #define MMC3680KJ_PRODUCT_ID 0x0a
68 #define MMC3680KJ_OTP_READ_DONE_BIT 0x10
69 #define MMC3680KJ_PUMP_ON_BIT 0x08
70 #define MMC3680KJ_MDT_BIT 0x04
71 #define MMC3680KJ_MEAS_T_DONE_BIT 0x02
72 #define MMC3680KJ_MEAS_M_DONE_BIT 0x01
73
74 #define MMC3680KJ_I2C_SLAVE_ADDR 0x30
75 #define MMC3680KJ_ADDR_TRANS(n) ((n) << 1)
76 #define MMC3680KJ_I2C_ADDR MMC3680KJ_ADDR_TRANS(MMC3680KJ_I2C_SLAVE_ADDR)
77
78 #define MMC3680KJ_OFFSET 32768
79 #define MMC3680KJ_SENSITIVITY 1024000
80 #define MMC3680KJ_T_ZERO -75
81 #define MMC3680KJ_T_SENSITIVITY 80
82
83 #define MMC3680KJ_MAG_DATA_SIZE 6
84 #define OTP_CONVERT(REG) (((REG) >= 32 ? (32 - (REG)) : (REG)) * 6)
85
86 typedef enum
87 {
88 FLAG_INIT_MAG = 0,
89 FLAG_INIT_TEMP,
90 } FLAG_INIT_BIT;
91
92 i2c_dev_t mmc3680kj_ctx = {
93 .port = 4,
94 .config.address_width = 7,
95 .config.freq = 100000,
96 .config.dev_addr = MMC3680KJ_I2C_ADDR,
97 };
98
99 static uint8_t g_init_bitwise = 0;
100 static int32_t g_otp_matrix[3] = { 1000000, 1000000, 1350000 };
101
mmc3680kj_validate_id(i2c_dev_t * drv,uint8_t product_id)102 static int mmc3680kj_validate_id(i2c_dev_t *drv, uint8_t product_id)
103 {
104 uint8_t value = 0;
105 int ret = 0;
106
107 if (drv == NULL) {
108 return -1;
109 }
110
111 ret = sensor_i2c_read(drv, MMC3680KJ_REG_PRODUCTID, &value, I2C_DATA_LEN,
112 I2C_OP_RETRIES);
113 if (unlikely(ret)) {
114 return ret;
115 }
116
117 if (value != product_id) {
118 return -1;
119 }
120
121 return 0;
122 }
123
mmc3680kj_check_otp(i2c_dev_t * drv)124 static int mmc3680kj_check_otp(i2c_dev_t *drv)
125 {
126 uint8_t value = 0;
127 int ret = 0;
128
129 if (drv == NULL) {
130 return -1;
131 }
132
133 ret = sensor_i2c_read(drv, MMC3680KJ_REG_STATUS, &value, I2C_DATA_LEN,
134 I2C_OP_RETRIES);
135 if (unlikely(ret)) {
136 return ret;
137 }
138
139 if ((value & MMC3680KJ_OTP_READ_DONE_BIT) != MMC3680KJ_OTP_READ_DONE_BIT) {
140 return -1;
141 }
142
143 return 0;
144 }
145
mmc3680kj_get_comp_matrix(i2c_dev_t * drv)146 static int mmc3680kj_get_comp_matrix(i2c_dev_t *drv)
147 {
148 uint8_t value = 0;
149 uint8_t reg_data[2] = { 0 };
150 int ret = 0;
151
152 if (drv == NULL) {
153 return -1;
154 }
155
156 value = MMC3680KJ_CMD_PASSWORD;
157 ret = sensor_i2c_write(drv, MMC3680KJ_REG_PASSWORD, &value, I2C_DATA_LEN,
158 I2C_OP_RETRIES);
159 if (unlikely(ret)) {
160 return ret;
161 }
162
163 value = MMC3680KJ_CMD_OTP_OPER;
164 ret = sensor_i2c_write(drv, MMC3680KJ_REG_OTPMODE, &value, I2C_DATA_LEN,
165 I2C_OP_RETRIES);
166 if (unlikely(ret)) {
167 return ret;
168 }
169
170 value = MMC3680KJ_CMD_OTP_MR;
171 ret = sensor_i2c_write(drv, MMC3680KJ_REG_TESTMODE, &value, I2C_DATA_LEN,
172 I2C_OP_RETRIES);
173 if (unlikely(ret)) {
174 return ret;
175 }
176
177 value = MMC3680KJ_CMD_OTP_ACT;
178 ret = sensor_i2c_write(drv, MMC3680KJ_REG_CTRL2, &value, I2C_DATA_LEN,
179 I2C_OP_RETRIES);
180 if (unlikely(ret)) {
181 return ret;
182 }
183
184 ret = sensor_i2c_read(drv, MMC3680KJ_REG_OTP, reg_data, 2, I2C_OP_RETRIES);
185 if (unlikely(ret)) {
186 return ret;
187 }
188
189 value = MMC3680KJ_CMD_OTP_NACT;
190 ret = sensor_i2c_write(drv, MMC3680KJ_REG_CTRL2, &value, I2C_DATA_LEN,
191 I2C_OP_RETRIES);
192 if (unlikely(ret)) {
193 return ret;
194 }
195
196 g_otp_matrix[0] = 1000000;
197 g_otp_matrix[1] = OTP_CONVERT(reg_data[0] & 0x3f) * 1000 + 1000000;
198 g_otp_matrix[2] =
199 (OTP_CONVERT((reg_data[1] & 0x0f) << 2 | (reg_data[0] & 0xc0) >> 6) +
200 1000) *
201 1350;
202
203 return 0;
204 }
205
mmc3680kj_set_pulse_width(i2c_dev_t * drv)206 static int mmc3680kj_set_pulse_width(i2c_dev_t *drv)
207 {
208 uint8_t value = 0;
209 int ret = 0;
210
211 if (drv == NULL) {
212 return -1;
213 }
214
215 value = MMC3680KJ_CMD_OTP_NACT;
216 ret = sensor_i2c_write(drv, MMC3680KJ_REG_CTRL2, &value, I2C_DATA_LEN,
217 I2C_OP_RETRIES);
218 if (unlikely(ret)) {
219 return ret;
220 }
221
222 value = MMC3680KJ_CMD_PASSWORD;
223 ret = sensor_i2c_write(drv, MMC3680KJ_REG_PASSWORD, &value, I2C_DATA_LEN,
224 I2C_OP_RETRIES);
225 if (unlikely(ret)) {
226 return ret;
227 }
228
229 ret = sensor_i2c_read(drv, MMC3680KJ_REG_SR_PWIDTH, &value, I2C_DATA_LEN,
230 I2C_OP_RETRIES);
231 if (unlikely(ret)) {
232 return ret;
233 }
234
235 value &= 0xe7;
236
237 ret = sensor_i2c_write(drv, MMC3680KJ_REG_SR_PWIDTH, &value, I2C_DATA_LEN,
238 I2C_OP_RETRIES);
239 if (unlikely(ret)) {
240 return ret;
241 }
242
243 return 0;
244 }
245
mmc3680kj_set(i2c_dev_t * drv)246 static int mmc3680kj_set(i2c_dev_t *drv)
247 {
248 uint8_t value = 0;
249 int ret = 0;
250
251 if (drv == NULL) {
252 return -1;
253 }
254
255 value = MMC3680KJ_CMD_SET;
256 ret = sensor_i2c_write(drv, MMC3680KJ_REG_CTRL0, &value, I2C_DATA_LEN,
257 I2C_OP_RETRIES);
258 if (unlikely(ret)) {
259 return ret;
260 }
261
262 krhino_task_sleep(krhino_ms_to_ticks(1));
263
264 return 0;
265 }
266
mmc3680kj_set_output_resolution(i2c_dev_t * drv,uint8_t res)267 static int mmc3680kj_set_output_resolution(i2c_dev_t *drv, uint8_t res)
268 {
269 int ret = 0;
270
271 if (drv == NULL) {
272 return -1;
273 }
274
275 ret = sensor_i2c_write(drv, MMC3680KJ_REG_CTRL1, &res, I2C_DATA_LEN,
276 I2C_OP_RETRIES);
277 if (unlikely(ret)) {
278 return ret;
279 }
280
281 return 0;
282 }
283
mmc3680kj_enable(i2c_dev_t * drv,FLAG_INIT_BIT flag)284 static int mmc3680kj_enable(i2c_dev_t *drv, FLAG_INIT_BIT flag)
285 {
286 uint8_t value = 0;
287 int ret = 0;
288
289 if (drv == NULL) {
290 return -1;
291 }
292
293 if (flag == FLAG_INIT_MAG) {
294 value = MMC3680KJ_CMD_TM_M;
295 ret = sensor_i2c_write(drv, MMC3680KJ_REG_CTRL0, &value, I2C_DATA_LEN,
296 I2C_OP_RETRIES);
297 if (unlikely(ret)) {
298 return ret;
299 }
300
301 do {
302 krhino_task_sleep(krhino_ms_to_ticks(10));
303 ret = sensor_i2c_read(drv, MMC3680KJ_REG_STATUS, &value,
304 I2C_DATA_LEN, I2C_OP_RETRIES);
305 if (unlikely(ret)) {
306 return ret;
307 }
308 } while ((value & 0x01) != 0x01);
309 } else if (flag == FLAG_INIT_TEMP) {
310 value = MMC3680KJ_CMD_TM_T;
311 ret = sensor_i2c_write(drv, MMC3680KJ_REG_CTRL0, &value, I2C_DATA_LEN,
312 I2C_OP_RETRIES);
313 if (unlikely(ret)) {
314 return ret;
315 }
316
317 do {
318 krhino_task_sleep(krhino_ms_to_ticks(10));
319 ret = sensor_i2c_read(drv, MMC3680KJ_REG_STATUS, &value,
320 I2C_DATA_LEN, I2C_OP_RETRIES);
321 if (unlikely(ret)) {
322 return ret;
323 }
324 } while ((value & 0x02) != 0x02);
325 } else {
326 return -1;
327 }
328
329 return 0;
330 }
331
mmc3680kj_need_set()332 static int mmc3680kj_need_set()
333 {
334 static sys_time_t last_time = 0;
335 sys_time_t now_time = 0;
336
337 now_time = krhino_sys_time_get();
338 if (now_time - last_time > 5000) {
339 last_time = now_time;
340 return 1;
341 }
342
343 return 0;
344 }
345
drv_mag_memsic_mmc3680kj_irq_handle(void)346 static void drv_mag_memsic_mmc3680kj_irq_handle(void)
347 {
348 /* no handle so far */
349 }
350
drv_mag_memsic_mmc3680kj_open(void)351 static int drv_mag_memsic_mmc3680kj_open(void)
352 {
353 int ret = 0;
354
355 ret = mmc3680kj_set(&mmc3680kj_ctx);
356 if (unlikely(ret)) {
357 return ret;
358 }
359 LOG("%s %s successfully \n", SENSOR_STR, __func__);
360
361 return 0;
362 }
363
drv_mag_memsic_mmc3680kj_close(void)364 static int drv_mag_memsic_mmc3680kj_close(void)
365 {
366 LOG("%s %s successfully \n", SENSOR_STR, __func__);
367
368 return 0;
369 }
370
drv_mag_memsic_mmc3680kj_read(void * buf,size_t len)371 static int drv_mag_memsic_mmc3680kj_read(void *buf, size_t len)
372 {
373 int ret = 0;
374 size_t size;
375 mag_data_t *pdata = (mag_data_t *)buf;
376 uint8_t reg_raw[MMC3680KJ_MAG_DATA_SIZE] = { 0 };
377 uint16_t data_raw[3] = { 0 };
378 uint32_t mag_raw[3] = { 0 };
379
380 if (buf == NULL) {
381 return -1;
382 }
383
384 size = sizeof(mag_data_t);
385 if (len < size) {
386 return -1;
387 }
388
389 if (mmc3680kj_need_set()) {
390 ret = mmc3680kj_set(&mmc3680kj_ctx);
391 if (unlikely(ret)) {
392 return ret;
393 }
394 }
395
396 ret = mmc3680kj_enable(&mmc3680kj_ctx, FLAG_INIT_MAG);
397 if (unlikely(ret)) {
398 return ret;
399 }
400
401 ret = sensor_i2c_read(&mmc3680kj_ctx, MMC3680KJ_REG_DATA, reg_raw,
402 MMC3680KJ_MAG_DATA_SIZE, I2C_OP_RETRIES);
403 if (unlikely(ret)) {
404 return ret;
405 }
406
407 data_raw[0] = (uint16_t)(reg_raw[1] << 8 | reg_raw[0]);
408 data_raw[1] = (uint16_t)(reg_raw[3] << 8 | reg_raw[2]);
409 data_raw[2] = (uint16_t)(reg_raw[5] << 8 | reg_raw[4]);
410 mag_raw[0] = (uint32_t)(data_raw[0]);
411 mag_raw[1] = (uint32_t)(data_raw[1] - data_raw[2] + MMC3680KJ_OFFSET);
412 mag_raw[2] = (uint32_t)(data_raw[1] + data_raw[2] - MMC3680KJ_OFFSET);
413
414 pdata->data[0] = (int32_t)(mag_raw[0] - MMC3680KJ_OFFSET) *
415 g_otp_matrix[0] / MMC3680KJ_SENSITIVITY;
416 pdata->data[1] = (int32_t)(mag_raw[1] - MMC3680KJ_OFFSET) *
417 g_otp_matrix[1] / MMC3680KJ_SENSITIVITY;
418 pdata->data[2] = (int32_t)(mag_raw[2] - MMC3680KJ_OFFSET) *
419 g_otp_matrix[2] / MMC3680KJ_SENSITIVITY;
420 pdata->timestamp = aos_now_ms();
421
422 return (int)size;
423 }
424
drv_mag_memsic_mmc3680kj_write(const void * buf,size_t len)425 static int drv_mag_memsic_mmc3680kj_write(const void *buf, size_t len)
426 {
427 (void)buf;
428 (void)len;
429 return 0;
430 }
431
drv_mag_memsic_mmc3680kj_ioctl(int cmd,unsigned long arg)432 static int drv_mag_memsic_mmc3680kj_ioctl(int cmd, unsigned long arg)
433 {
434 switch (cmd) {
435 case SENSOR_IOCTL_GET_INFO: {
436 /* fill the dev info here */
437 dev_sensor_info_t *info = (dev_sensor_info_t *)arg;
438 info->model = "MMC3680KJ";
439 info->unit = mGauss;
440 } break;
441 default:
442 return -1;
443 }
444
445 LOG("%s %s successfully \n", SENSOR_STR, __func__);
446 return 0;
447 }
448
drv_mag_memsic_mmc3680kj_init(void)449 int drv_mag_memsic_mmc3680kj_init(void)
450 {
451 int ret = 0;
452 sensor_obj_t sensor_mag;
453
454 memset(&sensor_mag, 0, sizeof(sensor_mag));
455
456 if (!g_init_bitwise) {
457 ret = mmc3680kj_check_otp(&mmc3680kj_ctx);
458 if (unlikely(ret)) {
459 return -1;
460 }
461
462 ret = mmc3680kj_validate_id(&mmc3680kj_ctx, MMC3680KJ_PRODUCT_ID);
463 if (unlikely(ret)) {
464 return -1;
465 }
466 }
467
468 if (!(g_init_bitwise & (1 << FLAG_INIT_MAG))) {
469 /* fill the sensor_mag obj parameters here */
470 sensor_mag.tag = TAG_DEV_MAG;
471 sensor_mag.path = dev_mag_path;
472 sensor_mag.io_port = I2C_PORT;
473 sensor_mag.open = drv_mag_memsic_mmc3680kj_open;
474 sensor_mag.close = drv_mag_memsic_mmc3680kj_close;
475 sensor_mag.read = drv_mag_memsic_mmc3680kj_read;
476 sensor_mag.write = drv_mag_memsic_mmc3680kj_write;
477 sensor_mag.ioctl = drv_mag_memsic_mmc3680kj_ioctl;
478 sensor_mag.irq_handle = drv_mag_memsic_mmc3680kj_irq_handle;
479
480 ret = sensor_create_obj(&sensor_mag);
481 if (unlikely(ret)) {
482 return -1;
483 }
484
485 ret = mmc3680kj_get_comp_matrix(&mmc3680kj_ctx);
486 if (unlikely(ret)) {
487 return -1;
488 }
489
490 ret = mmc3680kj_set_pulse_width(&mmc3680kj_ctx);
491 if (unlikely(ret)) {
492 return -1;
493 }
494
495 ret =
496 mmc3680kj_set_output_resolution(&mmc3680kj_ctx, MMC3680KJ_CMD_100HZ);
497 if (unlikely(ret)) {
498 return -1;
499 }
500
501 g_init_bitwise |= 1 << FLAG_INIT_MAG;
502 }
503
504 LOG("%s %s successfully \n", SENSOR_STR, __func__);
505 return 0;
506 }
507
drv_temp_memsic_mmc3680kj_irq_handle(void)508 static void drv_temp_memsic_mmc3680kj_irq_handle(void)
509 {
510 /* no handle so far */
511 }
512
drv_temp_memsic_mmc3680kj_open(void)513 static int drv_temp_memsic_mmc3680kj_open(void)
514 {
515 LOG("%s %s successfully \n", SENSOR_STR, __func__);
516
517 return 0;
518 }
519
drv_temp_memsic_mmc3680kj_close(void)520 static int drv_temp_memsic_mmc3680kj_close(void)
521 {
522 LOG("%s %s successfully \n", SENSOR_STR, __func__);
523
524 return 0;
525 }
526
drv_temp_memsic_mmc3680kj_read(void * buf,size_t len)527 static int drv_temp_memsic_mmc3680kj_read(void *buf, size_t len)
528 {
529 int ret = 0;
530 size_t size;
531 temperature_data_t *pdata = (temperature_data_t *)buf;
532 uint8_t reg_raw = 0;
533
534 if (buf == NULL) {
535 return -1;
536 }
537
538 size = sizeof(temperature_data_t);
539 if (len < size) {
540 return -1;
541 }
542
543 ret = mmc3680kj_enable(&mmc3680kj_ctx, FLAG_INIT_TEMP);
544 if (unlikely(ret)) {
545 return ret;
546 }
547
548 ret = sensor_i2c_read(&mmc3680kj_ctx, MMC3680KJ_REG_TEMP, ®_raw,
549 I2C_DATA_LEN, I2C_OP_RETRIES);
550 if (unlikely(ret)) {
551 return ret;
552 }
553
554 pdata->t = reg_raw * MMC3680KJ_T_SENSITIVITY / 100 + MMC3680KJ_T_ZERO;
555 pdata->timestamp = aos_now_ms();
556
557 return (int)size;
558 }
559
drv_temp_memsic_mmc3680kj_write(const void * buf,size_t len)560 static int drv_temp_memsic_mmc3680kj_write(const void *buf, size_t len)
561 {
562 (void)buf;
563 (void)len;
564 return 0;
565 }
566
drv_temp_memsic_mmc3680kj_ioctl(int cmd,unsigned long arg)567 static int drv_temp_memsic_mmc3680kj_ioctl(int cmd, unsigned long arg)
568 {
569 switch (cmd) {
570 case SENSOR_IOCTL_GET_INFO: {
571 /* fill the dev info here */
572 dev_sensor_info_t *info = (dev_sensor_info_t *)arg;
573 info->model = "MMC3680KJ";
574 info->unit = dCelsius;
575 } break;
576 default:
577 return -1;
578 }
579
580 LOG("%s %s successfully \n", SENSOR_STR, __func__);
581 return 0;
582 }
583
drv_temp_memsic_mmc3680kj_init(void)584 int drv_temp_memsic_mmc3680kj_init(void)
585 {
586 int ret = 0;
587 sensor_obj_t sensor_temp;
588
589 memset(&sensor_temp, 0, sizeof(sensor_temp));
590
591 if (!g_init_bitwise) {
592 ret = mmc3680kj_check_otp(&mmc3680kj_ctx);
593 if (unlikely(ret)) {
594 return -1;
595 }
596
597 ret = mmc3680kj_validate_id(&mmc3680kj_ctx, MMC3680KJ_PRODUCT_ID);
598 if (unlikely(ret)) {
599 return -1;
600 }
601 }
602
603 if (!(g_init_bitwise & (1 << FLAG_INIT_TEMP))) {
604 /* fill the sensor_temp obj parameters here */
605 sensor_temp.tag = TAG_DEV_TEMP;
606 sensor_temp.path = dev_temp_path;
607 sensor_temp.io_port = I2C_PORT;
608 sensor_temp.open = drv_temp_memsic_mmc3680kj_open;
609 sensor_temp.close = drv_temp_memsic_mmc3680kj_close;
610 sensor_temp.read = drv_temp_memsic_mmc3680kj_read;
611 sensor_temp.write = drv_temp_memsic_mmc3680kj_write;
612 sensor_temp.ioctl = drv_temp_memsic_mmc3680kj_ioctl;
613 sensor_temp.irq_handle = drv_temp_memsic_mmc3680kj_irq_handle;
614
615 ret = sensor_create_obj(&sensor_temp);
616 if (unlikely(ret)) {
617 return -1;
618 }
619
620 g_init_bitwise |= 1 << FLAG_INIT_TEMP;
621 }
622
623 LOG("%s %s successfully \n", SENSOR_STR, __func__);
624 return 0;
625 }
626
627 SENSOR_DRV_ADD(drv_mag_memsic_mmc3680kj_init);
628
629