From 96a098bf74ce1ef752a20e3dcb8f4aa91a072aa1 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Sun, 13 Nov 2011 19:11:06 -0600 Subject: [PATCH] Add code for MPU6050 driver --- flight/PiOS/STM32F4xx/pios_mpu6050.c | 396 ++++++++++++++++++ flight/PiOS/inc/pios_mpu6050.h | 151 +++++++ flight/PiOS/pios.h | 3 + .../OpenPilotOSX.xcodeproj/project.pbxproj | 24 ++ 4 files changed, 574 insertions(+) create mode 100644 flight/PiOS/STM32F4xx/pios_mpu6050.c create mode 100644 flight/PiOS/inc/pios_mpu6050.h diff --git a/flight/PiOS/STM32F4xx/pios_mpu6050.c b/flight/PiOS/STM32F4xx/pios_mpu6050.c new file mode 100644 index 000000000..d50674a26 --- /dev/null +++ b/flight/PiOS/STM32F4xx/pios_mpu6050.c @@ -0,0 +1,396 @@ +/** + ****************************************************************************** + * @addtogroup PIOS PIOS Core hardware abstraction layer + * @{ + * @addtogroup PIOS_MPU6050 MPU6050 Functions + * @brief Deals with the hardware interface to the 3-axis gyro + * @{ + * + * @file pios_mpu050.c + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2011. + * @brief MPU6050 3-axis gyor functions from INS + * @see The GNU Public License (GPL) Version 3 + * + ****************************************************************************** + */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* Project Includes */ +#include "pios.h" + +#if defined(PIOS_INCLUDE_MPU6050) + +/* Global Variables */ + +/* Local Variables */ +#define DEG_TO_RAD (M_PI / 180.0) +static void PIOS_MPU6050_Config(struct pios_mpu6050_cfg const * cfg); +static int32_t PIOS_MPU6050_Read(uint8_t address, uint8_t * buffer, uint8_t len); +static int32_t PIOS_MPU6050_Write(uint8_t address, uint8_t buffer); + +#define PIOS_MPU6050_MAX_DOWNSAMPLE 10 +static int16_t pios_mpu6050_buffer[PIOS_MPU6050_MAX_DOWNSAMPLE * sizeof(struct pios_mpu6050_data)]; +static t_fifo_buffer pios_mpu6050_fifo; + +volatile bool mpu6050_first_read = true; +volatile bool mpu6050_configured = false; +volatile bool mpu6050_cb_ready = true; + +static struct pios_mpu6050_cfg const * cfg; + +/** + * @brief Initialize the MPU6050 3-axis gyro sensor. + * @return none + */ +void PIOS_MPU6050_Init(const struct pios_mpu6050_cfg * new_cfg) +{ + cfg = new_cfg; + + fifoBuf_init(&pios_mpu6050_fifo, (uint8_t *) pios_mpu6050_buffer, sizeof(pios_mpu6050_buffer)); + + /* Configure EOC pin as input floating */ + GPIO_Init(cfg->drdy.gpio, &cfg->drdy.init); + + /* Configure the End Of Conversion (EOC) interrupt */ + SYSCFG_EXTILineConfig(cfg->eoc_exti.port_source, cfg->eoc_exti.pin_source); + EXTI_Init(&cfg->eoc_exti.init); + + /* Enable and set EOC EXTI Interrupt to the lowest priority */ + NVIC_Init(&cfg->eoc_irq.init); + + /* Configure the MPU6050 Sensor */ + PIOS_MPU6050_Config(cfg); +} + +/** + * @brief Initialize the MPU6050 3-axis gyro sensor + * \return none + * \param[in] PIOS_MPU6050_ConfigTypeDef struct to be used to configure sensor. +* +*/ +static void PIOS_MPU6050_Config(struct pios_mpu6050_cfg const * cfg) +{ + mpu6050_first_read = true; + mpu6050_cb_ready = true; + + // Reset chip and fifo + while (PIOS_MPU6050_Write(PIOS_MPU6050_USER_CTRL_REG, 0x01 | 0x02) != 0); + PIOS_DELAY_WaituS(20); + while (PIOS_MPU6050_Write(PIOS_MPU6050_USER_CTRL_REG, 0x00) != 0); + + // FIFO storage + while (PIOS_MPU6050_Write(PIOS_MPU6050_FIFO_EN_REG, cfg->Fifo_store) != 0); + + // Sample rate divider + while (PIOS_MPU6050_Write(PIOS_MPU6050_SMPLRT_DIV_REG, cfg->Smpl_rate_div) != 0) ; + + // Digital low-pass filter and scale + while (PIOS_MPU6050_Write(PIOS_MPU6050_DLPF_CFG_REG, cfg->filter | (cfg->range << 3)) != 0) ; + + // Interrupt configuration + while (PIOS_MPU6050_Write(PIOS_MPU6050_USER_CTRL_REG, cfg->User_ctl) != 0) ; + + // Interrupt configuration + while (PIOS_MPU6050_Write(PIOS_MPU6050_PWR_MGMT_REG, cfg->Pwr_mgmt_clk) != 0) ; + + // Interrupt configuration + while (PIOS_MPU6050_Write(PIOS_MPU6050_INT_CFG_REG, cfg->Interrupt_cfg) != 0) ; + + mpu6050_configured = true; +} + +/** + * @brief Read current X, Z, Y values (in that order) + * \param[out] int16_t array of size 3 to store X, Z, and Y magnetometer readings + * \returns The number of samples remaining in the fifo +*/ +int32_t PIOS_MPU6050_ReadGyros(struct pios_mpu6050_data * data) +{ + uint8_t buf[6]; + if(PIOS_MPU6050_Read(PIOS_MPU6050_GYRO_X_OUT_MSB, (uint8_t *) buf, sizeof(buf)) < 0) + return -1; + data->x = buf[0] << 8 | buf[1]; + data->y = buf[2] << 8 | buf[3]; + data->z = buf[4] << 8 | buf[5]; + return 0; +} + + +/** + * @brief Read the identification bytes from the MPU6050 sensor + * \return ID read from MPU6050 or -1 if failure +*/ +int32_t PIOS_MPU6050_ReadID() +{ + uint8_t mpu6050_id; + if(PIOS_MPU6050_Read(PIOS_MPU6050_WHOAMI, (uint8_t *) &mpu6050_id, 1) != 0) + return -1; + return mpu6050_id; +} + +/** + * \brief Reads the data from the MPU6050 FIFO + * \param[out] buffer destination buffer + * \param[in] len maximum number of bytes which should be read + * \note This returns the data as X, Y, Z the temperature + * \return number of bytes transferred if operation was successful + * \return -1 if error during I2C transfer + */ +int32_t PIOS_MPU6050_ReadFifo(struct pios_mpu6050_data * buffer) +{ + if(fifoBuf_getUsed(&pios_mpu6050_fifo) < sizeof(*buffer)) + return -1; + + fifoBuf_getData(&pios_mpu6050_fifo, (uint8_t *) buffer, sizeof(*buffer)); + + return 0; +} + +/** +* @brief Reads one or more bytes from MPU6050 into a buffer +* \param[in] address MPU6050 register address (depends on size) +* \param[out] buffer destination buffer +* \param[in] len number of bytes which should be read +* \return 0 if operation was successful +* \return -1 if error during I2C transfer +* \return -2 if unable to claim i2c device +*/ +static int32_t PIOS_MPU6050_Read(uint8_t address, uint8_t * buffer, uint8_t len) +{ + uint8_t addr_buffer[] = { + address, + }; + + const struct pios_i2c_txn txn_list[] = { + { + .info = __func__, + .addr = PIOS_MPU6050_I2C_ADDR, + .rw = PIOS_I2C_TXN_WRITE, + .len = sizeof(addr_buffer), + .buf = addr_buffer, + } + , + { + .info = __func__, + .addr = PIOS_MPU6050_I2C_ADDR, + .rw = PIOS_I2C_TXN_READ, + .len = len, + .buf = buffer, + } + }; + + return PIOS_I2C_Transfer(PIOS_I2C_GYRO_ADAPTER, txn_list, NELEMENTS(txn_list)); +} + +// Must allocate on stack to be persistent +static uint8_t cb_addr_buffer[] = { + 0, +}; +static struct pios_i2c_txn cb_txn_list[] = { + { + .addr = PIOS_MPU6050_I2C_ADDR, + .rw = PIOS_I2C_TXN_WRITE, + .len = sizeof(cb_addr_buffer), + .buf = cb_addr_buffer, + } + , + { + .addr = PIOS_MPU6050_I2C_ADDR, + .rw = PIOS_I2C_TXN_READ, + .len = 0, + .buf = 0, + } +}; + + + +static int32_t PIOS_MPU6050_Read_Callback(uint8_t address, uint8_t * buffer, uint8_t len, void *callback) +{ + cb_addr_buffer[0] = address; + cb_txn_list[0].info = __func__, + cb_txn_list[1].info = __func__; + cb_txn_list[1].len = len; + cb_txn_list[1].buf = buffer; + + return PIOS_I2C_Transfer_Callback(PIOS_I2C_GYRO_ADAPTER, cb_txn_list, NELEMENTS(cb_txn_list), callback); +} + +/** + * @brief Writes one or more bytes to the MPU6050 + * \param[in] address Register address + * \param[in] buffer source buffer + * \return 0 if operation was successful + * \return -1 if error during I2C transfer + * \return -2 if unable to claim i2c device + */ +static int32_t PIOS_MPU6050_Write(uint8_t address, uint8_t buffer) +{ + uint8_t data[] = { + address, + buffer, + }; + + const struct pios_i2c_txn txn_list[] = { + { + .info = __func__, + .addr = PIOS_MPU6050_I2C_ADDR, + .rw = PIOS_I2C_TXN_WRITE, + .len = sizeof(data), + .buf = data, + } + , + }; + + return PIOS_I2C_Transfer(PIOS_I2C_GYRO_ADAPTER, txn_list, NELEMENTS(txn_list)); +} + +float PIOS_MPU6050_GetScale() +{ + switch (cfg->range) { + case PIOS_MPU6050_SCALE_250_DEG: + return DEG_TO_RAD / 131.0; + case PIOS_MPU6050_SCALE_500_DEG: + return DEG_TO_RAD / 65.5; + case PIOS_MPU6050_SCALE_1000_DEG: + return DEG_TO_RAD / 32.8; + case PIOS_MPU6050_SCALE_2000_DEG: + return DEG_TO_RAD / 16.4; + } + return 0; +} +/** + * @brief Run self-test operation. + * \return 0 if test succeeded + * \return non-zero value if test succeeded + */ +uint8_t PIOS_MPU6050_Test(void) +{ + /* Verify that ID matches (MPU6050 ID is 0x69) */ + int32_t mpu6050_id = PIOS_MPU6050_ReadID(); + if(mpu6050_id < 0) + return -1; + + if(mpu6050_id != PIOS_MPU6050_I2C_ADDR & 0xFE) + return -2; + + return 0; +} + +static uint8_t mpu6050_read_buffer[sizeof(struct pios_mpu6050_data) + 2]; // Right now using ,Y,Z,fifo_footer +static void MPU6050_callback() +{ + struct pios_mpu6050_data data; + + if(fifoBuf_getFree(&pios_mpu6050_fifo) < sizeof(data)) + goto out; + + if(mpu6050_first_read) { + data.temperature = mpu6050_read_buffer[0] << 8 | mpu6050_read_buffer[1]; + data.x = mpu6050_read_buffer[2] << 8 | mpu6050_read_buffer[3]; + data.y = mpu6050_read_buffer[4] << 8 | mpu6050_read_buffer[5]; + data.z = mpu6050_read_buffer[6] << 8 | mpu6050_read_buffer[7]; + + mpu6050_first_read = false; + } else { + // First two bytes are left over fifo from last call + data.temperature = mpu6050_read_buffer[2] << 8 | mpu6050_read_buffer[3]; + data.x = mpu6050_read_buffer[4] << 8 | mpu6050_read_buffer[5]; + data.y = mpu6050_read_buffer[6] << 8 | mpu6050_read_buffer[7]; + data.z = mpu6050_read_buffer[8] << 8 | mpu6050_read_buffer[9]; + } + + fifoBuf_putData(&pios_mpu6050_fifo, (uint8_t *) &data, sizeof(data)); + +out: + mpu6050_cb_ready = true; + +} + +/** +* @brief IRQ Handler +*/ +uint32_t mpu6050_irq = 0; +uint16_t fifo_level; +uint8_t fifo_level_data[2]; +uint32_t cb_not_ready = 0; +void PIOS_MPU6050_IRQHandler(void) +{ + + mpu6050_irq++; + + if(!mpu6050_configured) + return; + + //PIOS_Assert(MPU6050_cb_ready); + if(!mpu6050_cb_ready) { + PIOS_LED_Toggle(LED2); + cb_not_ready++; + return; + } + + // If at least one read doesnt succeed then the irq not reset and we will stall + while(PIOS_MPU6050_Read(PIOS_MPU6050_FIFO_CNT_MSB, (uint8_t *) &fifo_level_data, sizeof(fifo_level_data)) != 0) + PIOS_DELAY_WaituS(10); + + fifo_level = (fifo_level_data[0] << 8) + fifo_level_data[1]; + + PIOS_DELAY_WaituS(10); + + if(mpu6050_first_read) { + // Stupid system for MPU6050. If first read from buffer then we will read 4 sensors without fifo + // footer. After this we will read out a fifo footer + if(fifo_level < sizeof(mpu6050_read_buffer)) + return; + + mpu6050_cb_ready = false; + + // Leave footer in buffer + PIOS_MPU6050_Read_Callback(PIOS_MPU6050_FIFO_REG, mpu6050_read_buffer, sizeof(mpu6050_read_buffer) - 2, MPU6050_callback); + + } else { + // Stupid system for MPU6050. Ensure something is left in buffer + if(fifo_level < (sizeof(mpu6050_read_buffer) + 2)) + return; + + mpu6050_cb_ready = false; + + // Leave footer in buffer + PIOS_MPU6050_Read_Callback(PIOS_MPU6050_FIFO_REG, mpu6050_read_buffer, sizeof(mpu6050_read_buffer), MPU6050_callback); + + } +} + +/** + * The physical IRQ handler + * Soon this will be generic in pios_exti and the BMA180 will register + * against it. Right now this is crap! + */ +void EXTI1_IRQHandler(void) +{ + if (EXTI_GetITStatus(EXTI_Line1) != RESET) + { + PIOS_MPU6050_IRQHandler(); + EXTI_ClearITPendingBit(EXTI_Line1); + } +} + +#endif + +/** + * @} + * @} + */ diff --git a/flight/PiOS/inc/pios_mpu6050.h b/flight/PiOS/inc/pios_mpu6050.h new file mode 100644 index 000000000..309c46919 --- /dev/null +++ b/flight/PiOS/inc/pios_mpu6050.h @@ -0,0 +1,151 @@ +/** + ****************************************************************************** + * @addtogroup PIOS PIOS Core hardware abstraction layer + * @{ + * @addtogroup PIOS_MPU6050 MPU6050 Functions + * @brief Deals with the hardware interface to the 3-axis gyro + * @{ + * + * @file pios_MPU6050.h + * @author David "Buzz" Carlson (buzz@chebuzz.com) + * The OpenPilot Team, http://www.openpilot.org Copyright (C) 2011. + * @brief MPU6050 3-axis gyor function headers + * @see The GNU Public License (GPL) Version 3 + * + ****************************************************************************** + */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PIOS_MPU6050_H +#define PIOS_MPU6050_H + +#include "pios.h" + +/* MPU6050 Addresses */ +#define PIOS_MPU6050_I2C_ADDR 0x69 +#define PIOS_MPU6050_X_MSB_OFFSET_REG 0x43 +#define PIOS_MPU6050_X_LSB_OFFSET_REG 0x44 +#define PIOS_MPU6050_Y_MSB_OFFSET_REG 0x45 +#define PIOS_MPU6050_Y_LSB_OFFSET_REG 0x46 +#define PIOS_MPU6050_Z_MSB_OFFSET_REG 0x47 +#define PIOS_MPU6050_Z_LSB_OFFSET_REG 0x48 +#define PIOS_MPU6050_FIFO_EN_REG 0x23 +#define PIOS_MPU6050_SMPLRT_DIV_REG 0X19 +#define PIOS_MPU6050_DLPF_CFG_REG 0X16 +#define PIOS_MPU6050_INT_CFG_REG 0x37 +#define PIOS_MPU6050_INT_STATUS_REG 0x3A +#define PIOS_MPU6050_TEMP_OUT_MSB 0x41 +#define PIOS_MPU6050_TEMP_OUT_LSB 0x42 +#define PIOS_MPU6050_GYRO_X_OUT_MSB 0x1D +#define PIOS_MPU6050_GYRO_X_OUT_LSB 0x1E +#define PIOS_MPU6050_GYRO_Y_OUT_MSB 0x1F +#define PIOS_MPU6050_GYRO_Y_OUT_LSB 0x20 +#define PIOS_MPU6050_GYRO_Z_OUT_MSB 0x21 +#define PIOS_MPU6050_GYRO_Z_OUT_LSB 0x22 +#define PIOS_MPU6050_FIFO_CNT_MSB 0x72 +#define PIOS_MPU6050_FIFO_CNT_LSB 0x73 +#define PIOS_MPU6050_FIFO_REG 0x74 +#define PIOS_MPU6050_USER_CTRL_REG 0x6A +#define PIOS_MPU6050_PWR_MGMT_REG 0x6C +#define PIOS_MPU6050_WHOAMI 0x75 + +/* FIFO enable for storing different values */ +#define PIOS_MPU6050_FIFO_TEMP_OUT 0x80 +#define PIOS_MPU6050_FIFO_GYRO_X_OUT 0x40 +#define PIOS_MPU6050_FIFO_GYRO_Y_OUT 0x20 +#define PIOS_MPU6050_FIFO_GYRO_Z_OUT 0x10 +#define PIOS_MPU6050_FIFO_FOOTER 0x01 + + +/* Interrupt Configuration */ +#define PIOS_MPU6050_INT_ACTL 0x80 +#define PIOS_MPU6050_INT_OPEN 0x40 +#define PIOS_MPU6050_INT_LATCH_EN 0x20 +#define PIOS_MPU6050_INT_CLR_ANYRD 0x10 +#define PIOS_MPU6050_INT_IMU_RDY 0x04 +#define PIOS_MPU6050_INT_DATA_RDY 0x01 + +/* Interrupt status */ +#define PIOS_MPU6050_INT_STATUS_FIFO_FULL 0x80 +#define PIOS_MPU6050_INT_STATUS_IMU_RDY 0X04 +#define PIOS_MPU6050_INT_STATUS_DATA_RDY 0X01 + +/* User control functionality */ +#define PIOS_MPU6050_USERCTL_FIFO_EN 0X40 +#define PIOS_MPU6050_USERCTL_FIFO_RST 0X02 +#define PIOS_MPU6050_USERCTL_GYRO_RST 0X01 + +/* Power management and clock selection */ +#define PIOS_MPU6050_PWRMGMT_IMU_RST 0X80 +#define PIOS_MPU6050_PWRMGMT_INTERN_CLK 0X00 +#define PIOS_MPU6050_PWRMGMT_PLL_X_CLK 0X01 +#define PIOS_MPU6050_PWRMGMT_PLL_Y_CLK 0X02 +#define PIOS_MPU6050_PWRMGMT_PLL_Z_CLK 0X03 +#define PIOS_MPU6050_PWRMGMT_STOP_CLK 0X07 + +enum pios_mpu6050_range { + PIOS_MPU6050_SCALE_250_DEG = 0x00, + PIOS_MPU6050_SCALE_500_DEG = 0x01, + PIOS_MPU6050_SCALE_1000_DEG = 0x02, + PIOS_MPU6050_SCALE_2000_DEG = 0x03 +}; + +enum pios_mpu6050_filter { + PIOS_MPU6050_LOWPASS_256_HZ = 0x00, + PIOS_MPU6050_LOWPASS_188_HZ = 0x01, + PIOS_MPU6050_LOWPASS_98_HZ = 0x02, + PIOS_MPU6050_LOWPASS_42_HZ = 0x03, + PIOS_MPU6050_LOWPASS_20_HZ = 0x04, + PIOS_MPU6050_LOWPASS_10_HZ = 0x05, + PIOS_MPU6050_LOWPASS_5_HZ = 0x06 +}; + +struct pios_mpu6050_data { + int16_t x; + int16_t y; + int16_t z; + int16_t temperature; +}; + +struct pios_mpu6050_cfg { + struct stm32_gpio drdy; + struct stm32_exti eoc_exti; + struct stm32_irq eoc_irq; + + uint8_t Fifo_store; /* FIFO storage of different readings (See datasheet page 31 for more details) */ + uint8_t Smpl_rate_div; /* Sample rate divider to use (See datasheet page 32 for more details) */ + uint8_t Interrupt_cfg; /* Interrupt configuration (See datasheet page 35 for more details) */ + uint8_t User_ctl; /* User control settings (See datasheet page 41 for more details) */ + uint8_t Pwr_mgmt_clk; /* Power management and clock selection (See datasheet page 32 for more details) */ + enum pios_mpu6050_range range; + enum pios_mpu6050_filter filter; +}; + +/* Public Functions */ +extern void PIOS_MPU6050_Init(const struct pios_mpu6050_cfg * cfg); +extern int32_t PIOS_MPU6050_ReadFifo(struct pios_mpu6050_data * buffer); +extern int32_t PIOS_MPU6050_ReadGyros(struct pios_mpu6050_data * buffer); +extern int32_t PIOS_MPU6050_ReadID(); +extern uint8_t PIOS_MPU6050_Test(); +extern float PIOS_MPU6050_GetScale(); + +#endif /* PIOS_MPU6050_H */ + +/** + * @} + * @} + */ diff --git a/flight/PiOS/pios.h b/flight/PiOS/pios.h index e1b2eb277..de3358ba8 100644 --- a/flight/PiOS/pios.h +++ b/flight/PiOS/pios.h @@ -117,6 +117,9 @@ #if defined(PIOS_INCLUDE_IMU3000) #include #endif +#if defined(PIOS_INCLUDE_MPU6050) +#include +#endif #include #if defined(PIOS_INCLUDE_ADXL345) diff --git a/flight/Project/OpenPilotOSX/OpenPilotOSX.xcodeproj/project.pbxproj b/flight/Project/OpenPilotOSX/OpenPilotOSX.xcodeproj/project.pbxproj index 5912e875c..15e101e25 100644 --- a/flight/Project/OpenPilotOSX/OpenPilotOSX.xcodeproj/project.pbxproj +++ b/flight/Project/OpenPilotOSX/OpenPilotOSX.xcodeproj/project.pbxproj @@ -3320,6 +3320,18 @@ 65FA9B71147087020019A260 /* STM32F4xx_Revolution.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STM32F4xx_Revolution.h; sourceTree = ""; }; 65FA9B77147095D40019A260 /* attitude.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = attitude.c; sourceTree = ""; }; 65FA9B79147095D40019A260 /* attitude.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = attitude.h; sourceTree = ""; }; + 65FA9B7A14709E700019A260 /* pios_mpu6050.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pios_mpu6050.c; sourceTree = ""; }; + 65FA9B7B14709E9E0019A260 /* pios_board_info.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pios_board_info.h; sourceTree = ""; }; + 65FA9B7C14709E9E0019A260 /* pios_gcsrcvr_priv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pios_gcsrcvr_priv.h; sourceTree = ""; }; + 65FA9B7D14709E9E0019A260 /* pios_hcsr04.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pios_hcsr04.h; sourceTree = ""; }; + 65FA9B7E14709E9E0019A260 /* pios_i2c_esc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pios_i2c_esc.h; sourceTree = ""; }; + 65FA9B7F14709E9E0019A260 /* pios_iap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pios_iap.h; sourceTree = ""; }; + 65FA9B8014709E9E0019A260 /* pios_initcall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pios_initcall.h; sourceTree = ""; }; + 65FA9B8114709E9E0019A260 /* pios_mpu6050.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pios_mpu6050.h; sourceTree = ""; }; + 65FA9B8214709E9E0019A260 /* pios_ppm_priv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pios_ppm_priv.h; sourceTree = ""; }; + 65FA9B8314709E9E0019A260 /* pios_tim_priv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pios_tim_priv.h; sourceTree = ""; }; + 65FA9B8414709E9F0019A260 /* pios_tim.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pios_tim.h; sourceTree = ""; }; + 65FA9B8514709E9F0019A260 /* pios_usb_hid_priv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pios_usb_hid_priv.h; sourceTree = ""; }; 65FAA03F133B669400F6F5CD /* GTOP_BIN.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = GTOP_BIN.c; sourceTree = ""; }; 65FBE14412E7C98100176B5A /* pios_servo_priv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pios_servo_priv.h; sourceTree = ""; }; 65FC66AA123F30F100B04F74 /* ahrs_timer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ahrs_timer.c; path = ../../AHRS/ahrs_timer.c; sourceTree = SOURCE_ROOT; }; @@ -3862,6 +3874,7 @@ 65904ECF14613B6100FD9482 /* pios_imu3000.c */, 65904ED014613B6100FD9482 /* pios_irq.c */, 65904ED114613B6100FD9482 /* pios_led.c */, + 65FA9B7A14709E700019A260 /* pios_mpu6050.c */, 65904ED214613B6100FD9482 /* pios_ppm.c */, 65904ED314613B6100FD9482 /* pios_servo.c */, 65904ED414613B6100FD9482 /* pios_spi.c */, @@ -8490,6 +8503,7 @@ 65E8F03811EFF25C00BBF654 /* inc */ = { isa = PBXGroup; children = ( + 65FA9B8514709E9F0019A260 /* pios_usb_hid_priv.h */, 65DEA78513F0FE6000095B06 /* stm32f2xx_conf.h */, 65E8F03A11EFF25C00BBF654 /* pios_adc.h */, 6528CCE212E40F6700CF5144 /* pios_adxl345.h */, @@ -8497,6 +8511,7 @@ 65E6E09912E037C800058553 /* pios_adc_priv.h */, 65DEA78613F1118400095B06 /* pios_bma180.h */, 65E8F03B11EFF25C00BBF654 /* pios_bmp085.h */, + 65FA9B7B14709E9E0019A260 /* pios_board_info.h */, 65E8F03C11EFF25C00BBF654 /* pios_com.h */, 65E8F03D11EFF25C00BBF654 /* pios_com_priv.h */, 65E8C745139A6D1A00E1F979 /* pios_crc.h */, @@ -8505,17 +8520,24 @@ 65E8F04011EFF25C00BBF654 /* pios_exti.h */, 6512D60512ED4CA2008175E5 /* pios_flash_w25x.h */, 65FF4D61137EFA4F00146BE4 /* pios_flashfs_objlist.h */, + 65FA9B7C14709E9E0019A260 /* pios_gcsrcvr_priv.h */, 65E8F04111EFF25C00BBF654 /* pios_gpio.h */, + 65FA9B7D14709E9E0019A260 /* pios_hcsr04.h */, 65E8F04211EFF25C00BBF654 /* pios_hmc5843.h */, 65D1FBD413F504C9006374A6 /* pios_hmc5883.h */, + 65FA9B7F14709E9E0019A260 /* pios_iap.h */, 65E8F04311EFF25C00BBF654 /* pios_i2c.h */, + 65FA9B7E14709E9E0019A260 /* pios_i2c_esc.h */, 6526645A122DF972006F9A3C /* pios_i2c_priv.h */, 65D1FBDA13F51AE1006374A6 /* pios_imu3000.h */, + 65FA9B8014709E9E0019A260 /* pios_initcall.h */, 65E8F04411EFF25C00BBF654 /* pios_irq.h */, 65E8F04511EFF25C00BBF654 /* pios_led.h */, + 65FA9B8114709E9E0019A260 /* pios_mpu6050.h */, 65E8F04611EFF25C00BBF654 /* pios_opahrs.h */, 65E8F04711EFF25C00BBF654 /* pios_opahrs_proto.h */, 65E8F04811EFF25C00BBF654 /* pios_ppm.h */, + 65FA9B8214709E9E0019A260 /* pios_ppm_priv.h */, 65E8F04911EFF25C00BBF654 /* pios_pwm.h */, 657FF86A12EA8BFB00801617 /* pios_pwm_priv.h */, 65643CAC1413322000A32F59 /* pios_rcvr.h */, @@ -8533,6 +8555,8 @@ 65E8F04E11EFF25C00BBF654 /* pios_spi_priv.h */, 65E8F04F11EFF25C00BBF654 /* pios_stm32.h */, 65E8F05011EFF25C00BBF654 /* pios_sys.h */, + 65FA9B8314709E9E0019A260 /* pios_tim_priv.h */, + 65FA9B8414709E9F0019A260 /* pios_tim.h */, 65E8F05111EFF25C00BBF654 /* pios_usart.h */, 65E8F05211EFF25C00BBF654 /* pios_usart_priv.h */, 65E8F05311EFF25C00BBF654 /* pios_usb.h */,