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