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/*---------------------------------------------------------------------------*/
193static 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
199static PIN_State pin_state;
200static PIN_Handle pin_handle;
201static I2C_Handle i2c_handle;
202
203/*---------------------------------------------------------------------------*/
204typedef 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
210static 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
225static 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 */
242static 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 */
260static 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 */
276static 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/*---------------------------------------------------------------------------*/
301static void
302sensor_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/*---------------------------------------------------------------------------*/
309static void
310sensor_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/*---------------------------------------------------------------------------*/
316static void
317convert_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 */
335static 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 */
348static bool
349acc_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 */
371static bool
372gyro_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 */
395static int32_t
396acc_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 */
412static int32_t
413gyro_convert(int32_t raw_data)
414{
415 /* calculate rotation, unit deg/s, range -250, +250 */
416 return raw_data * 100 * 500 / 65536;
417}
418/*---------------------------------------------------------------------------*/
419static void
420notify_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/*---------------------------------------------------------------------------*/
428static void
429initialise_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 */
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 */
466static int
467value(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 */
553static int
554configure(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 */
615static int
616status(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/*---------------------------------------------------------------------------*/
628SENSORS_SENSOR(mpu_9250_sensor, "MPU9250", value, configure, status);
629/*---------------------------------------------------------------------------*/
630#endif /* BOARD_SENSORS_ENABLE */
631/*---------------------------------------------------------------------------*/
632/** @} */
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
I2C_Handle i2c_arch_acquire(uint_least8_t index)
Open and lock the I2C Peripheral for use.
Definition: i2c-arch.c:84
void i2c_arch_release(I2C_Handle i2c_handle)
Release the I2C Peripheral for other modules to use.
Definition: i2c-arch.c:74
void ctimer_stop(struct ctimer *c)
Stop a pending callback timer.
Definition: ctimer.c:149
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
Definition: ctimer.c:99
#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.
static bool gyro_read(uint8_t int_status, uint16_t *data)
Read data from the accelerometer, total of 3 words (X, Y, Z).
static bool sensor_data_ready(uint8_t *int_status)
Check whether a data or wake on motion interrupt has occurred.
static int32_t acc_convert(int32_t raw_data)
Convert accelerometer raw reading to a value in G.
static int value(int type)
Returns a reading from the sensor.
static void sensor_sleep(void)
Place the sensor in low-power mode.
MPU_9250_SENSOR_TYPE
static int status(int type)
Returns the status of the sensor.
static bool acc_read(uint8_t int_status, uint16_t *data)
Read data from the accelerometer, total of 3 words (X, Y, Z).
static void sensor_wakeup(void)
Wakeup the sensor from low-power mode.
static int32_t gyro_convert(int32_t raw_data)
Convert gyro raw reading to a value in deg/sec.
static bool sensor_init(void)
Initialize the MPU-9250 sensor driver.
static int configure(int type, int enable)
Configuration function for the MPU9250 sensor.
@ MPU_9250_SENSOR_TYPE_GYRO_Z
0b000100 = 0x04
@ MPU_9250_SENSOR_TYPE_ACC_X
0b001000 = 0x08
@ MPU_9250_SENSOR_TYPE_ACC_Y
0b010000 = 0x10
@ MPU_9250_SENSOR_TYPE_ACC
0b111000 = 0x38
@ MPU_9250_SENSOR_TYPE_ACC_Z
0b100000 = 0x20
@ MPU_9250_SENSOR_TYPE_NONE
0b000000 = 0x00
@ MPU_9250_SENSOR_TYPE_ALL
0b111111 = 0x3F
@ MPU_9250_SENSOR_TYPE_GYRO_Y
0b000010 = 0x02
@ MPU_9250_SENSOR_TYPE_GYRO_X
0b000001 = 0x01
@ MPU_9250_SENSOR_TYPE_GYRO
0b000111 = 0x07
Implementation of the I2C HAL driver for CC13xx/CC26xx.
Header file for the real-time timer module.
Header file with definitions related to SmartRF06 EB boards.