Contiki-NG
mpu-9250-sensor.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018, Texas Instruments Incorporated - http://www.ti.com/
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holder nor the names of its
14  * contributors may be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28  * OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 /**
31  * \addtogroup sensortag-mpu
32  * @{
33  *
34  * \file
35  * Driver for the Sensortag Invensense MPU9250 motion processing unit
36  * \author
37  * Edvard Pettersen <e.pettersen@ti.com>
38  */
39 /*---------------------------------------------------------------------------*/
40 #include "contiki.h"
41 #include "lib/sensors.h"
42 #include "sys/rtimer.h"
43 #include "dev/i2c-arch.h"
44 /*---------------------------------------------------------------------------*/
45 #include "board-conf.h"
46 #include "mpu-9250-sensor.h"
47 /*---------------------------------------------------------------------------*/
48 #include <Board.h>
49 
50 #include <ti/devices/DeviceFamily.h>
51 #include DeviceFamily_constructPath(driverlib/cpu.h)
52 
53 #include <ti/drivers/PIN.h>
54 #include <ti/drivers/I2C.h>
55 /*---------------------------------------------------------------------------*/
56 #include <stdint.h>
57 #include <string.h>
58 #include <stdio.h>
59 #include <math.h>
60 /*---------------------------------------------------------------------------*/
61 #define DEBUG 0
62 #if DEBUG
63 #define PRINTF(...) printf(__VA_ARGS__)
64 #else
65 #define PRINTF(...)
66 #endif
67 /*---------------------------------------------------------------------------*/
68 /*
69  * Disable the entire file if sensors are disabled, as it could potentially
70  * create compile errors with missing defines from either the Board file or
71  * configuration defines.
72  */
73 #if BOARD_SENSORS_ENABLE
74 /*---------------------------------------------------------------------------*/
75 #ifndef Board_MPU9250_ADDR
76 #error "Board file doesn't define I2C address Board_MPU9250_ADDR"
77 #endif
78 #ifndef Board_MPU9250_MAG_ADDR
79 #error "Board file doesn't define I2C address Board_MPU9250_MAG_ADDR"
80 #endif
81 
82 /* Sensor I2C address */
83 #define MPU_9250_I2C_ADDRESS Board_MPU9250_ADDR
84 #define MPU_9250_MAG_I2C_ADDRESS Board_MPU9250_MAG_ADDR
85 /*-------------a--------------------------------------------------------------*/
86 /* Self Test Registers */
87 #define REG_SELF_TEST_X_GYRO 0x00 /* R/W */
88 #define REG_SELF_TEST_Y_GYRO 0x01 /* R/W */
89 #define REG_SELF_TEST_Z_GYRO 0x02 /* R/W */
90 #define REG_SELF_TEST_X_ACCEL 0x0D /* R/W */
91 #define REG_SELF_TEST_Z_ACCEL 0x0E /* R/W */
92 #define REG_SELF_TEST_Y_ACCEL 0x0F /* R/W */
93 /*---------------------------------------------------------------------------*/
94 /* Axis Registers */
95 #define REG_XG_OFFSET_H 0x13 /* R/W */
96 #define REG_XG_OFFSET_L 0x14 /* R/W */
97 #define REG_YG_OFFSET_H 0x15 /* R/W */
98 #define REG_YG_OFFSET_L 0x16 /* R/W */
99 #define REG_ZG_OFFSET_H 0x17 /* R/W */
100 #define REG_ZG_OFFSET_L 0x18 /* R/W */
101 /*---------------------------------------------------------------------------*/
102 /* Control Registers */
103 #define REG_SMPLRT_DIV 0x19 /* R/W */
104 #define REG_CONFIG 0x1A /* R/W */
105 #define REG_GYRO_CONFIG 0x1B /* R/W */
106 #define REG_ACCEL_CONFIG 0x1C /* R/W */
107 #define REG_ACCEL_CONFIG_2 0x1D /* R/W */
108 #define REG_LP_ACCEL_ODR 0x1E /* R/W */
109 #define REG_WOM_THR 0x1F /* R/W */
110 #define REG_FIFO_EN 0x23 /* R/W */
111 /*---------------------------------------------------------------------------*/
112 /*
113  * Registers 0x24 - 0x36 are not applicable to the SensorTag HW configuration
114  * (IC2 Master)
115  */
116 #define REG_INT_PIN_CFG 0x37 /* R/W */
117 #define REG_INT_ENABLE 0x38 /* R/W */
118 #define REG_INT_STATUS 0x3A /* R */
119 #define REG_ACCEL_XOUT_H 0x3B /* R */
120 #define REG_ACCEL_XOUT_L 0x3C /* R */
121 #define REG_ACCEL_YOUT_H 0x3D /* R */
122 #define REG_ACCEL_YOUT_L 0x3E /* R */
123 #define REG_ACCEL_ZOUT_H 0x3F /* R */
124 #define REG_ACCEL_ZOUT_L 0x40 /* R */
125 #define REG_TEMP_OUT_H 0x41 /* R */
126 #define REG_TEMP_OUT_L 0x42 /* R */
127 #define REG_GYRO_XOUT_H 0x43 /* R */
128 #define REG_GYRO_XOUT_L 0x44 /* R */
129 #define REG_GYRO_YOUT_H 0x45 /* R */
130 #define REG_GYRO_YOUT_L 0x46 /* R */
131 #define REG_GYRO_ZOUT_H 0x47 /* R */
132 #define REG_GYRO_ZOUT_L 0x48 /* R */
133 /*---------------------------------------------------------------------------*/
134 /*
135  * Registers 0x49 - 0x60 are not applicable to the SensorTag HW configuration
136  * (external sensor data)
137  *
138  * Registers 0x63 - 0x67 are not applicable to the SensorTag HW configuration
139  * (I2C master)
140  */
141 #define REG_SIG_PATH_RST 0x68 /* R/W */
142 #define REG_ACC_INTEL_CTRL 0x69 /* R/W */
143 #define REG_USER_CTRL 0x6A /* R/W */
144 #define REG_PWR_MGMT_1 0x6B /* R/W */
145 #define REG_PWR_MGMT_2 0x6C /* R/W */
146 #define REG_FIFO_COUNT_H 0x72 /* R/W */
147 #define REG_FIFO_COUNT_L 0x73 /* R/W */
148 #define REG_FIFO_R_W 0x74 /* R/W */
149 #define REG_WHO_AM_I 0x75 /* R/W */
150 /*---------------------------------------------------------------------------*/
151 /* Masks is mpuConfig valiable */
152 #define ACC_CONFIG_MASK 0x38
153 #define GYRO_CONFIG_MASK 0x07
154 /*---------------------------------------------------------------------------*/
155 /* Values PWR_MGMT_1 */
156 #define PWR_MGMT_1_VAL_MPU_SLEEP 0x4F /* Sleep + stop all clocks */
157 #define PWR_MGMT_1_VAL_MPU_WAKE_UP 0x09 /* Disable temp. + intern osc */
158 /*---------------------------------------------------------------------------*/
159 /* Values PWR_MGMT_2 */
160 #define PWR_MGMT_2_VAL_ALL_AXES 0x3F
161 #define PWR_MGMT_2_VAL_GYRO_AXES 0x07
162 #define PWR_MGMT_2_VAL_ACC_AXES 0x38
163 /*---------------------------------------------------------------------------*/
164 /* Output data rates */
165 #define INV_LPA_0_3125HZ 0
166 #define INV_LPA_0_625HZ 1
167 #define INV_LPA_1_25HZ 2
168 #define INV_LPA_2_5HZ 3
169 #define INV_LPA_5HZ 4
170 #define INV_LPA_10HZ 5
171 #define INV_LPA_20HZ 6
172 #define INV_LPA_40HZ 7
173 #define INV_LPA_80HZ 8
174 #define INV_LPA_160HZ 9
175 #define INV_LPA_320HZ 10
176 #define INV_LPA_640HZ 11
177 #define INV_LPA_STOPPED 255
178 /*---------------------------------------------------------------------------*/
179 /* Bit values */
180 #define BIT_ANY_RD_CLR 0x10
181 #define BIT_RAW_RDY_EN 0x01
182 #define BIT_WOM_EN 0x40
183 #define BIT_LPA_CYCLE 0x20
184 #define BIT_STBY_XA 0x20
185 #define BIT_STBY_YA 0x10
186 #define BIT_STBY_ZA 0x08
187 #define BIT_STBY_XG 0x04
188 #define BIT_STBY_YG 0x02
189 #define BIT_STBY_ZG 0x01
190 #define BIT_STBY_XYZA (BIT_STBY_XA | BIT_STBY_YA | BIT_STBY_ZA)
191 #define BIT_STBY_XYZG (BIT_STBY_XG | BIT_STBY_YG | BIT_STBY_ZG)
192 /*---------------------------------------------------------------------------*/
193 static PIN_Config mpu_9250_pin_table[] = {
194  Board_MPU_INT | PIN_INPUT_EN | PIN_PULLDOWN | PIN_HYSTERESIS,
195  Board_MPU_POWER | PIN_GPIO_OUTPUT_EN | PIN_DRVSTR_MAX | PIN_GPIO_LOW,
196  PIN_TERMINATE
197 };
198 
199 static PIN_State pin_state;
200 static PIN_Handle pin_handle;
201 static I2C_Handle i2c_handle;
202 
203 /*---------------------------------------------------------------------------*/
204 typedef struct {
205  volatile MPU_9250_SENSOR_STATUS status;
206  volatile MPU_9250_SENSOR_TYPE type;
207  MPU_9250_SENSOR_ACC_RANGE acc_range;
208 } MPU_9250_Object;
209 
210 static MPU_9250_Object mpu_9250;
211 /*---------------------------------------------------------------------------*/
212 /* 3 16-byte words for all sensor readings */
213 #define SENSOR_DATA_BUF_SIZE 3
214 /* Data sizes */
215 #define DATA_SIZE 6
216 /*---------------------------------------------------------------------------*/
217 /*
218  * Wait SENSOR_BOOT_DELAY ticks for the sensor to boot and
219  * SENSOR_STARTUP_DELAY for readings to be ready
220  * Gyro is a little slower than Acc
221  */
222 #define SENSOR_BOOT_DELAY 8
223 #define SENSOR_STARTUP_DELAY 5
224 
225 static struct ctimer startup_timer;
226 /*---------------------------------------------------------------------------*/
227 
228 /*
229  * Wait timeout in rtimer ticks. This is just a random low number, since the
230  * first time we read the sensor status, it should be ready to return data
231  */
232 #define READING_WAIT_TIMEOUT 10
233 /*---------------------------------------------------------------------------*/
234 /* Code in flash, cache disabled: 7 cycles per loop */
235 /* ui32Count = [delay in us] * [CPU clock in MHz] / [cycles per loop] */
236 #define delay_ms(ms) CPUdelay((ms) * 1000 * 48 / 7)
237 /*---------------------------------------------------------------------------*/
238 /**
239  * \brief Initialize the MPU-9250 sensor driver.
240  * \return true if I2C operation successful; else, return false.
241  */
242 static bool
244 {
245  pin_handle = PIN_open(&pin_state, mpu_9250_pin_table);
246  if(pin_handle == NULL) {
247  return false;
248  }
249 
250  mpu_9250.type = MPU_9250_SENSOR_TYPE_NONE;
251  mpu_9250.status = MPU_9250_SENSOR_STATUS_DISABLED;
252  mpu_9250.acc_range = MPU_9250_SENSOR_ACC_RANGE_ARG;
253 
254  return true;
255 }
256 /*---------------------------------------------------------------------------*/
257 /**
258  * \brief Place the sensor in low-power mode.
259  */
260 static void
262 {
263  {
264  uint8_t all_axes_data[] = { REG_PWR_MGMT_2, PWR_MGMT_2_VAL_ALL_AXES };
265  i2c_arch_write(i2c_handle, MPU_9250_I2C_ADDRESS, all_axes_data, sizeof(all_axes_data));
266  }
267  {
268  uint8_t mpu_sleep_data[] = { REG_PWR_MGMT_1, PWR_MGMT_1_VAL_MPU_SLEEP };
269  i2c_arch_write(i2c_handle, MPU_9250_I2C_ADDRESS, mpu_sleep_data, sizeof(mpu_sleep_data));
270  }
271 }
272 /*---------------------------------------------------------------------------*/
273 /**
274  * \brief Wakeup the sensor from low-power mode.
275  */
276 static void
278 {
279  {
280  uint8_t mpu_wakeup_data[] = { REG_PWR_MGMT_1, PWR_MGMT_1_VAL_MPU_WAKE_UP };
281  i2c_arch_write(i2c_handle, MPU_9250_I2C_ADDRESS, mpu_wakeup_data, sizeof(mpu_wakeup_data));
282  }
283  {
284  /* All axis initially disabled */
285  uint8_t all_axes_data[] = { REG_PWR_MGMT_2, PWR_MGMT_2_VAL_ALL_AXES };
286  i2c_arch_write(i2c_handle, MPU_9250_I2C_ADDRESS, all_axes_data, sizeof(all_axes_data));
287  }
288  {
289  /* Restore the range */
290  uint8_t accel_cfg_data[] = { REG_ACCEL_CONFIG, mpu_9250.acc_range };
291  i2c_arch_write(i2c_handle, MPU_9250_I2C_ADDRESS, accel_cfg_data, sizeof(accel_cfg_data));
292  }
293  {
294  /* Clear interrupts */
295  uint8_t int_status_data[] = { REG_INT_STATUS };
296  uint8_t dummy;
297  i2c_arch_write_read(i2c_handle, MPU_9250_I2C_ADDRESS, int_status_data, sizeof(int_status_data), &dummy, 1);
298  }
299 }
300 /*---------------------------------------------------------------------------*/
301 static void
302 sensor_set_acc_range(MPU_9250_SENSOR_ACC_RANGE acc_range)
303 {
304  /* Apply the range */
305  uint8_t accel_cfg_data[] = { REG_ACCEL_CONFIG, acc_range };
306  i2c_arch_write(i2c_handle, MPU_9250_I2C_ADDRESS, accel_cfg_data, sizeof(accel_cfg_data));
307 }
308 /*---------------------------------------------------------------------------*/
309 static void
310 sensor_set_axes(MPU_9250_SENSOR_TYPE sensor_type)
311 {
312  uint8_t _data[] = { REG_PWR_MGMT_2, ~(uint8_t)sensor_type };
313  i2c_arch_write(i2c_handle, MPU_9250_I2C_ADDRESS, _data, sizeof(_data));
314 }
315 /*---------------------------------------------------------------------------*/
316 static void
317 convert_to_le(uint8_t *data, uint8_t len)
318 {
319  int i;
320  for(i = 0; i < len; i += 2) {
321  uint8_t tmp;
322  tmp = data[i];
323  data[i] = data[i + 1];
324  data[i + 1] = tmp;
325  }
326 }
327 /*---------------------------------------------------------------------------*/
328 /**
329  * \brief Check whether a data or wake on motion interrupt has occurred.
330  * \return Return the interrupt status.
331  *
332  * This driver does not use interrupts, however this function allows
333  * us to determine whether a new sensor reading is available.
334  */
335 static bool
337 {
338  uint8_t int_status_data[] = { REG_INT_STATUS };
339  const bool spi_ok = i2c_arch_write_read(i2c_handle, MPU_9250_I2C_ADDRESS, int_status_data, sizeof(int_status_data), int_status, 1);
340 
341  return spi_ok && (*int_status != 0);
342 }
343 /*---------------------------------------------------------------------------*/
344 /**
345  * \brief Read data from the accelerometer, total of 3 words (X, Y, Z).
346  * \return true if a valid reading could be taken; otherwise, false.
347  */
348 static bool
349 acc_read(uint8_t int_status, uint16_t *data)
350 {
351  if(!(int_status & BIT_RAW_RDY_EN)) {
352  return false;
353  }
354 
355  /* Burst read of all accelerometer values */
356  uint8_t accel_xout_h[] = { REG_ACCEL_XOUT_H };
357  bool spi_ok = i2c_arch_write_read(i2c_handle, MPU_9250_I2C_ADDRESS, accel_xout_h, sizeof(accel_xout_h), data, DATA_SIZE);
358  if(!spi_ok) {
359  return false;
360  }
361 
362  convert_to_le((uint8_t *)data, DATA_SIZE);
363 
364  return true;
365 }
366 /*---------------------------------------------------------------------------*/
367 /**
368  * \brief Read data from the accelerometer, total of 3 words (X, Y, Z).
369  * \return true if a valid reading could be taken; otherwise, false.
370  */
371 static bool
372 gyro_read(uint8_t int_status, uint16_t *data)
373 {
374  if(!(int_status & BIT_RAW_RDY_EN)) {
375  return false;
376  }
377 
378  /* Burst read of all accelerometer values */
379  uint8_t gyro_xout_h[] = { REG_GYRO_XOUT_H };
380  bool spi_ok = i2c_arch_write_read(i2c_handle, MPU_9250_I2C_ADDRESS, gyro_xout_h, sizeof(gyro_xout_h), data, DATA_SIZE);
381  if(!spi_ok) {
382  return false;
383  }
384 
385  convert_to_le((uint8_t *)data, DATA_SIZE);
386 
387  return true;
388 }
389 /*---------------------------------------------------------------------------*/
390 /**
391  * \brief Convert accelerometer raw reading to a value in G.
392  * \param raw_data The raw accelerometer reading.
393  * \return The converted value.
394  */
395 static int32_t
396 acc_convert(int32_t raw_data)
397 {
398  switch(mpu_9250.acc_range) {
399  case MPU_9250_SENSOR_ACC_RANGE_2G: return raw_data * 100 * 2 / 32768;
400  case MPU_9250_SENSOR_ACC_RANGE_4G: return raw_data * 100 * 4 / 32768;
401  case MPU_9250_SENSOR_ACC_RANGE_8G: return raw_data * 100 * 8 / 32768;
402  case MPU_9250_SENSOR_ACC_RANGE_16G: return raw_data * 100 * 16 / 32768;
403  }
404  return 0;
405 }
406 /*---------------------------------------------------------------------------*/
407 /**
408  * \brief Convert gyro raw reading to a value in deg/sec.
409  * \param raw_data The raw accelerometer reading.
410  * \return The converted value.
411  */
412 static int32_t
413 gyro_convert(int32_t raw_data)
414 {
415  /* calculate rotation, unit deg/s, range -250, +250 */
416  return raw_data * 100 * 500 / 65536;
417 }
418 /*---------------------------------------------------------------------------*/
419 static void
420 notify_ready_cb(void *unused)
421 {
422  (void)unused;
423 
424  mpu_9250.status = MPU_9250_SENSOR_STATUS_READY;
425  sensors_changed(&mpu_9250_sensor);
426 }
427 /*---------------------------------------------------------------------------*/
428 static void
429 initialise_cb(void *unused)
430 {
431  (void)unused;
432 
433  if(mpu_9250.type == MPU_9250_SENSOR_TYPE_NONE) {
434  return;
435  }
436 
437  i2c_handle = i2c_arch_acquire(Board_I2C1);
438 
439  if(!i2c_handle) {
440  return;
441  }
442 
443  /* Wake up the sensor */
444  sensor_wakeup();
445 
446  /* Configure the accelerometer range */
447  if((mpu_9250.type & MPU_9250_SENSOR_TYPE_ACC) != 0) {
448  sensor_set_acc_range(mpu_9250.acc_range);
449  }
450 
451  /* Enable gyro + accelerometer readout */
452  sensor_set_axes(mpu_9250.type);
453  delay_ms(10);
454 
455  i2c_arch_release(i2c_handle);
456 
457  ctimer_set(&startup_timer, SENSOR_STARTUP_DELAY, notify_ready_cb, NULL);
458 }
459 /*---------------------------------------------------------------------------*/
460 /**
461  * \brief Returns a reading from the sensor.
462  * \param type MPU_9250_SENSOR_TYPE_ACC_[XYZ] or
463  * MPU_9250_SENSOR_TYPE_GYRO_[XYZ].
464  * \return Centi-G (ACC) or centi-Deg/Sec (Gyro).
465  */
466 static int
467 value(int type)
468 {
469  if(mpu_9250.status == MPU_9250_SENSOR_STATUS_DISABLED) {
470  PRINTF("MPU: Sensor Disabled\n");
471  return MPU_9250_READING_ERROR;
472  }
473 
474  if(mpu_9250.type == MPU_9250_SENSOR_TYPE_NONE) {
475  return MPU_9250_READING_ERROR;
476  }
477 
478  i2c_handle = i2c_arch_acquire(Board_I2C1);
479 
480  if(!i2c_handle) {
481  return MPU_9250_READING_ERROR;
482  }
483 
484  uint8_t int_status = 0;
485  const rtimer_clock_t t0 = RTIMER_NOW();
486  while(!sensor_data_ready(&int_status)) {
487  if(!(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + READING_WAIT_TIMEOUT))) {
488  i2c_arch_release(i2c_handle);
489  return MPU_9250_READING_ERROR;
490  }
491  }
492 
493  uint16_t sensor_value[SENSOR_DATA_BUF_SIZE];
494  memset(sensor_value, 0, sizeof(sensor_value));
495 
496  /* Read accel data */
497  if((type & MPU_9250_SENSOR_TYPE_ACC) != 0) {
498 
499  if(!acc_read(int_status, sensor_value)) {
500  i2c_arch_release(i2c_handle);
501  return MPU_9250_READING_ERROR;
502  }
503 
504  i2c_arch_release(i2c_handle);
505 
506  PRINTF("MPU: ACC = 0x%04x 0x%04x 0x%04x = ",
507  sensor_value[0], sensor_value[1], sensor_value[2]);
508 
509  /* Convert */
510  switch(type) {
511  case MPU_9250_SENSOR_TYPE_ACC_X: return acc_convert(sensor_value[0]);
512  case MPU_9250_SENSOR_TYPE_ACC_Y: return acc_convert(sensor_value[1]);
513  case MPU_9250_SENSOR_TYPE_ACC_Z: return acc_convert(sensor_value[2]);
514  default: return MPU_9250_READING_ERROR;
515  }
516 
517  /* Read gyro data */
518  } else if((type & MPU_9250_SENSOR_TYPE_GYRO) != 0) {
519 
520  if(!gyro_read(int_status, sensor_value)) {
521  i2c_arch_release(i2c_handle);
522  return MPU_9250_READING_ERROR;
523  }
524 
525  i2c_arch_release(i2c_handle);
526 
527  PRINTF("MPU: Gyro = 0x%04x 0x%04x 0x%04x = ",
528  sensor_value[0], sensor_value[1], sensor_value[2]);
529 
530  /* Convert */
531  switch(type) {
532  case MPU_9250_SENSOR_TYPE_GYRO_X: return gyro_convert(sensor_value[0]);
533  case MPU_9250_SENSOR_TYPE_GYRO_Y: return gyro_convert(sensor_value[1]);
534  case MPU_9250_SENSOR_TYPE_GYRO_Z: return gyro_convert(sensor_value[2]);
535  default: return MPU_9250_READING_ERROR;
536  }
537 
538  /* Invalid sensor type */
539  } else {
540  PRINTF("MPU: Invalid type\n");
541  return MPU_9250_READING_ERROR;
542  }
543 }
544 /*---------------------------------------------------------------------------*/
545 /**
546  * \brief Configuration function for the MPU9250 sensor.
547  * \param type Activate, enable or disable the sensor. See below.
548  * \param enable Enable or disable sensor.
549  * When type == SENSORS_HW_INIT we turn on the hardware.
550  * When type == SENSORS_ACTIVE and enable==1 we enable the sensor.
551  * When type == SENSORS_ACTIVE and enable==0 we disable the sensor.
552  */
553 static int
554 configure(int type, int enable)
555 {
556  /* Mask enable */
557  const MPU_9250_SENSOR_TYPE enable_type = enable & MPU_9250_SENSOR_TYPE_ALL;
558 
559  switch(type) {
560  case SENSORS_HW_INIT:
561  if(sensor_init()) {
562  mpu_9250.status = MPU_9250_SENSOR_STATUS_ENABLED;
563  } else {
564  mpu_9250.status = MPU_9250_SENSOR_STATUS_DISABLED;
565  }
566  break;
567 
568  case SENSORS_ACTIVE:
569  if(enable_type != MPU_9250_SENSOR_TYPE_NONE) {
570  PRINTF("MPU: Enabling\n");
571 
572  mpu_9250.type = enable_type;
573  mpu_9250.status = MPU_9250_SENSOR_STATUS_BOOTING;
574 
575  PIN_setOutputValue(pin_handle, Board_MPU_POWER, 1);
576 
577  ctimer_set(&startup_timer, SENSOR_BOOT_DELAY, initialise_cb, NULL);
578  } else {
579  PRINTF("MPU: Disabling\n");
580 
581  ctimer_stop(&startup_timer);
582 
583  if(PIN_getOutputValue(Board_MPU_POWER)) {
584  i2c_handle = i2c_arch_acquire(Board_I2C1);
585 
586  if(!i2c_handle) {
587  PIN_setOutputValue(pin_handle, Board_MPU_POWER, 0);
588 
589  return MPU_9250_SENSOR_STATUS_DISABLED;
590  }
591 
592  sensor_sleep();
593 
594  i2c_arch_release(i2c_handle);
595 
596  PIN_setOutputValue(pin_handle, Board_MPU_POWER, 0);
597  }
598 
599  mpu_9250.type = MPU_9250_SENSOR_TYPE_NONE;
600  mpu_9250.status = MPU_9250_SENSOR_STATUS_DISABLED;
601  }
602  break;
603 
604  default:
605  break;
606  }
607  return mpu_9250.status;
608 }
609 /*---------------------------------------------------------------------------*/
610 /**
611  * \brief Returns the status of the sensor
612  * \param type SENSORS_ACTIVE or SENSORS_READY
613  * \return 1 if the sensor is enabled, else 0.
614  */
615 static int
616 status(int type)
617 {
618  switch(type) {
619  case SENSORS_ACTIVE:
620  case SENSORS_READY:
621  return mpu_9250.status;
622 
623  default:
624  return MPU_9250_SENSOR_STATUS_DISABLED;
625  }
626 }
627 /*---------------------------------------------------------------------------*/
628 SENSORS_SENSOR(mpu_9250_sensor, "MPU9250", value, configure, status);
629 /*---------------------------------------------------------------------------*/
630 #endif /* BOARD_SENSORS_ENABLE */
631 /*---------------------------------------------------------------------------*/
632 /** @} */
void ctimer_stop(struct ctimer *c)
Stop a pending callback timer.
Definition: ctimer.c:149
static bool sensor_init(void)
Initialize the MPU-9250 sensor driver.
static int value(int type)
Returns a reading from the sensor.
MPU_9250_SENSOR_TYPE
static void sensor_sleep(void)
Place the sensor in low-power mode.
static int32_t acc_convert(int32_t raw_data)
Convert accelerometer raw reading to a value in G.
Implementation of the I2C HAL driver for CC13xx/CC26xx.
static bool acc_read(uint8_t int_status, uint16_t *data)
Read data from the accelerometer, total of 3 words (X, Y, Z).
static int status(int type)
Returns the status of the sensor.
bool i2c_arch_write_read(I2C_Handle i2c_handle, uint_least8_t slave_addr, void *wbuf, size_t wcount, void *rbuf, size_t rcount)
Setup and peform an I2C transaction.
Definition: i2c-arch.c:53
static bool i2c_arch_write(I2C_Handle i2c_handle, uint_least8_t slave_addr, void *wbuf, size_t wcount)
Perform a write-only I2C transaction.
Definition: i2c-arch.h:128
static void sensor_wakeup(void)
Wakeup the sensor from low-power mode.
#define RTIMER_NOW()
Get the current clock time.
Definition: rtimer.h:185
static uint8_t int_status(void)
Check whether a data or wake on motion interrupt has occurred.
void i2c_arch_release(I2C_Handle i2c_handle)
Release the I2C Peripheral for other modules to use.
Definition: i2c-arch.c:74
Header file for the real-time timer module.
I2C_Handle i2c_arch_acquire(uint_least8_t index)
Open and lock the I2C Peripheral for use.
Definition: i2c-arch.c:84
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
Definition: ctimer.c:99
static int configure(int type, int enable)
Configuration function for the MPU9250 sensor.
static bool gyro_read(uint8_t int_status, uint16_t *data)
Read data from the accelerometer, total of 3 words (X, Y, Z).
Header file with definitions related to the sensors on the Sensortags.
static int32_t gyro_convert(int32_t raw_data)
Convert gyro raw reading to a value in deg/sec.
static bool sensor_data_ready(uint8_t *int_status)
Check whether a data or wake on motion interrupt has occurred.