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 #include "aos/kernel.h"
11 #include "sensor_drv_api.h"
12 #include "sensor_hal.h"
13 
14 
15 #define AIS328DQ_I2C_ADDR1                 	(0x18)
16 #define AIS328DQ_I2C_ADDR2                 	(0x19)
17 #define AIS328DQ_I2C_ADDR_TRANS(n)         	((n)<<1)
18 #define AIS328DQ_I2C_ADDR                  	AIS328DQ_I2C_ADDR_TRANS(AIS328DQ_I2C_ADDR1)
19 
20 #define AIS328DQ_ACC_WHO_AM_I              	0x0F
21 #define AIS328DQ_ACC_CTRL_REG1             	0x20
22 #define AIS328DQ_ACC_CTRL_REG2             	0x21
23 #define AIS328DQ_ACC_CTRL_REG3            	0x22
24 #define AIS328DQ_ACC_CTRL_REG4             	0x23
25 #define AIS328DQ_ACC_CTRL_REG5             	0x24
26 #define AIS328DQ_ACC_STATUS_REG           	0x27
27 #define AIS328DQ_ACC_OUT_X_L              	0x28
28 #define AIS328DQ_ACC_OUT_X_H              	0x29
29 #define AIS328DQ_ACC_OUT_Y_L              	0x2A
30 #define AIS328DQ_ACC_OUT_Y_H              	0x2B
31 #define AIS328DQ_ACC_OUT_Z_L              	0x2C
32 #define AIS328DQ_ACC_OUT_Z_H              	0x2D
33 
34 #define AIS328DQ_ACC_RANGE_2G              	(0x0)
35 #define AIS328DQ_ACC_RANGE_4G              	(0x1)
36 #define AIS328DQ_ACC_RANGE_8G               (0x3)
37 #define AIS328DQ_ACC_RANGE_MSK              (0x30)
38 #define AIS328DQ_ACC_RANGE_POS              (4)
39 
40 #define AIS328DQ_ACC_SENSITIVITY_2G        	(980)
41 #define AIS328DQ_ACC_SENSITIVITY_4G        	(1950)
42 #define AIS328DQ_ACC_SENSITIVITY_8G         (3910)
43 
44 #define AIS328DQ_ACC_CHIP_ID_VALUE			(0x32)
45 
46 #define AIS328DQ_SHIFT_EIGHT_BITS           (8)
47 #define AIS328DQ_SHIFT_FOUR_BITS            (4)
48 
49 #define AIS328DQ_16_BIT_SHIFT               (0xFF)
50 
51 #define AIS328DQ_ACC_ODR_POWER_DOWN			(0x00)
52 #define AIS328DQ_ACC_ODR_0_5_HZ             (0x40)
53 #define AIS328DQ_ACC_ODR_1_HZ               (0x60)
54 #define AIS328DQ_ACC_ODR_2_HZ               (0x80)
55 #define AIS328DQ_ACC_ODR_5_HZ               (0xA0)
56 #define AIS328DQ_ACC_ODR_10_HZ              (0xC0)
57 #define AIS328DQ_ACC_ODR_50_HZ              (0x20)
58 #define AIS328DQ_ACC_ODR_100_HZ             (0x28)
59 #define AIS328DQ_ACC_ODR_400_HZ             (0x30)
60 #define AIS328DQ_ACC_ODR_1000_HZ            (0x38)
61 #define AIS328DQ_ACC_ODR_MSK                (0xF8)
62 #define AIS328DQ_ACC_ODR_POS                (3)
63 
64 #define AIS328DQ_ACC_DEFAULT_ODR_100HZ      (100)
65 
66 #define AIS328DQ_BDU_ENABLE					(0x80)
67 
68 #define AIS328DQ_ACC_STATUS_ZYXDA			(0x08)
69 
70 #define AIS328DQ_GET_BITSLICE(regvar, bitname)\
71 ((regvar & bitname##_MSK) >> bitname##_POS)
72 
73 #define AIS328DQ_SET_BITSLICE(regvar, bitname, val)\
74 	((regvar & ~bitname##_MSK) | ((val<<bitname##_POS)&bitname##_MSK))
75 
76 
77 static int32_t ais328dq_acc_factor[ACC_RANGE_MAX] = { AIS328DQ_ACC_SENSITIVITY_2G, AIS328DQ_ACC_SENSITIVITY_4G,
78                                      AIS328DQ_ACC_SENSITIVITY_8G, 0 };
79 static int32_t cur_acc_factor = 0;
80 
81 
82 i2c_dev_t ais328dq_ctx = {
83     .port = 3,
84     .config.address_width = 8,
85     .config.freq = 400000,
86     .config.dev_addr = AIS328DQ_I2C_ADDR,
87 };
88 
drv_acc_st_ais328dq_validate_id(i2c_dev_t * drv,uint8_t id_value)89 static int drv_acc_st_ais328dq_validate_id(i2c_dev_t* drv, uint8_t id_value)
90 {
91     uint8_t value = 0x00;
92     int ret = 0;
93 
94     if(drv == NULL){
95         return -1;
96     }
97 
98     ret = sensor_i2c_read(drv, AIS328DQ_ACC_WHO_AM_I, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
99     if(unlikely(ret)){
100         return ret;
101     }
102 
103     if (id_value != value){
104         return -1;
105     }
106 
107     return 0;
108 }
109 
drv_acc_st_ais328dq_set_power_mode(i2c_dev_t * drv,dev_power_mode_e mode)110 static int drv_acc_st_ais328dq_set_power_mode(i2c_dev_t* drv, dev_power_mode_e mode)
111 {
112     uint8_t value = 0x00;
113     int ret = 0;
114 
115     ret = sensor_i2c_read(drv, AIS328DQ_ACC_CTRL_REG1, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
116     if(unlikely(ret)){
117         return ret;
118     }
119 
120     switch(mode){
121         case DEV_POWER_ON:{
122             value = AIS328DQ_SET_BITSLICE(value,AIS328DQ_ACC_ODR,AIS328DQ_ACC_ODR_10_HZ);
123             ret = sensor_i2c_write(drv, AIS328DQ_ACC_CTRL_REG1, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
124             if(unlikely(ret)){
125                 return ret;
126             }
127         }break;
128 
129         case DEV_POWER_OFF:{
130             value = AIS328DQ_SET_BITSLICE(value,AIS328DQ_ACC_ODR,AIS328DQ_ACC_ODR_POWER_DOWN);
131             ret = sensor_i2c_write(drv, AIS328DQ_ACC_CTRL_REG1, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
132             if(unlikely(ret)){
133                 return ret;
134             }
135         }break;
136 
137         case DEV_SLEEP:{
138             value = AIS328DQ_SET_BITSLICE(value,AIS328DQ_ACC_ODR,AIS328DQ_ACC_ODR_10_HZ);
139             ret = sensor_i2c_write(drv, AIS328DQ_ACC_CTRL_REG1, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
140             if(unlikely(ret)){
141                 return ret;
142             }
143 
144         }break;
145 
146        default:break;
147     }
148     return 0;
149 }
150 
drv_acc_st_ais328dq_hz2odr(uint32_t hz)151 static uint8_t drv_acc_st_ais328dq_hz2odr(uint32_t hz)
152 {
153     if(hz > 400)
154         return AIS328DQ_ACC_ODR_1000_HZ;
155     else if(hz > 100)
156         return AIS328DQ_ACC_ODR_400_HZ;
157     else if(hz > 50)
158         return AIS328DQ_ACC_ODR_100_HZ;
159     else if(hz > 10)
160         return AIS328DQ_ACC_ODR_50_HZ;
161     else if(hz > 5)
162         return AIS328DQ_ACC_ODR_10_HZ;
163     else if(hz > 2)
164         return AIS328DQ_ACC_ODR_5_HZ;
165     else if(hz > 1)
166         return AIS328DQ_ACC_ODR_2_HZ;
167 	else
168 		return AIS328DQ_ACC_ODR_1_HZ;
169 
170 }
171 
drv_acc_st_ais328dq_set_odr(i2c_dev_t * drv,uint32_t hz)172 static int drv_acc_st_ais328dq_set_odr(i2c_dev_t* drv, uint32_t hz)
173 {
174     int ret = 0;
175     uint8_t value = 0x00;
176     uint8_t odr = drv_acc_st_ais328dq_hz2odr(hz);
177 
178     ret = sensor_i2c_read(drv, AIS328DQ_ACC_CTRL_REG1, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
179     if(unlikely(ret)){
180         return ret;
181     }
182 
183     value = AIS328DQ_SET_BITSLICE(value,AIS328DQ_ACC_ODR,odr);
184 
185     ret = sensor_i2c_write(drv, AIS328DQ_ACC_CTRL_REG1, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
186     if(unlikely(ret)){
187         return ret;
188     }
189     return 0;
190 }
191 
drv_acc_st_ais328dq_set_range(i2c_dev_t * drv,uint32_t range)192 static int drv_acc_st_ais328dq_set_range(i2c_dev_t* drv, uint32_t range)
193 {
194 
195     int ret = 0;
196     uint8_t value = 0x00;
197     uint8_t tmp = 0;
198 
199     ret = sensor_i2c_read(drv, AIS328DQ_ACC_CTRL_REG4, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
200     if(unlikely(ret)){
201         return ret;
202     }
203 
204     switch (range){
205         case ACC_RANGE_2G:{
206             tmp = AIS328DQ_ACC_RANGE_2G;
207         }break;
208 
209         case ACC_RANGE_4G:{
210             tmp = AIS328DQ_ACC_RANGE_4G;
211         }break;
212 
213         case ACC_RANGE_8G:{
214             tmp = AIS328DQ_ACC_RANGE_8G;
215         }break;
216 
217         default:break;
218     }
219 
220     value  = AIS328DQ_SET_BITSLICE(value,AIS328DQ_ACC_RANGE,tmp);
221 
222     ret = sensor_i2c_write(drv, AIS328DQ_ACC_CTRL_REG4, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
223     if(unlikely(ret)){
224         return ret;
225     }
226 
227     if((range >= ACC_RANGE_2G)&&(range <= ACC_RANGE_8G)){
228         cur_acc_factor = ais328dq_acc_factor[range];
229     }
230 
231     return 0;
232 }
233 
234 
drv_acc_st_ais328dq_set_bdu(i2c_dev_t * drv)235 static int drv_acc_st_ais328dq_set_bdu(i2c_dev_t* drv)
236 {
237     uint8_t value = 0x00;
238     int ret = 0;
239 
240     ret = sensor_i2c_read(drv, AIS328DQ_ACC_CTRL_REG4, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
241     if(unlikely(ret)){
242         return ret;
243     }
244     value |= AIS328DQ_BDU_ENABLE;
245 
246     ret = sensor_i2c_write(drv, AIS328DQ_ACC_CTRL_REG4, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
247     if(unlikely(ret)){
248         return ret;
249     }
250     return 0;
251 }
252 
drv_acc_st_ais328dq_irq_handle(void)253 static void drv_acc_st_ais328dq_irq_handle(void)
254 {
255     /* no handle so far */
256 }
257 
drv_acc_st_ais328dq_open(void)258 static int drv_acc_st_ais328dq_open(void)
259 {
260     int ret = 0;
261     ret  = drv_acc_st_ais328dq_set_power_mode(&ais328dq_ctx, DEV_POWER_ON);
262     if(unlikely(ret)){
263         return -1;
264     }
265 
266     ret = drv_acc_st_ais328dq_set_range(&ais328dq_ctx, ACC_RANGE_8G);
267     if(unlikely(ret)){
268         return -1;
269     }
270 
271     ret = drv_acc_st_ais328dq_set_odr(&ais328dq_ctx, AIS328DQ_ACC_DEFAULT_ODR_100HZ);
272     if(unlikely(ret)){
273         return -1;
274     }
275 
276     return 0;
277 
278 }
279 
drv_acc_st_ais328dq_close(void)280 static int drv_acc_st_ais328dq_close(void)
281 {
282     int ret = 0;
283     ret  = drv_acc_st_ais328dq_set_power_mode(&ais328dq_ctx, DEV_POWER_OFF);
284     if(unlikely(ret)){
285         return -1;
286     }
287     return 0;
288 }
289 
drv_acc_st_ais328dq_read(void * buf,size_t len)290 static int drv_acc_st_ais328dq_read(void *buf, size_t len)
291 {
292 
293     int ret = 0;
294     size_t size;
295     uint8_t reg[6];
296     accel_data_t *accel = (accel_data_t *)buf;
297     if(buf == NULL){
298         return -1;
299     }
300 
301     size = sizeof(accel_data_t);
302     if(len < size){
303         return -1;
304     }
305 
306 	ret = sensor_i2c_read(&ais328dq_ctx, (AIS328DQ_ACC_OUT_X_L | 0x80), reg, 6, I2C_OP_RETRIES);
307 
308 	if(unlikely(ret)){
309         return -1;
310     }
311     accel->data[DATA_AXIS_X] = (int16_t)((((int16_t)((int8_t)reg[1]))<< AIS328DQ_SHIFT_EIGHT_BITS)|(reg[0]));
312 	accel->data[DATA_AXIS_X] = accel->data[DATA_AXIS_X] >> AIS328DQ_SHIFT_FOUR_BITS;
313     accel->data[DATA_AXIS_Y] = (int16_t)((((int16_t)((int8_t)reg[3]))<< AIS328DQ_SHIFT_EIGHT_BITS)|(reg[2]));
314 	accel->data[DATA_AXIS_Y] = accel->data[DATA_AXIS_Y] >> AIS328DQ_SHIFT_FOUR_BITS;
315 	accel->data[DATA_AXIS_Z] = (int16_t)((((int16_t)((int8_t)reg[5]))<< AIS328DQ_SHIFT_EIGHT_BITS)|(reg[4]));
316 	accel->data[DATA_AXIS_Z] = accel->data[DATA_AXIS_Z] >> AIS328DQ_SHIFT_FOUR_BITS;
317 
318     if(cur_acc_factor != 0){
319         accel->data[DATA_AXIS_X] = accel->data[DATA_AXIS_X] * cur_acc_factor / 1000;
320         accel->data[DATA_AXIS_Y] = accel->data[DATA_AXIS_Y] * cur_acc_factor / 1000;
321         accel->data[DATA_AXIS_Z] = accel->data[DATA_AXIS_Z] * cur_acc_factor / 1000;
322     }
323 
324     accel->timestamp = aos_now_ms();
325 
326     return (int)size;
327 }
328 
drv_acc_st_ais328dq_ioctl(int cmd,unsigned long arg)329 static int drv_acc_st_ais328dq_ioctl(int cmd, unsigned long arg)
330 {
331     int ret = 0;
332     dev_sensor_info_t *info = (dev_sensor_info_t *)arg;
333 
334     switch(cmd){
335         case SENSOR_IOCTL_ODR_SET:{
336             ret = drv_acc_st_ais328dq_set_odr(&ais328dq_ctx, arg);
337             if(unlikely(ret)){
338                 return -1;
339             }
340         }break;
341         case SENSOR_IOCTL_RANGE_SET:{
342             ret = drv_acc_st_ais328dq_set_range(&ais328dq_ctx, arg);
343             if(unlikely(ret)){
344                 return -1;
345             }
346         }break;
347         case SENSOR_IOCTL_SET_POWER:{
348             ret = drv_acc_st_ais328dq_set_power_mode(&ais328dq_ctx, arg);
349             if(unlikely(ret)){
350                 return -1;
351             }
352         }break;
353         case SENSOR_IOCTL_GET_INFO:{
354             /* fill the dev info here */
355             info->model = "AIS328DQ";
356             info->range_max = 8;
357             info->range_min = 2;
358             info->unit = mg;
359 
360         }break;
361        default:break;
362     }
363 
364     return 0;
365 }
366 
drv_acc_st_ais328dq_init(void)367 int drv_acc_st_ais328dq_init(void){
368     int ret = 0;
369     sensor_obj_t sensor;
370     memset(&sensor, 0, sizeof(sensor));
371 
372     /* fill the sensor obj parameters here */
373     sensor.io_port    = I2C_PORT;
374     sensor.tag        = TAG_DEV_ACC;
375     sensor.path       = dev_acc_path;
376     sensor.open       = drv_acc_st_ais328dq_open;
377     sensor.close      = drv_acc_st_ais328dq_close;
378     sensor.read       = drv_acc_st_ais328dq_read;
379     sensor.write      = NULL;
380     sensor.ioctl      = drv_acc_st_ais328dq_ioctl;
381     sensor.irq_handle = drv_acc_st_ais328dq_irq_handle;
382 
383     ret = sensor_create_obj(&sensor);
384     if(unlikely(ret)){
385         return -1;
386     }
387 
388     ret = drv_acc_st_ais328dq_validate_id(&ais328dq_ctx, AIS328DQ_ACC_CHIP_ID_VALUE);
389     if(unlikely(ret)){
390         return -1;
391     }
392 
393     ret = drv_acc_st_ais328dq_set_range(&ais328dq_ctx, ACC_RANGE_8G);
394     if(unlikely(ret)){
395         return -1;
396     }
397 
398 	ret = drv_acc_st_ais328dq_set_bdu(&ais328dq_ctx);
399     if(unlikely(ret)){
400         return -1;
401     }
402 
403     //set odr is 100hz, and will update
404     ret = drv_acc_st_ais328dq_set_odr(&ais328dq_ctx, AIS328DQ_ACC_DEFAULT_ODR_100HZ);
405     if(unlikely(ret)){
406         return -1;
407     }
408 
409     /* update the phy sensor info to sensor hal */
410     LOG("%s %s successfully \n", SENSOR_STR, __func__);
411     return 0;
412 }
413 
414 SENSOR_DRV_ADD(drv_acc_st_ais328dq_init);
415 
416