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 #define ST480_DEBUG
15 
16 #ifdef ST480_DEBUG
17 #define ST480_LOG  LOG
18 #else
19 #define ST480_LOG
20 #endif
21 
22 //#define ST480_I2C_ADDR1                 0x1C
23 #define ST480_I2C_ADDR2                   0x0C
24 #define ST480_I2C_ADDR_TRANS(n)           ((n)<<1)
25 #define ST480_I2C_ADDR                    ST480_I2C_ADDR_TRANS(ST480_I2C_ADDR2)
26 #define ST480_BIT(x)                      (x)
27 
28 #define I_AM_ST480                        0x7C  //TODO
29 #define ST480_MAG_WHO_AM_I_REG            0x00
30 
31 
32 #define WRITE_REGISTER_CMD 				  0x60
33 #define READ_REGISTER_CMD 			      0x50
34 #define EXIT_REGISTER_CMD 			      0x80
35 #define MEMORY_RECALL_CMD 			      0xD0
36 #define MEMORY_STORE_CMD 			      0xE0
37 #define RESET_CMD 					      0xF0
38 #define ST480_REG_DRR_SHIFT 			  2
39 #define CALIBRATION_REG  				  (0x02 << ST480_REG_DRR_SHIFT)
40 #define CALIBRATION_DATA_LOW			  0x18
41 #define CALIBRATION_DATA_HIGH 			  0x00
42 
43 #define ONE_INIT_DATA_LOW 				  0x7C
44 #define ONE_INIT_DATA_HIGH 				  0x00
45 #define ONE_INIT_REG 					  (0x00 << ST480_REG_DRR_SHIFT)
46 
47 #define TWO_INIT_DATA_LOW 				  0x00
48 #define TWO_INIT_DATA_HIGH 				  0x00
49 #define TWO_INIT_REG 					  (0x02 << ST480_REG_DRR_SHIFT)
50 
51 #define ST480_SINGLE_MODE				  1
52 #define SINGLE_MEASUREMENT_MODE_CMD 	  0x3F
53 
54 
55 #define READ_MEASUREMENT_CMD 			  0x4F
56 
57 #define ST480_MAG_XY_SENSITIVITY_FOR_48GA  15
58 #define ST480_MAG_Z_SENSITIVITY_FOR_48GA   25
59 
60 
61 i2c_dev_t ST480_ctx = {
62 	.port = 4,
63     .config.address_width = 8,
64     .config.freq = 200000,
65     .config.dev_addr = ST480_I2C_ADDR,
66 };
67 
68 
sensor_i2c_single_write(i2c_dev_t * i2c,uint8_t * data,uint16_t size,uint32_t timeout)69 static int32_t sensor_i2c_single_write(i2c_dev_t *i2c, uint8_t *data, uint16_t size, uint32_t timeout)
70 {
71 	int32_t ret = 0;
72 	if(i2c == NULL){
73 		return -1;
74 	}
75 
76 	ret = hal_i2c_master_send(i2c, i2c->config.dev_addr, data, size, AOS_WAIT_FOREVER);
77 
78 	return ret;
79 
80 }
81 
sensor_i2c_single_read(i2c_dev_t * i2c,uint8_t * data,uint16_t size,uint32_t timeout)82 static int32_t sensor_i2c_single_read(i2c_dev_t *i2c, uint8_t *data, uint16_t size, uint32_t timeout)
83 {
84     int32_t ret = 0;
85     if(i2c == NULL){
86         return -1;
87     }
88     ret = hal_i2c_master_recv(i2c, i2c->config.dev_addr, data, size, AOS_WAIT_FOREVER);
89     return ret;
90 
91 }
92 
93 
94 
drv_mag_sen_st480_validate_id(i2c_dev_t * drv,uint8_t id_value)95 static int drv_mag_sen_st480_validate_id(i2c_dev_t* drv, uint8_t id_value)
96 {
97     uint8_t value = 0x00;
98     int ret = 0, i = 1;
99 	uint8_t buf[5];
100 
101     if(drv == NULL){
102         return -1;
103     }
104 
105 	do{
106 		buf[0] = READ_REGISTER_CMD;
107 		buf[1] = 0x00;
108 
109 		ret = sensor_i2c_single_write(drv, buf, 2, I2C_OP_RETRIES);
110 		if(unlikely(ret)){
111 			return ret;
112 		}
113 
114 		ret = sensor_i2c_single_read(drv, buf, 3, I2C_OP_RETRIES);
115 		if(unlikely(ret)){
116 			return ret;
117 		}
118 
119 		ST480_LOG("senodia st480 id = %d.", buf[2]);
120 
121 		value = buf[2];
122 	}while((buf[2] != I_AM_ST480) && (i-- > 0));
123 
124 
125     if (id_value != value){
126         return -1;
127     }
128 
129     return 0;
130 }
131 
drv_mag_sen_st480_set_power_mode(i2c_dev_t * drv,dev_power_mode_e mode)132 static int drv_mag_sen_st480_set_power_mode(i2c_dev_t* drv, dev_power_mode_e mode)
133 {
134     //no use
135 
136     return 0;
137 }
138 
drv_mag_sen_st480_set_odr(i2c_dev_t * drv,uint8_t odr)139 static int drv_mag_sen_st480_set_odr(i2c_dev_t* drv, uint8_t odr)
140 {
141 
142 	//no use
143 
144     return 0;
145 }
146 
147 
drv_mag_sen_st480_set_range(i2c_dev_t * drv,uint32_t range)148 static int drv_mag_sen_st480_set_range(i2c_dev_t* drv, uint32_t range)
149 {
150 
151 	//no use
152 
153     return 0;
154 }
155 
drv_mag_sen_st480_set_default_config(i2c_dev_t * drv)156 static int drv_mag_sen_st480_set_default_config(i2c_dev_t* drv)
157 {
158     uint8_t buf[5] = {0};
159     int ret = 0;
160 
161 	//init register step 1
162 	buf[0] = WRITE_REGISTER_CMD;
163 	buf[1] = ONE_INIT_DATA_HIGH;
164 	buf[2] = ONE_INIT_DATA_LOW;
165 	buf[3] = ONE_INIT_REG;
166 	ret = sensor_i2c_single_write(drv, buf, 4, I2C_OP_RETRIES);
167 	if(unlikely(ret)){
168 		return ret;
169 	}
170 
171 	ret = sensor_i2c_single_read(drv, buf, 1, I2C_OP_RETRIES);
172 	if(unlikely(ret)){
173 		return ret;
174 	}
175 
176 	//init register step 2
177 	buf[0] = WRITE_REGISTER_CMD;
178 	buf[1] = TWO_INIT_DATA_HIGH;
179 	buf[2] = TWO_INIT_DATA_LOW;
180 	buf[3] = TWO_INIT_REG;
181 	ret = sensor_i2c_single_write(drv, buf, 4, I2C_OP_RETRIES);
182 	if(unlikely(ret)){
183 		return ret;
184 	}
185 
186 	ret = sensor_i2c_single_read(drv, buf, 1, I2C_OP_RETRIES);
187 	if(unlikely(ret)){
188 		return ret;
189 	}
190 
191 	//set calibration register
192 	buf[0] = WRITE_REGISTER_CMD;
193 	buf[1] = CALIBRATION_DATA_HIGH;
194 	buf[2] = CALIBRATION_DATA_LOW;
195 	buf[3] = CALIBRATION_REG;
196 	ret = sensor_i2c_single_write(drv, buf, 4, I2C_OP_RETRIES);
197 	if(unlikely(ret)){
198 		return ret;
199 	}
200 
201 	ret = sensor_i2c_single_read(drv, buf, 1, I2C_OP_RETRIES);
202 	if(unlikely(ret)){
203 		return ret;
204 	}
205 
206 	//set mode config
207   	buf[0] = SINGLE_MEASUREMENT_MODE_CMD;
208   	ret = sensor_i2c_single_write(&ST480_ctx, buf, 1, I2C_OP_RETRIES);
209   	if(unlikely(ret)){
210 		  return ret;
211   	}
212 
213   	ret = sensor_i2c_single_read(&ST480_ctx, buf, 1, I2C_OP_RETRIES);
214   	if(unlikely(ret)){
215 		  return ret;
216   	}
217 
218     return 0;
219 }
220 
drv_mag_sen_st480_irq_handle(void)221 static void drv_mag_sen_st480_irq_handle(void)
222 {
223     /* no handle so far */
224 }
225 
drv_mag_sen_st480_open(void)226 static int drv_mag_sen_st480_open(void)
227 {
228     //no use
229     ST480_LOG("drv_mag_sen_st480_open:");
230 
231     return 0;
232 
233 }
234 
drv_mag_sen_st480_close(void)235 static int drv_mag_sen_st480_close(void)
236 {
237 
238     //no use
239     ST480_LOG("drv_mag_sen_st480_close:");
240 
241     return 0;
242 }
243 
drv_mag_sen_st480_read(void * buf,size_t len)244 static int drv_mag_sen_st480_read(void* buf, size_t len)
245 {
246   int ret = 0;
247   size_t size;
248   int16_t pnRawData[3] = {0};
249   uint8_t buffer[9];
250   uint8_t i = 0;
251 
252   mag_data_t* pdata = (mag_data_t*)buf;
253    if(buf == NULL){
254         return -1;
255   }
256 
257   size = sizeof(mag_data_t);
258   if(len < size){
259         return -1;
260   }
261 
262   buffer[0] = READ_MEASUREMENT_CMD;
263   ret = sensor_i2c_single_write(&ST480_ctx, buffer, 1, I2C_OP_RETRIES);
264   if(unlikely(ret)){
265 	  return ret;
266   }
267 
268   ret = sensor_i2c_single_read(&ST480_ctx, buffer, 9, I2C_OP_RETRIES);
269   if(unlikely(ret)){
270 	  return ret;
271   }
272 
273   if (!((buffer[0]>>4) & 0X01)) {
274 
275 	  for(i=0; i<3; i++)
276   	  {
277     	pnRawData[i]=(int16_t)((((uint16_t)buffer[2*i + 3]) << 8) | ((uint16_t)buffer[2*i + 4]));
278   	  }
279   }
280 
281 
282   pdata->data[0] =(int32_t)(pnRawData[0] * ST480_MAG_XY_SENSITIVITY_FOR_48GA / 10);
283   pdata->data[1] =(int32_t)(pnRawData[1] * ST480_MAG_XY_SENSITIVITY_FOR_48GA / 10);
284   pdata->data[2] =(int32_t)(pnRawData[2] * ST480_MAG_Z_SENSITIVITY_FOR_48GA / 10);
285 
286 
287   pdata->timestamp = aos_now_ms();
288 
289   //set mode config
290   buffer[0] = SINGLE_MEASUREMENT_MODE_CMD;
291   ret = sensor_i2c_single_write(&ST480_ctx, buffer, 1, I2C_OP_RETRIES);
292   if(unlikely(ret)){
293 		return ret;
294   }
295 
296   ret = sensor_i2c_single_read(&ST480_ctx, buffer, 1, I2C_OP_RETRIES);
297   if(unlikely(ret)){
298 		return ret;
299   }
300 
301   return (int)size;
302 }
303 
304 
drv_mag_sen_st480_ioctl(int cmd,unsigned long arg)305 static int drv_mag_sen_st480_ioctl(int cmd, unsigned long arg)
306 {
307     int ret = 0;
308 
309     switch(cmd){
310         case SENSOR_IOCTL_ODR_SET:{
311             ret = drv_mag_sen_st480_set_odr(&ST480_ctx, arg);
312             if(unlikely(ret)){
313                 return -1;
314             }
315         }break;
316         case SENSOR_IOCTL_RANGE_SET:{
317             ret = drv_mag_sen_st480_set_range(&ST480_ctx, arg);
318             if(unlikely(ret)){
319                 return -1;
320             }
321         }break;
322         case SENSOR_IOCTL_SET_POWER:{
323             ret = drv_mag_sen_st480_set_power_mode(&ST480_ctx, arg);
324             if(unlikely(ret)){
325                 return -1;
326             }
327         }break;
328         case SENSOR_IOCTL_GET_INFO:{
329             /* fill the dev info here */
330             dev_sensor_info_t *info = (dev_sensor_info_t *)arg;
331             info->model = "ST480";
332             info->range_max = 48;
333             info->range_min = 48;
334             info->unit = mGauss;
335         }break;
336 
337        default:break;
338     }
339 
340     return 0;
341 }
342 
drv_mag_sen_st480_init(void)343 int drv_mag_sen_st480_init(void){
344     int ret = 0;
345     sensor_obj_t sensor;
346     memset(&sensor, 0, sizeof(sensor));
347     /* fill the sensor obj parameters here */
348     sensor.io_port    = I2C_PORT;
349     sensor.tag        = TAG_DEV_MAG;
350     sensor.path       = dev_mag_path;
351     sensor.open       = drv_mag_sen_st480_open;
352     sensor.close      = drv_mag_sen_st480_close;
353     sensor.read       = drv_mag_sen_st480_read;
354     sensor.write      = NULL;
355     sensor.ioctl      = drv_mag_sen_st480_ioctl;
356     sensor.irq_handle = drv_mag_sen_st480_irq_handle;
357 
358 
359     ret = sensor_create_obj(&sensor);
360     if(unlikely(ret)){
361         return -1;
362     }
363 
364     ret = drv_mag_sen_st480_validate_id(&ST480_ctx, I_AM_ST480);
365     if(unlikely(ret)){
366         return -1;
367     }
368 
369     ret = drv_mag_sen_st480_set_default_config(&ST480_ctx);
370     if(unlikely(ret)){
371         return -1;
372     }
373 
374     /* update the phy sensor info to sensor hal */
375     LOG("%s %s successfully \n", SENSOR_STR, __func__);
376     return 0;
377 }
378 
379 SENSOR_DRV_ADD(drv_mag_sen_st480_init);
380 
381