1 /*
2 * Copyright (C) 2015-2017 Alibaba Group Holding Limited
3 *
4 *
5 */
6 
7 #include "aos/kernel.h"
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include "sensor_drv_api.h"
12 #include "sensor_hal.h"
13 
14 #define BMA455_I2C_ADDR_LOW                     (0x18)
15 #define BMA455_I2C_ADDR_HIGH                    (0x19)
16 #define BMA455_I2C_ADDR_TRANS(n)                ((n)<<1)
17 #define BMA455_I2C_ADDR                         BMA455_I2C_ADDR_TRANS(BMA455_I2C_ADDR_LOW)
18 
19 #define BMA455_CHIP_ID_ADDR                     UINT8_C(0X00)
20 #define BMA455_CHIP_ID_VALUE                    (0x15)
21 
22 #define BMA455_POWER_CONF_ADDR                  UINT8_C(0x7C)
23 #define BMA455_POWER_CTRL_ADDR                  UINT8_C(0x7D)
24 
25 #define BMA455_ACCEL_CONFIG_ADDR                UINT8_C(0X40)
26 #define BMA455_ACCEL_CONFIG1_ADDR               UINT8_C(0X41)
27 
28 #define BMA455_DEFAULT_ODR_100HZ                (100)
29 #define BMA455_CMD_ADDR                         UINT8_C(0X7E)
30 
31 #define BMA455_OUTPUT_DATA_RATE_0_78HZ          UINT8_C(0x01)
32 #define BMA455_OUTPUT_DATA_RATE_1_56HZ          UINT8_C(0x02)
33 #define BMA455_OUTPUT_DATA_RATE_3_12HZ          UINT8_C(0x03)
34 #define BMA455_OUTPUT_DATA_RATE_6_25HZ          UINT8_C(0x04)
35 #define BMA455_OUTPUT_DATA_RATE_12_5HZ          UINT8_C(0x05)
36 #define BMA455_OUTPUT_DATA_RATE_25HZ            UINT8_C(0x06)
37 #define BMA455_OUTPUT_DATA_RATE_50HZ            UINT8_C(0x07)
38 #define BMA455_OUTPUT_DATA_RATE_100HZ           UINT8_C(0x08)
39 #define BMA455_OUTPUT_DATA_RATE_200HZ           UINT8_C(0x09)
40 #define BMA455_OUTPUT_DATA_RATE_400HZ           UINT8_C(0x0A)
41 #define BMA455_OUTPUT_DATA_RATE_800HZ           UINT8_C(0x0B)
42 #define BMA455_OUTPUT_DATA_RATE_1600HZ          UINT8_C(0x0C)
43 
44 #define BMA455_ACCEL_OSR4_AVG1                  UINT8_C(0)
45 #define BMA455_ACCEL_OSR2_AVG2                  UINT8_C(1)
46 #define BMA455_ACCEL_NORMAL_AVG4                UINT8_C(2)
47 #define BMA455_ACCEL_CIC_AVG8                   UINT8_C(3)
48 #define BMA455_ACCEL_RES_AVG16                  UINT8_C(4)
49 #define BMA455_ACCEL_RES_AVG32                  UINT8_C(5)
50 #define BMA455_ACCEL_RES_AVG64                  UINT8_C(6)
51 #define BMA455_ACCEL_RES_AVG128                 UINT8_C(7)
52 
53 #define BMA455_ACCEL_RANGE_2G                   UINT8_C(0)
54 #define BMA455_ACCEL_RANGE_4G                   UINT8_C(1)
55 #define BMA455_ACCEL_RANGE_8G                   UINT8_C(2)
56 #define BMA455_ACCEL_RANGE_16G                  UINT8_C(3)
57 
58 #define BMA455_DATA_0_ADDR                      UINT8_C(0X0A)
59 #define BMA455_DATA_8_ADDR                      UINT8_C(0X12)
60 #define BMA455_ACCEL_DATA_LENGTH                UINT8_C(6)
61 
62 #define BMA455_ENABLE                           UINT8_C(0x01)
63 #define BMA455_DISABLE                          UINT8_C(0x00)
64 
65 #define BMA455_ADVANCE_POWER_SAVE_MSK           UINT8_C(0x01)
66 
67 #define BMA455_ACCEL_ENABLE_POS                 UINT8_C(2)
68 #define BMA455_ACCEL_ENABLE_MSK                 UINT8_C(0x04)
69 
70 #define BMA455_ACCEL_PERF_POS                   UINT8_C(7)
71 
72 #define BMA455_ACCEL_ODR_POS                    UINT8_C(0)
73 #define BMA455_ACCEL_ODR_MSK                    UINT8_C(0x0F)
74 
75 #define BMA455_ACCEL_RANGE_POS                  UINT8_C(0)
76 #define BMA455_ACCEL_RANGE_MSK                  UINT8_C(0x03)
77 
78 #define BMA455_ENABLE_SOFT_RESET_VALUE          UINT8_C(0XB6)
79 
80 #define BMA455_GET_BITSLICE(regvar, bitname)\
81   ((regvar & bitname##_MSK) >> bitname##_POS)
82 #define BMA455_SET_BITSLICE(regvar, bitname, val)\
83   ((regvar & ~bitname##_MSK) | \
84   ((val<<bitname##_POS)&bitname##_MSK))
85 #define BMA455_SET_BITS_POS_0(reg_data, bitname, data) \
86     ((reg_data & ~(bitname##_MSK)) | \
87     (data & bitname##_MSK))
88 
89 #define BMA455_GET_BITS_POS_0(reg_data, bitname) (reg_data & (bitname##_MSK))
90 
91 
92 static uint32_t bma455_factor[4] = { 16384, 8192, 4096, 2048 };
93 static uint32_t current_factor = 0;
94 static uint32_t set_range_failed = 0;
95 
96 i2c_dev_t bma455_ctx = {
97     .port = 3,
98     .config.dev_addr = BMA455_I2C_ADDR,
99 };
100 
drv_acc_bosch_bma455_soft_reset(i2c_dev_t * drv)101 int drv_acc_bosch_bma455_soft_reset(i2c_dev_t* drv)
102 {
103     int ret = 0;
104     uint8_t value = BMA455_ENABLE_SOFT_RESET_VALUE;
105     ret = sensor_i2c_write(drv, BMA455_CMD_ADDR, &value,
106                            I2C_DATA_LEN, I2C_OP_RETRIES);
107     aos_msleep(2);
108     if(unlikely(ret)) {
109         return -1;
110     }
111     return 0;
112 }
113 
drv_acc_bosch_bma455_validate_id(i2c_dev_t * drv)114 int drv_acc_bosch_bma455_validate_id(i2c_dev_t* drv)
115 {
116     uint8_t value = 0x00;
117     int ret = 0;
118 
119     if(drv == NULL) {
120         return -1;
121     }
122 
123     ret = sensor_i2c_read(drv, BMA455_CHIP_ID_ADDR, &value, I2C_DATA_LEN,
124                           I2C_OP_RETRIES);
125     if(unlikely(ret)) {
126         LOG("%s %s  sensor_i2c_read \n", SENSOR_STR, __func__);
127         return ret;
128     }
129 
130     if(BMA455_CHIP_ID_VALUE != value) {
131         LOG("%s %s  value=%x \n", SENSOR_STR, __func__, value);
132         return -1;
133     }
134 
135     return 0;
136 }
137 
drv_acc_bosch_bma455_set_power_mode(i2c_dev_t * drv,dev_power_mode_e mode)138 int drv_acc_bosch_bma455_set_power_mode(i2c_dev_t* drv,
139                                                dev_power_mode_e mode)
140 {
141 
142     uint8_t value, value1 = 0x00;
143     int ret = 0;
144     switch(mode) {
145         case DEV_POWER_ON: {
146             ret = sensor_i2c_read(drv, BMA455_ACCEL_CONFIG_ADDR, &value, I2C_DATA_LEN,
147                                   I2C_OP_RETRIES);
148             if(unlikely(ret)) {
149                 return ret;
150             }
151             value |= (BMA455_ENABLE << BMA455_ACCEL_PERF_POS);
152             ret = sensor_i2c_write(drv, BMA455_ACCEL_CONFIG_ADDR, &value, I2C_DATA_LEN,
153                                    I2C_OP_RETRIES);
154             aos_msleep(2);
155             if(unlikely(ret)) {
156                 return ret;
157             }
158 
159             ret = sensor_i2c_read(drv, BMA455_POWER_CTRL_ADDR, &value1, I2C_DATA_LEN,
160                                   I2C_OP_RETRIES);
161             if(unlikely(ret)) {
162                 return ret;
163             }
164             value1 = BMA455_SET_BITSLICE(value1, BMA455_ACCEL_ENABLE, BMA455_ENABLE);
165             ret = sensor_i2c_write(drv, BMA455_POWER_CTRL_ADDR, &value1, I2C_DATA_LEN,
166                                    I2C_OP_RETRIES);
167             aos_msleep(2);
168             if(unlikely(ret)) {
169                 return ret;
170             }
171         }
172         break;
173         case DEV_POWER_OFF:
174         case DEV_SLEEP:
175         case DEV_SUSPEND: {
176 
177             ret = sensor_i2c_read(drv, BMA455_POWER_CTRL_ADDR, &value, I2C_DATA_LEN,
178                                   I2C_OP_RETRIES);
179             if(unlikely(ret)) {
180                 return ret;
181             }
182             value = BMA455_SET_BITSLICE(value, BMA455_ACCEL_ENABLE, BMA455_DISABLE);
183             ret = sensor_i2c_write(drv, BMA455_POWER_CTRL_ADDR, &value, I2C_DATA_LEN,
184                                    I2C_OP_RETRIES);
185             aos_msleep(2);
186             if(unlikely(ret)) {
187                 return ret;
188             }
189 
190             ret = sensor_i2c_read(drv, BMA455_POWER_CONF_ADDR, &value1, I2C_DATA_LEN,
191                                   I2C_OP_RETRIES);
192             if(unlikely(ret)) {
193                 return ret;
194             }
195             value1 = BMA455_SET_BITS_POS_0(value1, BMA455_ADVANCE_POWER_SAVE, BMA455_ENABLE);
196             ret = sensor_i2c_write(drv, BMA455_POWER_CONF_ADDR, &value1, I2C_DATA_LEN,
197                                    I2C_OP_RETRIES);
198             aos_msleep(2);
199             if(unlikely(ret)) {
200                 return ret;
201             }
202         }
203         break;
204 
205         default:
206             break;
207     }
208     return 0;
209 }
210 
drv_acc_bosch_bma455_set_odr(i2c_dev_t * drv,uint32_t hz)211 int drv_acc_bosch_bma455_set_odr(i2c_dev_t* drv, uint32_t hz)
212 {
213     int ret = 0;
214     uint8_t value = 0x00;
215     uint8_t odr = 0x00;
216 
217     ret = sensor_i2c_read(drv, BMA455_ACCEL_CONFIG_ADDR, &value, I2C_DATA_LEN,
218                           I2C_OP_RETRIES);
219     if(unlikely(ret)) {
220         return ret;
221     }
222 
223     if(hz >= 800) {
224         odr = BMA455_OUTPUT_DATA_RATE_1600HZ;
225     } else if(hz >= 400) {
226         odr = BMA455_OUTPUT_DATA_RATE_800HZ;
227     } else if(hz >= 200) {
228         odr = BMA455_OUTPUT_DATA_RATE_400HZ;
229     } else if(hz >= 100) {
230         odr = BMA455_OUTPUT_DATA_RATE_200HZ;
231     } else if(hz >= 50) {
232         odr = BMA455_OUTPUT_DATA_RATE_100HZ;
233     } else if(hz >= 25) {
234         odr = BMA455_OUTPUT_DATA_RATE_50HZ;
235     } else if(hz >= 12) {
236         odr = BMA455_OUTPUT_DATA_RATE_25HZ;
237     } else if(hz >= 6) {
238         odr = BMA455_OUTPUT_DATA_RATE_12_5HZ;
239     } else if(hz >= 3) {
240         odr = BMA455_OUTPUT_DATA_RATE_6_25HZ;
241     } else {
242         odr = BMA455_OUTPUT_DATA_RATE_3_12HZ;
243     }
244 
245     value = BMA455_SET_BITSLICE(value, BMA455_ACCEL_ODR, odr);
246     ret = sensor_i2c_write(drv, BMA455_ACCEL_CONFIG_ADDR, &value, I2C_DATA_LEN,
247                            I2C_OP_RETRIES);
248     aos_msleep(2);
249     if(unlikely(ret)) {
250         return ret;
251     }
252     return 0;
253 }
254 
drv_acc_bosch_bma455_set_range(i2c_dev_t * drv,uint32_t range)255 int drv_acc_bosch_bma455_set_range(i2c_dev_t* drv, uint32_t range)
256 {
257     int ret = 0;
258     uint8_t value = 0x00;
259     uint8_t acc_range = 0x00;
260 
261     ret = sensor_i2c_read(drv, BMA455_ACCEL_CONFIG1_ADDR, &value, I2C_DATA_LEN,
262                           I2C_OP_RETRIES);
263     if(unlikely(ret)) {
264         set_range_failed = 1;
265         return ret;
266     }
267 
268     switch(range) {
269         case ACC_RANGE_2G: {
270             acc_range = BMA455_ACCEL_RANGE_2G;
271         }
272         break;
273 
274         case ACC_RANGE_4G: {
275             acc_range = BMA455_ACCEL_RANGE_4G;
276         }
277         break;
278 
279         case ACC_RANGE_8G: {
280             acc_range = BMA455_ACCEL_RANGE_8G;
281         }
282         break;
283 
284         case ACC_RANGE_16G: {
285             acc_range = BMA455_ACCEL_RANGE_16G;
286         }
287         break;
288 
289         default:
290             break;
291     }
292 
293     value = BMA455_SET_BITSLICE(value, BMA455_ACCEL_RANGE, acc_range);
294     ret = sensor_i2c_write(drv, BMA455_ACCEL_CONFIG1_ADDR, &value, I2C_DATA_LEN,
295                            I2C_OP_RETRIES);
296     aos_msleep(2);
297     if(unlikely(ret)) {
298         set_range_failed = 2;
299         return ret;
300     }
301 
302     if((range >= ACC_RANGE_2G)&&(range <= ACC_RANGE_16G)) {
303         current_factor = bma455_factor[range];
304     }
305 
306     set_range_failed = 3;
307     return 0;
308 }
309 
drv_acc_bosch_bma455_irq_handle(void)310 void drv_acc_bosch_bma455_irq_handle(void)
311 {
312     /* no handle so far */
313 }
314 
drv_acc_bosch_bma455_open(void)315 int drv_acc_bosch_bma455_open(void)
316 {
317     int ret = 0;
318     ret  = drv_acc_bosch_bma455_set_power_mode(&bma455_ctx, DEV_POWER_ON);
319     if(unlikely(ret)) {
320         return -1;
321     }
322     return 0;
323 
324 }
325 
drv_acc_bosch_bma455_close(void)326 int drv_acc_bosch_bma455_close(void)
327 {
328     int ret = 0;
329     ret  = drv_acc_bosch_bma455_set_power_mode(&bma455_ctx, DEV_POWER_OFF);
330     if(unlikely(ret)) {
331         return -1;
332     }
333     return 0;
334 }
335 
drv_acc_bosch_bma455_read(void * buf,size_t len)336 int drv_acc_bosch_bma455_read(void *buf, size_t len)
337 {
338     int ret = 0;
339     size_t size;
340     uint8_t reg[6];
341     uint8_t range = 0;
342     accel_data_t *accel = (accel_data_t *)buf;
343 
344     if(buf == NULL) {
345         return -1;
346     }
347 
348     size = sizeof(accel_data_t);
349     if(len < size) {
350         return -1;
351     }
352     ret  = sensor_i2c_read(&bma455_ctx, 0x41,  &range, I2C_REG_LEN, I2C_OP_RETRIES);
353     ret  = sensor_i2c_read(&bma455_ctx, BMA455_DATA_8_ADDR,  &reg[0], I2C_REG_LEN,
354                            I2C_OP_RETRIES);
355     ret |= sensor_i2c_read(&bma455_ctx, BMA455_DATA_8_ADDR+1,  &reg[1], I2C_REG_LEN,
356                            I2C_OP_RETRIES);
357     ret |= sensor_i2c_read(&bma455_ctx, BMA455_DATA_8_ADDR+2,  &reg[2], I2C_REG_LEN,
358                            I2C_OP_RETRIES);
359     ret |= sensor_i2c_read(&bma455_ctx, BMA455_DATA_8_ADDR+3,  &reg[3], I2C_REG_LEN,
360                            I2C_OP_RETRIES);
361     ret |= sensor_i2c_read(&bma455_ctx, BMA455_DATA_8_ADDR+4,  &reg[4], I2C_REG_LEN,
362                            I2C_OP_RETRIES);
363     ret |= sensor_i2c_read(&bma455_ctx, BMA455_DATA_8_ADDR+5,  &reg[5], I2C_REG_LEN,
364                            I2C_OP_RETRIES);
365 
366     if(unlikely(ret)) {
367         return -1;
368     }
369 
370     accel->data[DATA_AXIS_X] = ((int16_t)((reg[1] << 8) | reg[0]));
371     accel->data[DATA_AXIS_Y] = ((int16_t)((reg[3] << 8) | reg[2]));
372     accel->data[DATA_AXIS_Z] = ((int16_t)((reg[5] << 8) | reg[4]));
373     if(current_factor != 0) {
374         accel->data[DATA_AXIS_X] = accel->data[DATA_AXIS_X] *
375                                    ACCELEROMETER_UNIT_FACTOR / (int32_t)current_factor;
376         accel->data[DATA_AXIS_Y] = accel->data[DATA_AXIS_Y] *
377                                    ACCELEROMETER_UNIT_FACTOR / (int32_t)current_factor;
378         accel->data[DATA_AXIS_Z] = accel->data[DATA_AXIS_Z] *
379                                    ACCELEROMETER_UNIT_FACTOR / (int32_t)current_factor;
380     }
381     accel->timestamp = aos_now_ms();
382 
383     return (int)size;
384 }
385 
drv_acc_bosch_bma455_ioctl(int cmd,unsigned long arg)386 static int drv_acc_bosch_bma455_ioctl(int cmd, unsigned long arg)
387 {
388     int ret = 0;
389 
390     switch(cmd) {
391         case SENSOR_IOCTL_ODR_SET: {
392             ret = drv_acc_bosch_bma455_set_odr(&bma455_ctx, arg);
393             if(unlikely(ret)) {
394                 return -1;
395             }
396         }
397         break;
398         case SENSOR_IOCTL_RANGE_SET: {
399             ret = drv_acc_bosch_bma455_set_range(&bma455_ctx, arg);
400             if(unlikely(ret)) {
401                 return -1;
402             }
403         }
404         break;
405         case SENSOR_IOCTL_SET_POWER: {
406             ret = drv_acc_bosch_bma455_set_power_mode(&bma455_ctx, arg);
407             if(unlikely(ret)) {
408                 return -1;
409             }
410         }
411         break;
412         case SENSOR_IOCTL_GET_INFO: {
413             dev_sensor_info_t *info = (dev_sensor_info_t *)arg;
414             info->model = "BMA455";
415             info->range_max = 16;
416             info->range_min = 2;
417             info->unit = mg;
418         }
419         break;
420 
421         default:
422             break;
423     }
424 
425     return 0;
426 }
427 
drv_acc_bosch_bma455_init(void)428 int drv_acc_bosch_bma455_init(void) {
429     int ret = 0;
430     sensor_obj_t sensor;
431     memset(&sensor, 0, sizeof(sensor));
432 
433     /* fill the sensor obj parameters here */
434     sensor.io_port    = I2C_PORT;
435     sensor.tag        = TAG_DEV_ACC;
436     sensor.path       = dev_acc_path;
437     sensor.open       = drv_acc_bosch_bma455_open;
438     sensor.close      = drv_acc_bosch_bma455_close;
439     sensor.read       = drv_acc_bosch_bma455_read;
440     sensor.write      = NULL;
441     sensor.ioctl      = drv_acc_bosch_bma455_ioctl;
442     sensor.irq_handle = drv_acc_bosch_bma455_irq_handle;
443     ret = sensor_create_obj(&sensor);
444     if(unlikely(ret)) {
445         return -1;
446     }
447 
448     ret = drv_acc_bosch_bma455_validate_id(&bma455_ctx);
449     if(unlikely(ret)) {
450         return -1;
451     }
452 
453     ret = drv_acc_bosch_bma455_soft_reset(&bma455_ctx);
454     if(unlikely(ret)) {
455         return -1;
456     }
457 
458     ret = drv_acc_bosch_bma455_set_range(&bma455_ctx, ACC_RANGE_8G);
459     if(unlikely(ret)) {
460         return -1;
461     }
462 
463     /* set odr is 100hz, and will update */
464     ret = drv_acc_bosch_bma455_set_odr(&bma455_ctx, BMA455_DEFAULT_ODR_100HZ);
465     if(unlikely(ret)) {
466         return -1;
467     }
468     ret = drv_acc_bosch_bma455_set_power_mode(&bma455_ctx, DEV_SLEEP);
469     if(unlikely(ret)) {
470         return -1;
471     }
472 
473     /* update the phy sensor info to sensor hal */
474     LOG("%s %s successfully \n", SENSOR_STR, __func__);
475     return 0;
476 }
477 
478 SENSOR_DRV_ADD(drv_acc_bosch_bma455_init);
479 
480