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