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