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