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 LIS2HH12_I2C_ADDR1 (0x1E)
16 #define LIS2HH12_I2C_ADDR2 (0x1D)
17 #define LIS2HH12_I2C_ADDR_TRANS(n) ((n)<<1)
18 #define LIS2HH12_I2C_ADDR LIS2HH12_I2C_ADDR_TRANS(LIS2HH12_I2C_ADDR2)
19
20 #define LIS2HH12_ACC_TEMP_L 0x0B
21 #define LIS2HH12_ACC_TEMP_H 0x0C
22
23 #define LIS2HH12_ACC_WHO_AM_I 0x0F
24 #define LIS2HH12_ACC_ACT_THS 0x1E
25 #define LIS2HH12_ACC_ACT_DUR 0x1F
26
27 #define LIS2HH12_ACC_CTRL_REG1 0x20
28 #define LIS2HH12_ACC_CTRL_REG2 0x21
29 #define LIS2HH12_ACC_CTRL_REG3 0x22
30 #define LIS2HH12_ACC_CTRL_REG4 0x23
31 #define LIS2HH12_ACC_CTRL_REG5 0x24
32 #define LIS2HH12_ACC_CTRL_REG6 0x25
33 #define LIS2HH12_ACC_CTRL_REG7 0x26
34 #define LIS2HH12_ACC_STATUS_REG 0x27
35 #define LIS2HH12_ACC_OUT_X_L 0x28
36 #define LIS2HH12_ACC_OUT_X_H 0x29
37 #define LIS2HH12_ACC_OUT_Y_L 0x2A
38 #define LIS2HH12_ACC_OUT_Y_H 0x2B
39 #define LIS2HH12_ACC_OUT_Z_L 0x2C
40 #define LIS2HH12_ACC_OUT_Z_H 0x2D
41
42 #define LIS2HH12_ACC_RANGE_2G (0x0)
43 #define LIS2HH12_ACC_RANGE_4G (0x2)
44 #define LIS2HH12_ACC_RANGE_8G (0x3)
45 #define LIS2HH12_ACC_RANGE_MSK (0x30)
46 #define LIS2HH12_ACC_RANGE_POS (4)
47
48 #define LIS2HH12_ACC_SENSITIVITY_2G (61)
49 #define LIS2HH12_ACC_SENSITIVITY_4G (122)
50 #define LIS2HH12_ACC_SENSITIVITY_8G (244)
51
52 #define LIS2HH12_ACC_CHIP_ID_VALUE (0x41)
53
54 #define LIS2HH12_SHIFT_EIGHT_BITS (8)
55 #define LIS2HH12_SHIFT_FOUR_BITS (4)
56
57 #define LIS2HH12_16_BIT_SHIFT (0xFF)
58
59 #define LIS2HH12_ACC_ODR_POWER_DOWN (0x00)
60 #define LIS2HH12_ACC_ODR_10_HZ (0x01)
61 #define LIS2HH12_ACC_ODR_50_HZ (0x02)
62 #define LIS2HH12_ACC_ODR_100_HZ (0x03)
63 #define LIS2HH12_ACC_ODR_200_HZ (0x04)
64 #define LIS2HH12_ACC_ODR_400_HZ (0x05)
65 #define LIS2HH12_ACC_ODR_800_HZ (0x06)
66 #define LIS2HH12_ACC_ODR_MSK (0X70)
67 #define LIS2HH12_ACC_ODR_POS (4)
68
69 #define LIS2HH12_ENABLE_SOFT_RESET_VALUE (0x40)
70 #define LIS2HH12_ACC_DEFAULT_ODR_100HZ (100)
71
72 #define LIS2HH12_BDU_ENABLE (0x08)
73
74 #define LIS2HH12_ACC_STATUS_ZYXDA (0x08)
75
76 #define LIS2HH12_GET_BITSLICE(regvar, bitname)\
77 ((regvar & bitname##_MSK) >> bitname##_POS)
78
79 #define LIS2HH12_SET_BITSLICE(regvar, bitname, val)\
80 ((regvar & ~bitname##_MSK) | ((val<<bitname##_POS)&bitname##_MSK))
81
82
83 static int32_t lis2hh12_acc_factor[ACC_RANGE_MAX] = { LIS2HH12_ACC_SENSITIVITY_2G, LIS2HH12_ACC_SENSITIVITY_4G,
84 LIS2HH12_ACC_SENSITIVITY_8G};
85 static int32_t cur_acc_factor = 0;
86
87
88 i2c_dev_t lis2hh12_ctx = {
89 .port = 3,
90 .config.address_width = 8,
91 .config.freq = 400000,
92 .config.dev_addr = LIS2HH12_I2C_ADDR,
93 };
94
95
drv_acc_st_lis2hh12_soft_reset(i2c_dev_t * drv)96 static int drv_acc_st_lis2hh12_soft_reset(i2c_dev_t* drv)
97 {
98 int ret = 0;
99 uint8_t value = LIS2HH12_ENABLE_SOFT_RESET_VALUE;
100 ret = sensor_i2c_write(drv, LIS2HH12_ACC_CTRL_REG5, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
101 if(unlikely(ret)){
102 return -1;
103 }
104 return 0;
105 }
106
drv_acc_st_lis2hh12_validate_id(i2c_dev_t * drv,uint8_t id_value)107 static int drv_acc_st_lis2hh12_validate_id(i2c_dev_t* drv, uint8_t id_value)
108 {
109 uint8_t value = 0x00;
110 int ret = 0;
111
112 if(drv == NULL){
113 return -1;
114 }
115
116 aos_msleep(20);
117
118 ret = sensor_i2c_read(drv, LIS2HH12_ACC_WHO_AM_I, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
119 if(unlikely(ret)){
120 return ret;
121 }
122
123 if (id_value != value){
124 return -1;
125 }
126
127 return 0;
128 }
129
drv_acc_st_lis2hh12_set_power_mode(i2c_dev_t * drv,dev_power_mode_e mode)130 static int drv_acc_st_lis2hh12_set_power_mode(i2c_dev_t* drv, dev_power_mode_e mode)
131 {
132 uint8_t value = 0x00;
133 int ret = 0;
134
135 ret = sensor_i2c_read(drv, LIS2HH12_ACC_CTRL_REG1, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
136 if(unlikely(ret)){
137 return ret;
138 }
139
140 switch(mode){
141 case DEV_POWER_ON:{
142 value = LIS2HH12_SET_BITSLICE(value,LIS2HH12_ACC_ODR,LIS2HH12_ACC_ODR_10_HZ);
143 ret = sensor_i2c_write(drv, LIS2HH12_ACC_CTRL_REG1, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
144 if(unlikely(ret)){
145 return ret;
146 }
147 }break;
148
149 case DEV_POWER_OFF:{
150 value = LIS2HH12_SET_BITSLICE(value,LIS2HH12_ACC_ODR,LIS2HH12_ACC_ODR_POWER_DOWN);
151 ret = sensor_i2c_write(drv, LIS2HH12_ACC_CTRL_REG1, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
152 if(unlikely(ret)){
153 return ret;
154 }
155 }break;
156
157 case DEV_SLEEP:{
158 value = LIS2HH12_SET_BITSLICE(value,LIS2HH12_ACC_ODR,LIS2HH12_ACC_ODR_10_HZ);
159 ret = sensor_i2c_write(drv, LIS2HH12_ACC_CTRL_REG1, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
160 if(unlikely(ret)){
161 return ret;
162 }
163
164 }break;
165
166 default:break;
167 }
168 return 0;
169 }
170
drv_acc_st_lis2hh12_hz2odr(uint32_t hz)171 static uint8_t drv_acc_st_lis2hh12_hz2odr(uint32_t hz)
172 {
173 if(hz > 400)
174 return LIS2HH12_ACC_ODR_800_HZ;
175 else if(hz > 200)
176 return LIS2HH12_ACC_ODR_400_HZ;
177 else if(hz > 100)
178 return LIS2HH12_ACC_ODR_200_HZ;
179 else if(hz > 50)
180 return LIS2HH12_ACC_ODR_100_HZ;
181 else if(hz > 10)
182 return LIS2HH12_ACC_ODR_50_HZ;
183 else
184 return LIS2HH12_ACC_ODR_10_HZ;
185
186 }
187
drv_acc_st_lis2hh12_set_odr(i2c_dev_t * drv,uint32_t hz)188 static int drv_acc_st_lis2hh12_set_odr(i2c_dev_t* drv, uint32_t hz)
189 {
190 int ret = 0;
191 uint8_t value = 0x00;
192 uint8_t odr = drv_acc_st_lis2hh12_hz2odr(hz);
193
194 ret = sensor_i2c_read(drv, LIS2HH12_ACC_CTRL_REG1, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
195 if(unlikely(ret)){
196 return ret;
197 }
198
199 value = LIS2HH12_SET_BITSLICE(value,LIS2HH12_ACC_ODR,odr);
200
201 ret = sensor_i2c_write(drv, LIS2HH12_ACC_CTRL_REG1, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
202 if(unlikely(ret)){
203 return ret;
204 }
205 return 0;
206 }
207
drv_acc_st_lis2hh12_set_range(i2c_dev_t * drv,uint32_t range)208 static int drv_acc_st_lis2hh12_set_range(i2c_dev_t* drv, uint32_t range)
209 {
210
211 int ret = 0;
212 uint8_t value = 0x00;
213 uint8_t tmp = 0;
214
215 ret = sensor_i2c_read(drv, LIS2HH12_ACC_CTRL_REG4, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
216 if(unlikely(ret)){
217 return ret;
218 }
219
220 switch (range){
221 case ACC_RANGE_2G:{
222 tmp = LIS2HH12_ACC_RANGE_2G;
223 }break;
224
225 case ACC_RANGE_4G:{
226 tmp = LIS2HH12_ACC_RANGE_4G;
227 }break;
228
229 case ACC_RANGE_8G:{
230 tmp = LIS2HH12_ACC_RANGE_8G;
231 }break;
232
233 default:break;
234 }
235
236 value = LIS2HH12_SET_BITSLICE(value,LIS2HH12_ACC_RANGE,tmp);
237
238 LOG("LIS2HH12 SetRang %2x:0x%2x\n", range, value);
239 ret = sensor_i2c_write(drv, LIS2HH12_ACC_CTRL_REG4, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
240 if(unlikely(ret)){
241 return ret;
242 }
243
244 if((range >= ACC_RANGE_2G)&&(range <= ACC_RANGE_8G)){
245 cur_acc_factor = lis2hh12_acc_factor[range];
246 }
247
248 return 0;
249 }
250
251
drv_acc_st_lis2hh12_set_bdu(i2c_dev_t * drv)252 static int drv_acc_st_lis2hh12_set_bdu(i2c_dev_t* drv)
253 {
254 uint8_t value = 0x00;
255 int ret = 0;
256
257 ret = sensor_i2c_read(drv, LIS2HH12_ACC_CTRL_REG1, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
258 if(unlikely(ret)){
259 return ret;
260 }
261 value |= LIS2HH12_BDU_ENABLE;
262
263 ret = sensor_i2c_write(drv, LIS2HH12_ACC_CTRL_REG1, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
264 if(unlikely(ret)){
265 return ret;
266 }
267 return 0;
268 }
269
drv_acc_st_lis2hh12_irq_handle(void)270 static void drv_acc_st_lis2hh12_irq_handle(void)
271 {
272 /* no handle so far */
273 }
274
drv_acc_st_lis2hh12_open(void)275 static int drv_acc_st_lis2hh12_open(void)
276 {
277 int ret = 0;
278 ret = drv_acc_st_lis2hh12_set_power_mode(&lis2hh12_ctx, DEV_POWER_ON);
279 if(unlikely(ret)){
280 return -1;
281 }
282
283 ret = drv_acc_st_lis2hh12_set_range(&lis2hh12_ctx, ACC_RANGE_8G);
284 if(unlikely(ret)){
285 return -1;
286 }
287
288 ret = drv_acc_st_lis2hh12_set_odr(&lis2hh12_ctx, LIS2HH12_ACC_DEFAULT_ODR_100HZ);
289 if(unlikely(ret)){
290 return -1;
291 }
292
293 return 0;
294
295 }
296
drv_acc_st_lis2hh12_close(void)297 static int drv_acc_st_lis2hh12_close(void)
298 {
299 int ret = 0;
300 ret = drv_acc_st_lis2hh12_set_power_mode(&lis2hh12_ctx, DEV_POWER_OFF);
301 if(unlikely(ret)){
302 return -1;
303 }
304 return 0;
305 }
306
drv_acc_st_lis2hh12_read(void * buf,size_t len)307 static int drv_acc_st_lis2hh12_read(void *buf, size_t len)
308 {
309
310 int ret = 0;
311 size_t size;
312 uint8_t reg[6];
313 accel_data_t *accel = (accel_data_t *)buf;
314 if(buf == NULL){
315 return -1;
316 }
317
318 size = sizeof(accel_data_t);
319 if(len < size){
320 return -1;
321 }
322
323 ret = sensor_i2c_read(&lis2hh12_ctx, (LIS2HH12_ACC_OUT_X_L | 0x80), reg, 6, I2C_OP_RETRIES);
324
325 if(unlikely(ret)){
326 return -1;
327 }
328 accel->data[DATA_AXIS_X] = (int16_t)((((int16_t)((int8_t)reg[1]))<< LIS2HH12_SHIFT_EIGHT_BITS)|(reg[0]));
329 accel->data[DATA_AXIS_Y] = (int16_t)((((int16_t)((int8_t)reg[3]))<< LIS2HH12_SHIFT_EIGHT_BITS)|(reg[2]));
330 accel->data[DATA_AXIS_Z] = (int16_t)((((int16_t)((int8_t)reg[5]))<< LIS2HH12_SHIFT_EIGHT_BITS)|(reg[4]));
331
332 if(cur_acc_factor != 0){
333 accel->data[DATA_AXIS_X] = accel->data[DATA_AXIS_X] * cur_acc_factor / 1000;
334 accel->data[DATA_AXIS_Y] = accel->data[DATA_AXIS_Y] * cur_acc_factor / 1000;
335 accel->data[DATA_AXIS_Z] = accel->data[DATA_AXIS_Z] * cur_acc_factor / 1000;
336 }
337
338 accel->timestamp = aos_now_ms();
339
340 return (int)size;
341 }
342
drv_acc_st_lis2hh12_ioctl(int cmd,unsigned long arg)343 static int drv_acc_st_lis2hh12_ioctl(int cmd, unsigned long arg)
344 {
345 int ret = 0;
346 dev_sensor_info_t *info = (dev_sensor_info_t *)arg;
347
348 switch(cmd){
349 case SENSOR_IOCTL_ODR_SET:{
350 ret = drv_acc_st_lis2hh12_set_odr(&lis2hh12_ctx, arg);
351 if(unlikely(ret)){
352 return -1;
353 }
354 }break;
355 case SENSOR_IOCTL_RANGE_SET:{
356 ret = drv_acc_st_lis2hh12_set_range(&lis2hh12_ctx, arg);
357 if(unlikely(ret)){
358 return -1;
359 }
360 }break;
361 case SENSOR_IOCTL_SET_POWER:{
362 ret = drv_acc_st_lis2hh12_set_power_mode(&lis2hh12_ctx, arg);
363 if(unlikely(ret)){
364 return -1;
365 }
366 }break;
367 case SENSOR_IOCTL_GET_INFO:{
368 /* fill the dev info here */
369 info->model = "LIS2HH12";
370 info->range_max = 8;
371 info->range_min = 2;
372 info->unit = mg;
373
374 }break;
375 default:break;
376 }
377
378 return 0;
379 }
380
drv_acc_st_lis2hh12_init(void)381 int drv_acc_st_lis2hh12_init(void){
382 int ret = 0;
383 sensor_obj_t sensor;
384 memset(&sensor, 0, sizeof(sensor));
385
386 /* fill the sensor obj parameters here */
387 sensor.io_port = I2C_PORT;
388 sensor.tag = TAG_DEV_ACC;
389 sensor.path = dev_acc_path;
390 sensor.open = drv_acc_st_lis2hh12_open;
391 sensor.close = drv_acc_st_lis2hh12_close;
392 sensor.read = drv_acc_st_lis2hh12_read;
393 sensor.write = NULL;
394 sensor.ioctl = drv_acc_st_lis2hh12_ioctl;
395 sensor.irq_handle = drv_acc_st_lis2hh12_irq_handle;
396
397 ret = sensor_create_obj(&sensor);
398 if(unlikely(ret)){
399 return -1;
400 }
401
402 ret = drv_acc_st_lis2hh12_validate_id(&lis2hh12_ctx, LIS2HH12_ACC_CHIP_ID_VALUE);
403 if(unlikely(ret)){
404 return -1;
405 }
406
407 ret = drv_acc_st_lis2hh12_soft_reset(&lis2hh12_ctx);
408 if(unlikely(ret)){
409 return -1;
410 }
411
412 ret = drv_acc_st_lis2hh12_set_range(&lis2hh12_ctx, ACC_RANGE_8G);
413 if(unlikely(ret)){
414 return -1;
415 }
416
417 ret = drv_acc_st_lis2hh12_set_bdu(&lis2hh12_ctx);
418 if(unlikely(ret)){
419 return -1;
420 }
421
422 //set odr is 100hz, and will update
423 ret = drv_acc_st_lis2hh12_set_odr(&lis2hh12_ctx, LIS2HH12_ACC_DEFAULT_ODR_100HZ);
424 if(unlikely(ret)){
425 return -1;
426 }
427
428 /* update the phy sensor info to sensor hal */
429 LOG("%s %s successfully \n", SENSOR_STR, __func__);
430 return 0;
431 }
432
433 SENSOR_DRV_ADD(drv_acc_st_lis2hh12_init);
434
435
436