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 ADXL372_I2C_ADDR1 (0x1D)
16 #define ADXL372_I2C_ADDR2 (0x53)
17 #define ADXL372_I2C_ADDR_TRANS(n) ((n) << 1)
18 #define ADXL372_I2C_ADDR ADXL372_I2C_ADDR_TRANS(ADXL372_I2C_ADDR1)
19 
20 /* ADXL372 registers definition */
21 #define ADXL372_DEVID 0x00
22 #define ADXL372_DEVID_MST 0x01
23 #define ADXL372_PARTID 0x02
24 #define ADXL372_REVID 0x03
25 #define ADXL372_STATUS_1 0x04
26 #define ADXL372_STATUS_2 0x05
27 #define ADXL372_FIFO_ENTRIES_2 0x06
28 #define ADXL372_FIFO_ENTRIES_1 0x07
29 #define ADXL372_X_DATA_H 0x08
30 #define ADXL372_X_DATA_L 0x09
31 #define ADXL372_Y_DATA_H 0x0A
32 #define ADXL372_Y_DATA_L 0x0B
33 #define ADXL372_Z_DATA_H 0x0C
34 #define ADXL372_Z_DATA_L 0x0D
35 #define ADXL372_X_MAXPEAK_H 0x15
36 #define ADXL372_X_MAXPEAK_L 0x16
37 #define ADXL372_Y_MAXPEAK_H 0x17
38 #define ADXL372_Y_MAXPEAK_L 0x18
39 #define ADXL372_Z_MAXPEAK_H 0x19
40 #define ADXL372_Z_MAXPEAK_L 0x1A
41 #define ADXL372_OFFSET_X 0x20
42 #define ADXL372_OFFSET_Y 0x21
43 #define ADXL372_OFFSET_Z 0x22
44 #define ADXL372_X_THRESH_ACT_H 0x23
45 #define ADXL372_X_THRESH_ACT_L 0x24
46 #define ADXL372_Y_THRESH_ACT_H 0x25
47 #define ADXL372_Y_THRESH_ACT_L 0x26
48 #define ADXL372_Z_THRESH_ACT_H 0x27
49 #define ADXL372_Z_THRESH_ACT_L 0x28
50 #define ADXL372_TIME_ACT 0x29
51 #define ADXL372_X_THRESH_INACT_H 0x2A
52 #define ADXL372_X_THRESH_INACT_L 0x2B
53 #define ADXL372_Y_THRESH_INACT_H 0x2C
54 #define ADXL372_Y_THRESH_INACT_L 0x2D
55 #define ADXL372_Z_THRESH_INACT_H 0x2E
56 #define ADXL372_Z_THRESH_INACT_L 0x2F
57 #define ADXL372_TIME_INACT_H 0x30
58 #define ADXL372_TIME_INACT_L 0x31
59 #define ADXL372_X_THRESH_ACT2_H 0x32
60 #define ADXL372_X_THRESH_ACT2_L 0x33
61 #define ADXL372_Y_THRESH_ACT2_H 0x34
62 #define ADXL372_Y_THRESH_ACT2_L 0x35
63 #define ADXL372_Z_THRESH_ACT2_H 0x36
64 #define ADXL372_Z_THRESH_ACT2_L 0x37
65 #define ADXL372_HPF 0x38
66 #define ADXL372_FIFO_SAMPLES 0x39
67 #define ADXL372_FIFO_CTL 0x3A
68 #define ADXL372_INT1_MAP 0x3B
69 #define ADXL372_INT2_MAP 0x3C
70 #define ADXL372_TIMING 0x3D
71 #define ADXL372_MEASURE 0x3E
72 #define ADXL372_POWER_CTL 0x3F
73 #define ADXL372_SELF_TEST 0x40
74 #define ADXL372_RESET 0x41
75 #define ADXL372_FIFO_DATA 0x42
76 
77 #define ADXL372_DEVID_VAL 0xAD
78 #define ADXL372_PARTID_VAL 0xFA
79 #define ADXL372_RESET_CODE 0x52
80 
81 #define ADXL372_ODR_6400HZ (0x04 << 5)
82 #define ADXL372_ODR_3200HZ (0x03 << 5)
83 #define ADXL372_ODR_1600HZ (0x02 << 5)
84 #define ADXL372_ODR_800HZ (0x01 << 5)
85 #define ADXL372_ODR_400HZ (0x00 << 5)
86 #define ADXL372_ODR_BIT_MASK 0x1F
87 #define ADXL372_DEFAULT_ODR 400
88 
89 #define ADXL372_BW_3200HZ 0x04
90 #define ADXL372_BW_1600HZ 0x03
91 #define ADXL372_BW_800HZ 0x02
92 #define ADXL372_BW_400HZ 0x01
93 #define ADXL372_BW_200HZ 0x00
94 #define ADXL372_BW_BIT_MASK 0xF8
95 #define ADXL372_DEFAULT_BW 200
96 
97 i2c_dev_t adxl372_ctx = {
98     .port                 = 3,
99     .config.address_width = 8,
100     .config.freq          = 400000,
101     .config.dev_addr      = ADXL372_I2C_ADDR,
102 };
103 
drv_acc_adi_adxl372_soft_reset(i2c_dev_t * drv)104 static int drv_acc_adi_adxl372_soft_reset(i2c_dev_t *drv)
105 {
106     int     ret   = 0;
107     uint8_t value = ADXL372_RESET_CODE;
108     ret           = sensor_i2c_write(drv, ADXL372_RESET, &value, I2C_DATA_LEN,
109                            I2C_OP_RETRIES);
110     if (unlikely(ret)) {
111         return -1;
112     }
113     return 0;
114 }
115 
drv_acc_adi_adxl372_validate_id(i2c_dev_t * drv,uint8_t id_value)116 static int drv_acc_adi_adxl372_validate_id(i2c_dev_t *drv, uint8_t id_value)
117 {
118     uint8_t value = 0x00;
119     int     ret   = 0;
120 
121     if (drv == NULL) {
122         return -1;
123     }
124 
125     ret = sensor_i2c_read(drv, ADXL372_PARTID, &value, I2C_DATA_LEN,
126                           I2C_OP_RETRIES);
127     if (unlikely(ret)) {
128         return -1;
129     }
130 
131     if (id_value != value) {
132         return -1;
133     }
134 
135     return 0;
136 }
137 
drv_acc_adi_adxl372_set_power_mode(i2c_dev_t * drv,dev_power_mode_e mode)138 static int drv_acc_adi_adxl372_set_power_mode(i2c_dev_t *      drv,
139                                               dev_power_mode_e mode)
140 {
141     uint8_t value;
142     int     ret = 0;
143 
144     ret = sensor_i2c_read(drv, ADXL372_POWER_CTL, &value, I2C_DATA_LEN,
145                           I2C_OP_RETRIES);
146     if (unlikely(ret)) {
147         return ret;
148     }
149 
150     switch (mode) {
151         case DEV_POWER_ON: {
152             value &= 0xFC;
153             value |= 0x03;
154             ret = sensor_i2c_write(drv, ADXL372_POWER_CTL, &value, I2C_DATA_LEN,
155                                    I2C_OP_RETRIES);
156             if (unlikely(ret)) {
157                 return ret;
158             }
159         } break;
160 
161         case DEV_POWER_OFF: {
162             value &= 0xFC;
163             ret = sensor_i2c_write(drv, ADXL372_POWER_CTL, &value, I2C_DATA_LEN,
164                                    I2C_OP_RETRIES);
165             if (unlikely(ret)) {
166                 return ret;
167             }
168         } break;
169 
170         default:
171             break;
172     }
173     return 0;
174 }
175 
drv_acc_adi_adxl372_set_odr(i2c_dev_t * drv,uint32_t odr)176 static int drv_acc_adi_adxl372_set_odr(i2c_dev_t *drv, uint32_t odr)
177 {
178     int     ret   = 0;
179     uint8_t value = 0x00;
180 
181     ret = sensor_i2c_read(drv, ADXL372_TIMING, &value, I2C_DATA_LEN,
182                           I2C_OP_RETRIES);
183     if (unlikely(ret)) {
184         return ret;
185     }
186 
187     if (odr >= 6400) {
188         value &= ADXL372_ODR_BIT_MASK;
189         value |= ADXL372_ODR_6400HZ;
190     } else if (odr >= 3200) {
191         value &= ADXL372_ODR_BIT_MASK;
192         value |= ADXL372_ODR_3200HZ;
193     } else if (odr >= 1600) {
194         value &= ADXL372_ODR_BIT_MASK;
195         value |= ADXL372_ODR_1600HZ;
196     } else if (odr >= 800) {
197         value &= ADXL372_ODR_BIT_MASK;
198         value |= ADXL372_ODR_800HZ;
199     } else {
200         value &= ADXL372_ODR_BIT_MASK;
201         value |= ADXL372_ODR_400HZ;
202     }
203 
204     ret = sensor_i2c_write(drv, ADXL372_TIMING, &value, I2C_DATA_LEN,
205                            I2C_OP_RETRIES);
206     if (unlikely(ret)) {
207         return ret;
208     }
209     return 0;
210 }
211 
drv_acc_adi_adxl372_set_bw(i2c_dev_t * drv,uint32_t bw)212 static int drv_acc_adi_adxl372_set_bw(i2c_dev_t *drv, uint32_t bw)
213 {
214     int     ret   = 0;
215     uint8_t value = 0x00;
216 
217     ret = sensor_i2c_read(drv, ADXL372_MEASURE, &value, I2C_DATA_LEN,
218                           I2C_OP_RETRIES);
219     if (unlikely(ret)) {
220         return ret;
221     }
222 
223     if (bw >= 3200) {
224         value &= ADXL372_BW_BIT_MASK;
225         value |= ADXL372_BW_3200HZ;
226     } else if (bw >= 1600) {
227         value &= ADXL372_BW_BIT_MASK;
228         value |= ADXL372_BW_1600HZ;
229     } else if (bw >= 800) {
230         value &= ADXL372_BW_BIT_MASK;
231         value |= ADXL372_BW_800HZ;
232     } else if (bw >= 400) {
233         value &= ADXL372_BW_BIT_MASK;
234         value |= ADXL372_BW_400HZ;
235     } else {
236         value &= ADXL372_BW_BIT_MASK;
237         value |= ADXL372_BW_200HZ;
238     }
239     ret = sensor_i2c_write(drv, ADXL372_MEASURE, &value, I2C_DATA_LEN,
240                            I2C_OP_RETRIES);
241     if (unlikely(ret)) {
242         return ret;
243     }
244 
245     return 0;
246 }
247 
248 
drv_acc_adi_adxl372_irq_handle(void)249 static void drv_acc_adi_adxl372_irq_handle(void)
250 {
251     /* no handle so far */
252 }
253 
drv_acc_adi_adxl372_open(void)254 static int drv_acc_adi_adxl372_open(void)
255 {
256     int ret = 0;
257     ret     = drv_acc_adi_adxl372_set_power_mode(&adxl372_ctx, DEV_POWER_ON);
258     if (unlikely(ret)) {
259         return -1;
260     }
261     return 0;
262 }
263 
drv_acc_adi_adxl372_close(void)264 static int drv_acc_adi_adxl372_close(void)
265 {
266     int ret = 0;
267     ret     = drv_acc_adi_adxl372_set_power_mode(&adxl372_ctx, DEV_POWER_OFF);
268     if (unlikely(ret)) {
269         return -1;
270     }
271     return 0;
272 }
273 
drv_acc_adi_adxl372_read(void * buf,size_t len)274 static int drv_acc_adi_adxl372_read(void *buf, size_t len)
275 {
276     int     ret = 0;
277     size_t  size;
278     uint8_t LocalBuf[6];
279     int32_t x_val = 0, y_val = 0, z_val = 0;
280     int8_t  SignBit;
281 
282     accel_data_t *accel = (accel_data_t *)buf;
283     if (buf == NULL) {
284         return -1;
285     }
286 
287     size = sizeof(accel_data_t);
288     if (len < size) {
289         return -1;
290     }
291 
292     ret = sensor_i2c_read(&adxl372_ctx, ADXL372_X_DATA_H, &LocalBuf[0],
293                           I2C_REG_LEN, I2C_OP_RETRIES);
294     ret |= sensor_i2c_read(&adxl372_ctx, ADXL372_X_DATA_L, &LocalBuf[1],
295                            I2C_REG_LEN, I2C_OP_RETRIES);
296     ret |= sensor_i2c_read(&adxl372_ctx, ADXL372_Y_DATA_H, &LocalBuf[2],
297                            I2C_REG_LEN, I2C_OP_RETRIES);
298     ret |= sensor_i2c_read(&adxl372_ctx, ADXL372_Y_DATA_L, &LocalBuf[3],
299                            I2C_REG_LEN, I2C_OP_RETRIES);
300     ret |= sensor_i2c_read(&adxl372_ctx, ADXL372_Z_DATA_H, &LocalBuf[4],
301                            I2C_REG_LEN, I2C_OP_RETRIES);
302     ret |= sensor_i2c_read(&adxl372_ctx, ADXL372_Z_DATA_L, &LocalBuf[5],
303                            I2C_REG_LEN, I2C_OP_RETRIES);
304 
305     if (unlikely(ret)) {
306         return -1;
307     }
308 
309     x_val = (int32_t)(((LocalBuf[0] << 8) | ((LocalBuf[1] << 0) & 0xF0)) >> 4);
310     SignBit = (x_val & (1 << 11)) != 0;
311     if (SignBit)
312         x_val = x_val | ~((1 << 12) - 1);
313 
314     y_val = (int32_t)(((LocalBuf[2] << 8) | ((LocalBuf[3] << 0) & 0xF0)) >> 4);
315     SignBit = (y_val & (1 << 11)) != 0;
316     if (SignBit)
317         y_val = y_val | ~((1 << 12) - 1);
318 
319     z_val = (int32_t)(((LocalBuf[4] << 8) | ((LocalBuf[5] << 0) & 0xF0)) >> 4);
320     SignBit = (z_val & (1 << 11)) != 0;
321     if (SignBit)
322         z_val = z_val | ~((1 << 12) - 1);
323 
324     accel->data[DATA_AXIS_X] = (int32_t)(x_val * 100);
325     accel->data[DATA_AXIS_Y] = (int32_t)(y_val * 100);
326     accel->data[DATA_AXIS_Z] = (int32_t)(z_val * 100);
327     accel->timestamp         = aos_now_ms();
328 
329     return (int)size;
330 }
331 
drv_acc_adi_adxl372_ioctl(int cmd,unsigned long arg)332 static int drv_acc_adi_adxl372_ioctl(int cmd, unsigned long arg)
333 {
334     int                ret  = 0;
335     dev_sensor_info_t *info = (dev_sensor_info_t *)arg;
336     switch (cmd) {
337         case SENSOR_IOCTL_ODR_SET: {
338             ret = drv_acc_adi_adxl372_set_odr(&adxl372_ctx, arg);
339             if (unlikely(ret)) {
340                 return -1;
341             }
342         } break;
343 
344         case SENSOR_IOCTL_SET_POWER: {
345             ret = drv_acc_adi_adxl372_set_power_mode(&adxl372_ctx, arg);
346             if (unlikely(ret)) {
347                 return -1;
348             }
349         } break;
350         case SENSOR_IOCTL_GET_INFO: {
351             /* fill the dev info here */
352             info->model     = "ADXL372";
353             info->range_max = 200;
354             info->range_min = 0;
355             info->unit      = mg;
356         } break;
357 
358         default:
359             break;
360     }
361 
362     return 0;
363 }
364 
drv_acc_adi_adxl372_init(void)365 int drv_acc_adi_adxl372_init(void)
366 {
367     int          ret = 0;
368     sensor_obj_t sensor;
369 
370     memset(&sensor, 0, sizeof(sensor));
371     /* fill the sensor obj parameters here */
372     sensor.io_port    = I2C_PORT;
373     sensor.tag        = TAG_DEV_ACC;
374     sensor.path       = dev_acc_path;
375     sensor.open       = drv_acc_adi_adxl372_open;
376     sensor.close      = drv_acc_adi_adxl372_close;
377     sensor.read       = drv_acc_adi_adxl372_read;
378     sensor.write      = NULL;
379     sensor.ioctl      = drv_acc_adi_adxl372_ioctl;
380     sensor.irq_handle = drv_acc_adi_adxl372_irq_handle;
381 
382     ret = sensor_create_obj(&sensor);
383     if (unlikely(ret)) {
384         return -1;
385     }
386 
387     ret = drv_acc_adi_adxl372_validate_id(&adxl372_ctx, ADXL372_PARTID_VAL);
388     if (unlikely(ret)) {
389         return -1;
390     }
391 
392     ret = drv_acc_adi_adxl372_soft_reset(&adxl372_ctx);
393     if (unlikely(ret)) {
394         return -1;
395     }
396 
397     // set odr is 400hz, and will update
398     ret = drv_acc_adi_adxl372_set_odr(&adxl372_ctx, ADXL372_DEFAULT_ODR);
399     if (unlikely(ret)) {
400         return -1;
401     }
402 
403     ret = drv_acc_adi_adxl372_set_bw(&adxl372_ctx, ADXL372_DEFAULT_BW);
404     if (unlikely(ret)) {
405         return -1;
406     }
407 
408     ret = drv_acc_adi_adxl372_set_power_mode(&adxl372_ctx, DEV_POWER_ON);
409     if (unlikely(ret)) {
410         return -1;
411     }
412     /* update the phy sensor info to sensor hal */
413     LOG("%s %s successfully \n", SENSOR_STR, __func__);
414     return 0;
415 }
416 
417 SENSOR_DRV_ADD(drv_acc_adi_adxl372_init);
418 
419