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