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 LIS331HH_I2C_ADDR1                 	(0x18)
16 #define LIS331HH_I2C_ADDR2                 	(0x19)
17 #define LIS331HH_I2C_ADDR_TRANS(n)         	((n)<<1)
18 #define LIS331HH_I2C_ADDR                  	LIS331HH_I2C_ADDR_TRANS(LIS331HH_I2C_ADDR1)
19 
20 #define LIS331HH_ACC_WHO_AM_I              	0x0F
21 #define LIS331HH_ACC_CTRL_REG1             	0x20
22 #define LIS331HH_ACC_CTRL_REG2             	0x21
23 #define LIS331HH_ACC_CTRL_REG3            	0x22
24 #define LIS331HH_ACC_CTRL_REG4             	0x23
25 #define LIS331HH_ACC_CTRL_REG5             	0x24
26 #define LIS331HH_ACC_STATUS_REG           	0x27
27 #define LIS331HH_ACC_OUT_X_L              	0x28
28 #define LIS331HH_ACC_OUT_X_H              	0x29
29 #define LIS331HH_ACC_OUT_Y_L              	0x2A
30 #define LIS331HH_ACC_OUT_Y_H              	0x2B
31 #define LIS331HH_ACC_OUT_Z_L              	0x2C
32 #define LIS331HH_ACC_OUT_Z_H              	0x2D
33 
34 #define LIS331HH_ACC_RANGE_6G              	(0x0)
35 #define LIS331HH_ACC_RANGE_12G             	(0x1)
36 #define LIS331HH_ACC_RANGE_24G              (0x3)
37 #define LIS331HH_ACC_RANGE_MSK              (0x30)
38 #define LIS331HH_ACC_RANGE_POS              (4)
39 
40 #define LIS331HH_ACC_SENSITIVITY_6G        	3
41 #define LIS331HH_ACC_SENSITIVITY_12G        6
42 #define LIS331HH_ACC_SENSITIVITY_24G        12
43 
44 #define LIS331HH_SHIFT_EIGHT_BITS           (8)
45 #define LIS331HH_SHIFT_FOUR_BITS            (4)
46 
47 #define LIS331HH_16_BIT_SHIFT               (0xFF)
48 
49 #define LIS331HH_ACC_ODR_POWER_DOWN			(0x00)
50 #define LIS331HH_ACC_ODR_0_5_HZ             (0x40)
51 #define LIS331HH_ACC_ODR_1_HZ               (0x60)
52 #define LIS331HH_ACC_ODR_2_HZ               (0x80)
53 #define LIS331HH_ACC_ODR_5_HZ               (0xA0)
54 #define LIS331HH_ACC_ODR_10_HZ              (0xC0)
55 #define LIS331HH_ACC_ODR_50_HZ              (0x20)
56 #define LIS331HH_ACC_ODR_100_HZ             (0x28)
57 #define LIS331HH_ACC_ODR_400_HZ             (0x30)
58 #define LIS331HH_ACC_ODR_1000_HZ            (0x38)
59 #define LIS331HH_ACC_ODR_MSK                (0xF8)
60 #define LIS331HH_ACC_ODR_POS                (3)
61 
62 #define LIS331HH_ACC_DEFAULT_ODR_100HZ      (100)
63 
64 #define LIS331HH_BDU_ENABLE					(0x80)
65 
66 #define LIS331HH_ACC_STATUS_ZYXDA			(0x08)
67 
68 #define LIS331HH_GET_BITSLICE(regvar, bitname)\
69 ((regvar & bitname##_MSK) >> bitname##_POS)
70 
71 #define LIS331HH_SET_BITSLICE(regvar, bitname, val)\
72 	((regvar & ~bitname##_MSK) | ((val<<bitname##_POS)&bitname##_MSK))
73 
74 
75 static int32_t lis331hh_acc_factor[ACC_RANGE_MAX] = {0, 0, 0, 0, LIS331HH_ACC_SENSITIVITY_6G,
76 																		LIS331HH_ACC_SENSITIVITY_12G, LIS331HH_ACC_SENSITIVITY_24G };
77 static int32_t cur_acc_factor = 0;
78 
79 
80 i2c_dev_t lis331hh_ctx = {
81     .port = 3,
82     .config.address_width = 8,
83     .config.freq = 400000,
84     .config.dev_addr = LIS331HH_I2C_ADDR,
85 };
86 
drv_acc_st_lis331hh_set_power_mode(i2c_dev_t * drv,dev_power_mode_e mode)87 static int drv_acc_st_lis331hh_set_power_mode(i2c_dev_t* drv, dev_power_mode_e mode)
88 {
89     uint8_t value  = 0x00;
90     int ret = 0;
91 
92     ret = sensor_i2c_read(drv, LIS331HH_ACC_CTRL_REG1, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
93     if(unlikely(ret)){
94         return ret;
95     }
96 
97     switch(mode){
98         case DEV_POWER_ON:{
99             value = LIS331HH_SET_BITSLICE(value,LIS331HH_ACC_ODR,LIS331HH_ACC_ODR_10_HZ);
100             ret = sensor_i2c_write(drv, LIS331HH_ACC_CTRL_REG1, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
101             if(unlikely(ret)){
102                 return ret;
103             }
104         }break;
105 
106         case DEV_POWER_OFF:{
107             value = LIS331HH_SET_BITSLICE(value,LIS331HH_ACC_ODR,LIS331HH_ACC_ODR_POWER_DOWN);
108             ret = sensor_i2c_write(drv, LIS331HH_ACC_CTRL_REG1, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
109             if(unlikely(ret)){
110                 return ret;
111             }
112         }break;
113 
114         case DEV_SLEEP:{
115             value = LIS331HH_SET_BITSLICE(value,LIS331HH_ACC_ODR,LIS331HH_ACC_ODR_10_HZ);
116             ret = sensor_i2c_write(drv, LIS331HH_ACC_CTRL_REG1, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
117             if(unlikely(ret)){
118                 return ret;
119             }
120 
121         }break;
122 
123        default:break;
124     }
125     return 0;
126 }
127 
drv_acc_st_lis331hh_hz2odr(uint32_t hz)128 static uint8_t drv_acc_st_lis331hh_hz2odr(uint32_t hz)
129 {
130     if(hz > 400)
131         return LIS331HH_ACC_ODR_1000_HZ;
132     else if(hz > 100)
133         return LIS331HH_ACC_ODR_400_HZ;
134     else if(hz > 50)
135         return LIS331HH_ACC_ODR_100_HZ;
136     else if(hz > 10)
137         return LIS331HH_ACC_ODR_50_HZ;
138     else if(hz > 5)
139         return LIS331HH_ACC_ODR_10_HZ;
140     else if(hz > 2)
141         return LIS331HH_ACC_ODR_5_HZ;
142     else if(hz > 1)
143         return LIS331HH_ACC_ODR_2_HZ;
144 	else
145 		return LIS331HH_ACC_ODR_1_HZ;
146 
147 }
148 
drv_acc_st_lis331hh_set_odr(i2c_dev_t * drv,uint32_t hz)149 static int drv_acc_st_lis331hh_set_odr(i2c_dev_t* drv, uint32_t hz)
150 {
151     int ret = 0;
152     uint8_t value = 0x00;
153     uint8_t odr = drv_acc_st_lis331hh_hz2odr(hz);
154 
155     ret = sensor_i2c_read(drv, LIS331HH_ACC_CTRL_REG1, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
156     if(unlikely(ret)){
157         return ret;
158     }
159 
160     value = LIS331HH_SET_BITSLICE(value,LIS331HH_ACC_ODR,odr);
161 
162     ret = sensor_i2c_write(drv, LIS331HH_ACC_CTRL_REG1, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
163     if(unlikely(ret)){
164         return ret;
165     }
166     return 0;
167 }
168 
drv_acc_st_lis331hh_set_range(i2c_dev_t * drv,uint32_t range)169 static int drv_acc_st_lis331hh_set_range(i2c_dev_t* drv, uint32_t range)
170 {
171 
172     int ret = 0;
173     uint8_t value = 0x00;
174     uint8_t tmp = 0;
175 
176     ret = sensor_i2c_read(drv, LIS331HH_ACC_CTRL_REG4, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
177     if(unlikely(ret)){
178         return ret;
179     }
180 
181     switch (range){
182         case ACC_RANGE_6G:{
183             tmp = LIS331HH_ACC_RANGE_6G;
184         }break;
185 
186         case ACC_RANGE_12G:{
187             tmp = LIS331HH_ACC_RANGE_12G;
188         }break;
189 
190         case ACC_RANGE_24G:{
191             tmp = LIS331HH_ACC_RANGE_24G;
192         }break;
193 
194         default:break;
195     }
196 
197     value  = LIS331HH_SET_BITSLICE(value,LIS331HH_ACC_RANGE,tmp);
198 
199     ret = sensor_i2c_write(drv, LIS331HH_ACC_CTRL_REG4, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
200     if(unlikely(ret)){
201         return ret;
202     }
203 
204     if((range >= ACC_RANGE_6G)&&(range <= ACC_RANGE_24G)){
205         cur_acc_factor = lis331hh_acc_factor[range];
206     }
207 
208     return 0;
209 }
210 
211 
drv_acc_st_lis331hh_set_bdu(i2c_dev_t * drv)212 static int drv_acc_st_lis331hh_set_bdu(i2c_dev_t* drv)
213 {
214     uint8_t value = 0x00;
215     int ret = 0;
216 
217     ret = sensor_i2c_read(drv, LIS331HH_ACC_CTRL_REG4, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
218     if(unlikely(ret)){
219         return ret;
220     }
221     value |= LIS331HH_BDU_ENABLE;
222 
223     ret = sensor_i2c_write(drv, LIS331HH_ACC_CTRL_REG4, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
224     if(unlikely(ret)){
225         return ret;
226     }
227     return 0;
228 }
229 
drv_acc_st_lis331hh_irq_handle(void)230 static void drv_acc_st_lis331hh_irq_handle(void)
231 {
232     /* no handle so far */
233 }
234 
drv_acc_st_lis331hh_open(void)235 static int drv_acc_st_lis331hh_open(void)
236 {
237     int ret = 0;
238     ret  = drv_acc_st_lis331hh_set_power_mode(&lis331hh_ctx, DEV_POWER_ON);
239     if(unlikely(ret)){
240         return -1;
241     }
242 
243     ret = drv_acc_st_lis331hh_set_range(&lis331hh_ctx, ACC_RANGE_6G);
244     if(unlikely(ret)){
245         return -1;
246     }
247 
248     ret = drv_acc_st_lis331hh_set_odr(&lis331hh_ctx, LIS331HH_ACC_DEFAULT_ODR_100HZ);
249     if(unlikely(ret)){
250         return -1;
251     }
252 
253     return 0;
254 
255 }
256 
drv_acc_st_lis331hh_close(void)257 static int drv_acc_st_lis331hh_close(void)
258 {
259     int ret = 0;
260     ret  = drv_acc_st_lis331hh_set_power_mode(&lis331hh_ctx, DEV_POWER_OFF);
261     if(unlikely(ret)){
262         return -1;
263     }
264     return 0;
265 }
266 
drv_acc_st_lis331hh_read(void * buf,size_t len)267 static int drv_acc_st_lis331hh_read(void *buf, size_t len)
268 {
269 
270     int ret = 0;
271     size_t size;
272     uint8_t reg[6];
273     accel_data_t *accel = (accel_data_t *)buf;
274     if(buf == NULL){
275         return -1;
276     }
277 
278     size = sizeof(accel_data_t);
279     if(len < size){
280         return -1;
281     }
282 
283 	ret = sensor_i2c_read(&lis331hh_ctx, (LIS331HH_ACC_OUT_X_L | 0x80), reg, 6, I2C_OP_RETRIES);
284 
285 	if(unlikely(ret)){
286         return -1;
287     }
288     accel->data[DATA_AXIS_X] = (int16_t)((((int16_t)((int8_t)reg[1]))<< LIS331HH_SHIFT_EIGHT_BITS)|(reg[0]));
289 	accel->data[DATA_AXIS_X] = accel->data[DATA_AXIS_X] >> LIS331HH_SHIFT_FOUR_BITS;
290     accel->data[DATA_AXIS_Y] = (int16_t)((((int16_t)((int8_t)reg[3]))<< LIS331HH_SHIFT_EIGHT_BITS)|(reg[2]));
291 	accel->data[DATA_AXIS_Y] = accel->data[DATA_AXIS_Y] >> LIS331HH_SHIFT_FOUR_BITS;
292 	accel->data[DATA_AXIS_Z] = (int16_t)((((int16_t)((int8_t)reg[5]))<< LIS331HH_SHIFT_EIGHT_BITS)|(reg[4]));
293 	accel->data[DATA_AXIS_Z] = accel->data[DATA_AXIS_Z] >> LIS331HH_SHIFT_FOUR_BITS;
294 
295     if(cur_acc_factor != 0){
296         accel->data[DATA_AXIS_X] = accel->data[DATA_AXIS_X] * cur_acc_factor;
297         accel->data[DATA_AXIS_Y] = accel->data[DATA_AXIS_Y] * cur_acc_factor;
298         accel->data[DATA_AXIS_Z] = accel->data[DATA_AXIS_Z] * cur_acc_factor;
299     }
300 
301     accel->timestamp = aos_now_ms();
302 
303     return (int)size;
304 }
305 
drv_acc_st_lis331hh_ioctl(int cmd,unsigned long arg)306 static int drv_acc_st_lis331hh_ioctl(int cmd, unsigned long arg)
307 {
308     int ret = 0;
309     dev_sensor_info_t *info = (dev_sensor_info_t *)arg;
310 
311     switch(cmd){
312         case SENSOR_IOCTL_ODR_SET:{
313             ret = drv_acc_st_lis331hh_set_odr(&lis331hh_ctx, arg);
314             if(unlikely(ret)){
315                 return -1;
316             }
317         }break;
318         case SENSOR_IOCTL_RANGE_SET:{
319             ret = drv_acc_st_lis331hh_set_range(&lis331hh_ctx, arg);
320             if(unlikely(ret)){
321                 return -1;
322             }
323         }break;
324         case SENSOR_IOCTL_SET_POWER:{
325             ret = drv_acc_st_lis331hh_set_power_mode(&lis331hh_ctx, arg);
326             if(unlikely(ret)){
327                 return -1;
328             }
329         }break;
330         case SENSOR_IOCTL_GET_INFO:{
331             /* fill the dev info here */
332             info->model = "LIS331HH";
333             info->range_max = 24;
334             info->range_min = 6;
335             info->unit = mg;
336 
337         }break;
338        default:break;
339     }
340 
341     return 0;
342 }
343 
drv_acc_st_lis331hh_init(void)344 int drv_acc_st_lis331hh_init(void){
345     int ret = 0;
346     sensor_obj_t sensor;
347     memset(&sensor, 0, sizeof(sensor));
348 
349     /* fill the sensor obj parameters here */
350     sensor.io_port    = I2C_PORT;
351     sensor.tag        = TAG_DEV_ACC;
352     sensor.path       = dev_acc_path;
353     sensor.open       = drv_acc_st_lis331hh_open;
354     sensor.close      = drv_acc_st_lis331hh_close;
355     sensor.read       = drv_acc_st_lis331hh_read;
356     sensor.write      = NULL;
357     sensor.ioctl      = drv_acc_st_lis331hh_ioctl;
358     sensor.irq_handle = drv_acc_st_lis331hh_irq_handle;
359 
360     ret = sensor_create_obj(&sensor);
361     if(unlikely(ret)){
362         return -1;
363     }
364 
365     ret = drv_acc_st_lis331hh_set_range(&lis331hh_ctx, ACC_RANGE_6G);
366     if(unlikely(ret)){
367         return -1;
368     }
369 
370 	ret = drv_acc_st_lis331hh_set_bdu(&lis331hh_ctx);
371     if(unlikely(ret)){
372         return -1;
373     }
374 
375     //set odr is 100hz, and will update
376     ret = drv_acc_st_lis331hh_set_odr(&lis331hh_ctx, LIS331HH_ACC_DEFAULT_ODR_100HZ);
377     if(unlikely(ret)){
378         return -1;
379     }
380 
381     /* update the phy sensor info to sensor hal */
382     LOG("%s %s successfully \n", SENSOR_STR, __func__);
383     return 0;
384 }
385 
386 SENSOR_DRV_ADD(drv_acc_st_lis331hh_init);
387 
388 
389