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