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 ST350MC_DEBUG*/
15 
16 #ifdef ST350MC_DEBUG
17 #define ST350_LOG  LOG
18 #else
19 #define ST350_LOG
20 #endif
21 
22 
23 #define ST350MC_REGISTER_SETTING_TOTAL   	 5
24 #define ST350MC_OPERATION_TYPES_REG_TOTAL 	 4
25 
26 
27 #define ST350_I2C_ADDR2                   0x0D
28 #define ST350_I2C_ADDR_TRANS(n)           ((n)<<1)
29 #define ST350_I2C_ADDR                    ST350_I2C_ADDR_TRANS(ST350_I2C_ADDR2)
30 #define ST350_BIT(x)                      (x)
31 
32 #define I_AM_ST350                        0x53
33 #define ST350_MAG_WHO_AM_I_REG            0x00
34 
35 
36 #define ST350MC_REG_MINFO				0x01
37 #define ST350MC_REG_STAT1				0x02
38 #define ST350MC_REG_DATAX_L				0x03
39 #define ST350MC_REG_DATAX_H		    	0x04
40 #define ST350MC_REG_DATAY_L				0x05
41 #define ST350MC_REG_DATAY_H		    	0x06
42 #define ST350MC_REG_DATAZ_L				0x07
43 #define ST350MC_REG_DATAZ_H		    	0x08
44 #define ST350MC_REG_STAT2				0x09
45 #define ST350MC_REG_CNTRL1				0x0A
46 #define ST350MC_REG_CNTRL2				0x0B
47 #define ST350MC_REG_STCR				0x0C
48 #define ST350MC_REG_CNTRL3				0x0D
49 #define ST350MC_REG_TEMP_L				0x1C
50 #define ST350MC_REG_TEMP_H		  		0x1D
51 
52 #define	ST350MC_REG_AVGCNTL				0x41
53 #define	ST350MC_REG_DSM1				0x6c
54 
55 #define ST350MC_REG_X_GAIN_CNTL			0x50
56 #define ST350MC_REG_Y_GAIN_CNTL			0x52
57 #define ST350MC_REG_Z_GAIN_CNTL			0x54
58 #define ST350MC_REG_MHZ_CLK_TUNING  	0x56
59 #define ST350MC_REG_ANALOG_TEST_CTL3	0x72
60 #define ST350MC_REG_ANALOG_TEST_CTL7	0x76
61 
62 #define ST350MC_REG_SSR             	0x42
63 #define ST350MC_REG_CTR             	0x40
64 #define ST350MC_REG_BTR             	0x57
65 
66 #define ST350_MAG_SENSITIVITY_FOR_FS_20GA  3
67 #define UTTOUG   						10000
68 #define UTTOMG   						10
69 
70 typedef enum
71 {
72 ST350MC_SINGLE_MEASURE,
73 ST350MC_STANDBY,
74 ST350MC_SUSPEND
75 }st350_operation_mode_e;
76 
77 
78 typedef enum
79 {
80   ST350MC_NORMAL,
81   ST350MC_HIGH_PRECISION,
82   ST350MC_HIGH_SPEED,
83   ST350MC_LOW_POWER
84 
85 }st350mc_operation_types_e;
86 
87 
88 i2c_dev_t ST350_ctx = {
89 	.port = 2,
90     .config.address_width = 8,
91     .config.freq = 400000,
92     .config.dev_addr = ST350_I2C_ADDR,
93 };
94 
drv_mag_sen_st350_soft_reset(i2c_dev_t * drv)95 UNUSED static int drv_mag_sen_st350_soft_reset(i2c_dev_t* drv)
96 {
97     int ret = 0;
98     uint8_t value = 0x1;
99     ret = sensor_i2c_write(drv, ST350MC_REG_CNTRL2, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
100     if(unlikely(ret)){
101         return -1;
102     }
103     return 0;
104 }
105 
106 
drv_mag_sen_st350_validate_id(i2c_dev_t * drv,uint8_t id_value)107 static int drv_mag_sen_st350_validate_id(i2c_dev_t* drv, uint8_t id_value)
108 {
109     uint8_t value = 0x00;
110     int ret = 0, i = 3;
111 
112     (void)ret;
113     if(drv == NULL){
114         return -1;
115     }
116 
117 	do{
118 		ret = sensor_i2c_read(drv, ST350_MAG_WHO_AM_I_REG, &value, I2C_DATA_LEN, I2C_OP_RETRIES);
119 	}while((value != I_AM_ST350) && (i-- > 0));
120 
121 
122     if (id_value != value){
123         return -1;
124     }
125 
126     return 0;
127 }
128 
drv_mag_sen_st350_set_operation_types(i2c_dev_t * drv,st350mc_operation_types_e types)129 static int drv_mag_sen_st350_set_operation_types(i2c_dev_t* drv, st350mc_operation_types_e types)
130 {
131 	uint8_t ST350MCreg[ST350MC_OPERATION_TYPES_REG_TOTAL]  = {0x09,0x41,0x42,0x6C};
132 	uint8_t ST350MCSetRegData[ST350MC_OPERATION_TYPES_REG_TOTAL];
133 	uint8_t data, reg , i;
134 	int ret = 0;
135 
136 
137 	ST350MCSetRegData[0] = 0x02;
138 
139 	ST350MCSetRegData[1] = 0x03;
140 
141 	ST350MCSetRegData[2] = 0x40;
142 
143 	ST350MCSetRegData[3] = 0x05;
144 
145 	switch(types){
146 		case ST350MC_HIGH_PRECISION:
147 
148 		ST350MCSetRegData[3] |= 0x50;
149 		break;
150 
151 		case ST350MC_HIGH_SPEED:
152 
153 		ST350MCSetRegData[3] |= 0x30;
154 		break;
155 
156 		case ST350MC_LOW_POWER:
157 
158 		ST350MCSetRegData[0] |= 0xA0;
159 
160 		ST350MCSetRegData[3] |= 0x30;
161 		break;
162 
163 		case ST350MC_NORMAL:
164 		default:
165 
166 		ST350MCSetRegData[3] |= 0x40;
167 	}
168 
169 	for( i = 0 ; i < ST350MC_OPERATION_TYPES_REG_TOTAL ; i++){
170 		reg = ST350MCreg[i];
171 		data = ST350MCSetRegData[i];
172 
173     	ret = sensor_i2c_write(drv, reg, &data, I2C_DATA_LEN, I2C_OP_RETRIES);
174     	if(unlikely(ret)){
175         return ret;
176     	}
177 
178 #ifdef ST350MC_DEBUG
179 
180 		data =	0x0;
181 
182 		ret = sensor_i2c_read(&ST350_ctx, reg, &data, I2C_DATA_LEN, I2C_OP_RETRIES);
183 		if(unlikely(ret)){
184 			return -1;
185 		}
186 
187 		ST350_LOG("operation types >>>>>0x%x = %x", reg, data);
188 #endif
189 	}
190 
191 	return 0;
192 }
193 
194 
drv_mag_sen_st350_set_operation_mode(i2c_dev_t * drv,st350_operation_mode_e mode)195 static int drv_mag_sen_st350_set_operation_mode(i2c_dev_t* drv, st350_operation_mode_e mode)
196 {
197 
198 	uint8_t data, ret = 0, reg , i;
199 	uint8_t regBuff[2],dataBuff[2];
200 
201 	switch(mode){
202 		case ST350MC_SINGLE_MEASURE:
203 		regBuff[0] = 0x20;
204 		dataBuff[0] = 0;
205 		regBuff[1] = 0x0A;
206 		dataBuff[1] = 1;
207 		break;
208 
209 		case ST350MC_SUSPEND:
210 		regBuff[0] = 0x0A;
211 		dataBuff[0] = 0;
212 		regBuff[1] = 0x20;
213 		dataBuff[1] = 1;
214 		break;
215 
216 		case ST350MC_STANDBY:
217 		default:
218 		regBuff[0] = 0x20;
219 		dataBuff[0] = 0;
220 		regBuff[1] = 0x0A;
221 		dataBuff[1] = 0;
222 	}
223 
224 	for(i = 0; i < 2; i++){
225 		reg = regBuff[i];
226 		data = dataBuff[i];
227 
228     	ret = sensor_i2c_write(drv, reg, &data, I2C_DATA_LEN, I2C_OP_RETRIES);
229     	if(unlikely(ret)){
230         return ret;
231     	}
232 
233 #ifdef ST350MC_DEBUG
234 		data =	0x0;
235 
236 		ret = sensor_i2c_read(&ST350_ctx, reg, &data, I2C_DATA_LEN, I2C_OP_RETRIES);
237 		if(unlikely(ret)){
238 			return -1;
239 		}
240 
241 		ST350_LOG("operation mode >>>>>0x%x = %x", reg, data);
242 #endif
243 	}
244 
245 
246 	return 0;
247 }
248 
249 
drv_mag_sen_st350_set_power_mode(i2c_dev_t * drv,dev_power_mode_e mode)250 static int drv_mag_sen_st350_set_power_mode(i2c_dev_t* drv, dev_power_mode_e mode)
251 {
252 
253     if (mode == DEV_POWER_ON){
254         drv_mag_sen_st350_set_operation_mode(&ST350_ctx, ST350MC_STANDBY);
255 
256     }
257     else{
258         drv_mag_sen_st350_set_operation_mode(&ST350_ctx, ST350MC_SUSPEND);
259     }
260 
261 
262     return 0;
263 }
264 
drv_mag_sen_st350_set_odr(i2c_dev_t * drv,uint8_t odr)265 UNUSED static int drv_mag_sen_st350_set_odr(i2c_dev_t* drv, uint8_t odr)
266 {
267     return 0;
268 }
269 
270 
drv_mag_sen_st350_lowpower_mode(i2c_dev_t * drv,uint8_t lowpower_mode)271 UNUSED static int drv_mag_sen_st350_lowpower_mode(i2c_dev_t* drv, uint8_t lowpower_mode)
272 {
273     int ret = 0;
274 
275     ret = drv_mag_sen_st350_set_operation_types(&ST350_ctx, ST350MC_LOW_POWER);
276     if(unlikely(ret)){
277         return -1;
278     }
279 
280     return 0;
281 }
282 
drv_mag_sen_st350_set_range(i2c_dev_t * drv,uint32_t range)283 UNUSED static int drv_mag_sen_st350_set_range(i2c_dev_t* drv, uint32_t range)
284 {
285 
286     return 0;
287 }
288 
drv_mag_sen_st350_set_default_config(i2c_dev_t * drv)289 static int drv_mag_sen_st350_set_default_config(i2c_dev_t* drv)
290 {
291 	int ret = 0;
292 	uint8_t ST350MCreg[ST350MC_REGISTER_SETTING_TOTAL]  = 		{0x0D,0x56,0x57,0x72,0x76};
293 	uint8_t ST350MCSetRegData[ST350MC_REGISTER_SETTING_TOTAL] = {0x00,0x1F,0x00,0x2B,0x00};
294 
295 	uint8_t data, reg , i;
296 
297 
298 	reg = 0xBA;
299 	data = 0x0;
300 
301 	ret = sensor_i2c_read(&ST350_ctx, reg, &data, I2C_DATA_LEN, I2C_OP_RETRIES);
302     if(unlikely(ret)){
303         return -1;
304     }
305 	else{
306 		if((data == 0x10) || (data == 0xFF)){
307 			ST350MCSetRegData[4] = 0x20;
308 		}
309 	}
310 
311 
312 	for( i = 0 ; i < ST350MC_REGISTER_SETTING_TOTAL ; i++ )
313 	{
314 		reg = ST350MCreg[i];
315 		data = ST350MCSetRegData[i];
316 
317     	ret = sensor_i2c_write(drv, reg, &data, I2C_DATA_LEN, I2C_OP_RETRIES);
318     	if(unlikely(ret)){
319         return ret;
320     	}
321 
322 #ifdef ST350MC_DEBUG
323 		data =	0x0;
324 
325 		ret = sensor_i2c_read(&ST350_ctx, reg, &data, I2C_DATA_LEN, I2C_OP_RETRIES);
326 		if(unlikely(ret)){
327 			return -1;
328 		}
329 
330 		ST350_LOG(">>>>>0x%x = %x", reg, data);
331 #endif
332 	}
333 
334     return 0;
335 }
336 
drv_mag_sen_st350_irq_handle(void)337 static void drv_mag_sen_st350_irq_handle(void)
338 {
339     /* no handle so far */
340 }
341 
342 
drv_mag_sen_st350_dump_reg(void)343 UNUSED static int drv_mag_sen_st350_dump_reg(void)
344 {
345   uint8_t rw_buffer[32] = {0};
346   uint8_t reg_map[] = {
347       0x0D,
348       0x56,
349       0x57,
350       0x72,
351       0x76,
352       0x20,
353       0x0A,
354       0x09,
355       0x41,
356       0x42,
357       0x6C
358   };
359 
360   uint8_t i = 0;
361   uint16_t n = sizeof(reg_map)/sizeof(reg_map[0]);
362   int ret = 0;
363 
364   for(i=0; i<n;i++) {
365     ret = sensor_i2c_read(&ST350_ctx, reg_map[i], &rw_buffer[i],I2C_REG_LEN, I2C_OP_RETRIES);
366     if(unlikely(ret)){
367         return -1;
368     }
369 
370   }
371 
372   return 0;
373 }
374 
375 
376 
drv_mag_sen_st350_open(void)377 static int drv_mag_sen_st350_open(void)
378 {
379     int ret = 0;
380 
381     ret  = drv_mag_sen_st350_set_power_mode(&ST350_ctx, DEV_POWER_ON);
382     if(unlikely(ret)){
383         return -1;
384     }
385 
386 	ret = drv_mag_sen_st350_set_operation_mode(&ST350_ctx, ST350MC_SINGLE_MEASURE);
387     if(unlikely(ret)){
388         return -1;
389     }
390 
391 
392     return 0;
393 
394 }
395 
drv_mag_sen_st350_close(void)396 static int drv_mag_sen_st350_close(void)
397 {
398     int ret = 0;
399 
400     ret  = drv_mag_sen_st350_set_power_mode(&ST350_ctx, DEV_POWER_OFF);
401     if(unlikely(ret)){
402         return -1;
403     }
404     return 0;
405 }
406 
407 
408 
drv_mag_sen_st350_read(void * buf,size_t len)409 static int drv_mag_sen_st350_read(void* buf, size_t len)
410 {
411   int ret = 0, data;
412   size_t size;
413   int16_t pnRawData[3];
414   uint8_t buffer[6];
415   uint8_t i = 0;
416 
417   mag_data_t* pdata = (mag_data_t*)buf;
418   if(buf == NULL){
419         return -1;
420   }
421 
422   size = sizeof(mag_data_t);
423   if(len < size){
424         return -1;
425   }
426 
427 
428   ret = sensor_i2c_read(&ST350_ctx, ST350MC_REG_DATAX_L, buffer, 6, I2C_OP_RETRIES);
429   if(unlikely(ret)){
430         return -1;
431   }
432 
433   for(i=0; i<3; i++)
434   {
435     pnRawData[i]=(int16_t)((((uint16_t)buffer[2*i+1]) << 8) | ((uint16_t)buffer[2*i]));
436   }
437 
438   /*ST350_LOG("raw uint st350 x = %d, y = %d, z = %d", pnRawData[0], pnRawData[1], pnRawData[2]);*/
439 
440   for(i=0; i<3; i++)
441   {
442     pdata->data[i] =(int32_t)(pnRawData[i] * ST350_MAG_SENSITIVITY_FOR_FS_20GA * UTTOMG / 10);
443   }
444 
445 
446   pdata->timestamp = aos_now_ms();
447 
448   data = 1;
449   ret = sensor_i2c_write(&ST350_ctx, 0xa, (uint8_t *)&data, I2C_DATA_LEN, I2C_OP_RETRIES);
450   if(unlikely(ret)){
451 	return ret;
452   }
453 
454   aos_msleep(1);
455 
456   return (int)size;
457 }
458 
459 
drv_mag_sen_st350_ioctl(int cmd,unsigned long arg)460 static int drv_mag_sen_st350_ioctl(int cmd, unsigned long arg)
461 {
462     int ret = 0;
463 
464     switch(cmd){
465         case SENSOR_IOCTL_ODR_SET:{
466 
467         }break;
468         case SENSOR_IOCTL_RANGE_SET:{
469 
470         }break;
471         case SENSOR_IOCTL_SET_POWER:{
472             ret = drv_mag_sen_st350_set_power_mode(&ST350_ctx, arg);
473             if(unlikely(ret)){
474                 return -1;
475             }
476         }break;
477         case SENSOR_IOCTL_GET_INFO:{
478             /* fill the dev info here */
479             dev_sensor_info_t *info = (dev_sensor_info_t *)arg;
480             info->model = "ST350";
481             info->range_max = 25;
482             info->range_min = 20;
483             info->unit = mGauss;
484         }break;
485 
486        default:break;
487     }
488 
489     return 0;
490 }
491 
492 
drv_mag_sen_st350_init(void)493 int drv_mag_sen_st350_init(void){
494     int ret = 0;
495     sensor_obj_t sensor;
496     memset(&sensor, 0, sizeof(sensor));
497     /* fill the sensor obj parameters here */
498     sensor.io_port    = I2C_PORT;
499     sensor.tag        = TAG_DEV_MAG;
500     sensor.path       = dev_mag_path;
501     sensor.open       = drv_mag_sen_st350_open;
502     sensor.close      = drv_mag_sen_st350_close;
503     sensor.read       = drv_mag_sen_st350_read;
504     sensor.write      = NULL;
505     sensor.ioctl      = drv_mag_sen_st350_ioctl;
506     sensor.irq_handle = drv_mag_sen_st350_irq_handle;
507 
508     ret = sensor_create_obj(&sensor);
509     if(unlikely(ret)){
510         return -1;
511     }
512 
513     ret = drv_mag_sen_st350_validate_id(&ST350_ctx, I_AM_ST350);
514     if(unlikely(ret)){
515         return -1;
516     }
517 
518 	ret = drv_mag_sen_st350_set_power_mode(&ST350_ctx, DEV_POWER_ON);
519     if(unlikely(ret)){
520         return -1;
521     }
522 
523     ret = drv_mag_sen_st350_set_default_config(&ST350_ctx);
524     if(unlikely(ret)){
525         return -1;
526     }
527 
528 	aos_msleep(1);
529 
530 	ret = drv_mag_sen_st350_set_operation_types(&ST350_ctx, ST350MC_NORMAL);
531 	if(unlikely(ret)){
532 		return -1;
533 	}
534 
535 	aos_msleep(1);
536 
537 
538     /* update the phy sensor info to sensor hal */
539     LOG("%s %s successfully \n", SENSOR_STR, __func__);
540     return 0;
541 }
542 
543 SENSOR_DRV_ADD(drv_mag_sen_st350_init);
544 
545 
546