diff --git a/conf/airframes/PPZUAV/fixed-wing/ppzimu_tiny.xml b/conf/airframes/PPZUAV/fixed-wing/ppzimu_tiny.xml index 5560d16184..67c2bf0b62 100644 --- a/conf/airframes/PPZUAV/fixed-wing/ppzimu_tiny.xml +++ b/conf/airframes/PPZUAV/fixed-wing/ppzimu_tiny.xml @@ -203,8 +203,6 @@ --> - - -
- -
- - - - - - - - - - - - - - - - - - diff --git a/conf/modules/imu_ppzuav.xml b/conf/modules/imu_ppzuav.xml deleted file mode 100644 index 401f43719a..0000000000 --- a/conf/modules/imu_ppzuav.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - -
- -
- - - - - - - - - - - - - - - - -
diff --git a/conf/modules/ins_ppzuavimu.xml b/conf/modules/ins_ppzuavimu.xml deleted file mode 100644 index 06b6da5095..0000000000 --- a/conf/modules/ins_ppzuavimu.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - -
- -
- - - -$(error The ins_ppzuavimu module has been renamed, please replace the name="ins_ppzuavimu.xml" with name="imu_ppzuav.xml" in the load tag of your airframe file modules section.) - - -
diff --git a/sw/airborne/modules/sensors/imu_ppzuav.c b/sw/airborne/modules/sensors/imu_ppzuav.c deleted file mode 100644 index 7c05a6493e..0000000000 --- a/sw/airborne/modules/sensors/imu_ppzuav.c +++ /dev/null @@ -1,273 +0,0 @@ -/* - * This file is part of paparazzi. - * - * paparazzi 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 2, or (at your option) - * any later version. - * - * paparazzi 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 paparazzi; see the file COPYING. If not, write to - * the Free Software Foundation, 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#include -#include "imu_ppzuav.h" -#include "mcu_periph/i2c.h" -#include "led.h" - -// Set SPI_CS High -#include "mcu_periph/gpio_arch.h" - -// Downlink -#include "mcu_periph/uart.h" -#include "messages.h" -#include "subsystems/datalink/downlink.h" - -#ifndef DOWNLINK_DEVICE -#define DOWNLINK_DEVICE DOWNLINK_AP_DEVICE -#endif - - -// Peripherials -#define HMC5843_NO_IRQ -#include "peripherals/itg3200_regs.h" -#include "peripherals/adxl345_regs.h" -#include "peripherals/hmc5843_regs.h" - -// Results -volatile bool_t mag_valid; -volatile bool_t gyr_valid; -volatile bool_t acc_valid; - -// Communication -struct i2c_transaction ppzuavimu_hmc5843; -struct i2c_transaction ppzuavimu_itg3200; -struct i2c_transaction ppzuavimu_adxl345; - -// Standalone option: run module only -#ifndef IMU_TYPE_H -struct Imu imu; -#endif - -#ifndef PERIODIC_FREQUENCY -#define PERIODIC_FREQUENCY 60 -#endif - -void imu_impl_init(void) -{ - GPIO_ARCH_SET_SPI_CS_HIGH(); - - ///////////////////////////////////////////////////////////////////// - // ITG3200 - ppzuavimu_itg3200.type = I2CTransTx; - ppzuavimu_itg3200.slave_addr = ITG3200_ADDR; - ppzuavimu_itg3200.buf[0] = ITG3200_REG_DLPF_FS; -#if PERIODIC_FREQUENCY == 60 - /* set gyro range to 2000deg/s and low pass at 20Hz (< 60Hz/2) internal sampling at 1kHz */ - ppzuavimu_itg3200.buf[1] = (0x03<<3) | (0x04<<0); -# pragma message "ITG3200 read at 50Hz." -#else -# if PERIODIC_FREQUENCY == 120 -# pragma message "ITG3200 read at 100Hz." - /* set gyro range to 2000deg/s and low pass at 42Hz (< 120Hz/2) internal sampling at 1kHz */ - ppzuavimu_itg3200.buf[1] = (0x03<<3) | (0x03<<0); -# else -# error PERIODIC_FREQUENCY should be either 60Hz or 120Hz. Otherwise manually fix the sensor rates -# endif -#endif - ppzuavimu_itg3200.len_w = 2; - i2c_submit(&PPZUAVIMU_I2C_DEV,&ppzuavimu_itg3200); - while(ppzuavimu_itg3200.status == I2CTransPending); - - /* set sample rate to 66Hz: so at 60Hz there is always a new sample ready and you loose little */ - ppzuavimu_itg3200.buf[0] = ITG3200_REG_SMPLRT_DIV; -#if PERIODIC_FREQUENCY == 60 - ppzuavimu_itg3200.buf[1] = 19; // 50Hz -#else - ppzuavimu_itg3200.buf[1] = 9; // 100Hz -#endif - i2c_submit(&PPZUAVIMU_I2C_DEV,&ppzuavimu_itg3200); - while(ppzuavimu_itg3200.status == I2CTransPending); - - /* switch to gyroX clock */ - ppzuavimu_itg3200.buf[0] = ITG3200_REG_PWR_MGM; - ppzuavimu_itg3200.buf[1] = 0x01; - i2c_submit(&PPZUAVIMU_I2C_DEV,&ppzuavimu_itg3200); - while(ppzuavimu_itg3200.status == I2CTransPending); - - /* no interrupts for now, but set data ready interrupt to enable reading status bits */ - ppzuavimu_itg3200.buf[0] = ITG3200_REG_INT_CFG; - ppzuavimu_itg3200.buf[1] = 0x01; - i2c_submit(&PPZUAVIMU_I2C_DEV,&ppzuavimu_itg3200); - while(ppzuavimu_itg3200.status == I2CTransPending); - - ///////////////////////////////////////////////////////////////////// - // ADXL345 - - /* set data rate to 100Hz */ - ppzuavimu_adxl345.slave_addr = ADXL345_ADDR; - ppzuavimu_adxl345.type = I2CTransTx; - ppzuavimu_adxl345.buf[0] = ADXL345_REG_BW_RATE; -#if PERIODIC_FREQUENCY == 60 - ppzuavimu_adxl345.buf[1] = ADXL345_RATE_50HZ; // normal power and 50Hz sampling, 25Hz BW -#else - ppzuavimu_adxl345.buf[1] = ADXL345_RATE_100HZ; // normal power and 100Hz sampling, 50Hz BW -#endif - ppzuavimu_adxl345.len_w = 2; - i2c_submit(&PPZUAVIMU_I2C_DEV,&ppzuavimu_adxl345); - while(ppzuavimu_adxl345.status == I2CTransPending); - - /* switch to measurement mode */ - ppzuavimu_adxl345.type = I2CTransTx; - ppzuavimu_adxl345.buf[0] = ADXL345_REG_POWER_CTL; - ppzuavimu_adxl345.buf[1] = 1<<3; - ppzuavimu_adxl345.len_w = 2; - i2c_submit(&PPZUAVIMU_I2C_DEV,&ppzuavimu_adxl345); - while(ppzuavimu_adxl345.status == I2CTransPending); - - /* Set range to 16g but keeping full resolution of 3.9 mV/g */ - ppzuavimu_adxl345.type = I2CTransTx; - ppzuavimu_adxl345.buf[0] = ADXL345_REG_DATA_FORMAT; - ppzuavimu_adxl345.buf[1] = ADXL345_FULL_RES | ADXL345_RANGE_16G; - i2c_submit(&PPZUAVIMU_I2C_DEV,&ppzuavimu_adxl345); - while(ppzuavimu_adxl345.status == I2CTransPending); - - ///////////////////////////////////////////////////////////////////// - // HMC5843 - ppzuavimu_hmc5843.slave_addr = HMC5843_ADDR; - ppzuavimu_hmc5843.type = I2CTransTx; - ppzuavimu_hmc5843.buf[0] = HMC5843_REG_CFGA; // set to rate to max speed: 50Hz no bias - ppzuavimu_hmc5843.buf[1] = 0x00 | (0x06 << 2); - ppzuavimu_hmc5843.len_w = 2; - i2c_submit(&PPZUAVIMU_I2C_DEV,&ppzuavimu_hmc5843); - while(ppzuavimu_hmc5843.status == I2CTransPending); - - ppzuavimu_hmc5843.type = I2CTransTx; - ppzuavimu_hmc5843.buf[0] = HMC5843_REG_CFGB; // set to gain to 1 Gauss - ppzuavimu_hmc5843.buf[1] = 0x01<<5; - ppzuavimu_hmc5843.len_w = 2; - i2c_submit(&PPZUAVIMU_I2C_DEV,&ppzuavimu_hmc5843); - while(ppzuavimu_hmc5843.status == I2CTransPending); - - ppzuavimu_hmc5843.type = I2CTransTx; - ppzuavimu_hmc5843.buf[0] = HMC5843_REG_MODE; // set to continuous mode - ppzuavimu_hmc5843.buf[1] = 0x00; - ppzuavimu_hmc5843.len_w = 2; - i2c_submit(&PPZUAVIMU_I2C_DEV,&ppzuavimu_hmc5843); - while(ppzuavimu_hmc5843.status == I2CTransPending); - -} - -void imu_periodic( void ) -{ - // Start reading the latest gyroscope data - ppzuavimu_itg3200.type = I2CTransTxRx; - ppzuavimu_itg3200.len_r = 9; - ppzuavimu_itg3200.len_w = 1; - ppzuavimu_itg3200.buf[0] = ITG3200_REG_INT_STATUS; - i2c_submit(&PPZUAVIMU_I2C_DEV, &ppzuavimu_itg3200); - - // Start reading the latest accelerometer data - ppzuavimu_adxl345.type = I2CTransTxRx; - ppzuavimu_adxl345.len_r = 6; - ppzuavimu_adxl345.len_w = 1; - ppzuavimu_adxl345.buf[0] = ADXL345_REG_DATA_X0; - i2c_submit(&PPZUAVIMU_I2C_DEV, &ppzuavimu_adxl345); - - // Start reading the latest magnetometer data -#if PERIODIC_FREQUENCY > 60 - RunOnceEvery(2,{ -#endif - ppzuavimu_hmc5843.type = I2CTransTxRx; - ppzuavimu_hmc5843.len_r = 6; - ppzuavimu_hmc5843.len_w = 1; - ppzuavimu_hmc5843.buf[0] = HMC5843_REG_DATXM; - i2c_submit(&PPZUAVIMU_I2C_DEV, &ppzuavimu_hmc5843); -#if PERIODIC_FREQUENCY > 60 - }); -#endif - //RunOnceEvery(10,ppzuavimu_module_downlink_raw()); -} - -void ppzuavimu_module_downlink_raw( void ) -{ - DOWNLINK_SEND_IMU_GYRO_RAW(DefaultChannel, DefaultDevice,&imu.gyro_unscaled.p,&imu.gyro_unscaled.q,&imu.gyro_unscaled.r); - DOWNLINK_SEND_IMU_ACCEL_RAW(DefaultChannel, DefaultDevice,&imu.accel_unscaled.x,&imu.accel_unscaled.y,&imu.accel_unscaled.z); - DOWNLINK_SEND_IMU_MAG_RAW(DefaultChannel, DefaultDevice,&imu.mag_unscaled.x,&imu.mag_unscaled.y,&imu.mag_unscaled.z); -} - -void ppzuavimu_module_event( void ) -{ - int32_t x, y, z; - - // If the itg3200 I2C transaction has succeeded: convert the data - if (ppzuavimu_itg3200.status == I2CTransSuccess) - { -#define ITG_STA_DAT_OFFSET 3 - x = (int16_t) ((ppzuavimu_itg3200.buf[0+ITG_STA_DAT_OFFSET] << 8) | ppzuavimu_itg3200.buf[1+ITG_STA_DAT_OFFSET]); - y = (int16_t) ((ppzuavimu_itg3200.buf[2+ITG_STA_DAT_OFFSET] << 8) | ppzuavimu_itg3200.buf[3+ITG_STA_DAT_OFFSET]); - z = (int16_t) ((ppzuavimu_itg3200.buf[4+ITG_STA_DAT_OFFSET] << 8) | ppzuavimu_itg3200.buf[5+ITG_STA_DAT_OFFSET]); - - // Is this is new data - if (ppzuavimu_itg3200.buf[0] & 0x01) - { - //LED_ON(3); - gyr_valid = TRUE; - //LED_OFF(3); - } - else - { - } - - // Signs depend on the way sensors are soldered on the board: so they are hardcoded -#ifdef ASPIRIN_IMU - RATES_ASSIGN(imu.gyro_unscaled, x, -y, -z); -#else // PPZIMU - RATES_ASSIGN(imu.gyro_unscaled, -x, y, -z); -#endif - - ppzuavimu_itg3200.status = I2CTransDone; // remove the I2CTransSuccess status, otherwise data ready will be triggered again without new data - } - - // If the adxl345 I2C transaction has succeeded: convert the data - if (ppzuavimu_adxl345.status == I2CTransSuccess) - { - x = (int16_t) ((ppzuavimu_adxl345.buf[1] << 8) | ppzuavimu_adxl345.buf[0]); - y = (int16_t) ((ppzuavimu_adxl345.buf[3] << 8) | ppzuavimu_adxl345.buf[2]); - z = (int16_t) ((ppzuavimu_adxl345.buf[5] << 8) | ppzuavimu_adxl345.buf[4]); - -#ifdef ASPIRIN_IMU - VECT3_ASSIGN(imu.accel_unscaled, x, -y, -z); -#else // PPZIMU - VECT3_ASSIGN(imu.accel_unscaled, -x, y, -z); -#endif - - acc_valid = TRUE; - ppzuavimu_adxl345.status = I2CTransDone; - } - - // If the hmc5843 I2C transaction has succeeded: convert the data - if (ppzuavimu_hmc5843.status == I2CTransSuccess) - { - x = (int16_t) ((ppzuavimu_hmc5843.buf[0] << 8) | ppzuavimu_hmc5843.buf[1]); - y = (int16_t) ((ppzuavimu_hmc5843.buf[2] << 8) | ppzuavimu_hmc5843.buf[3]); - z = (int16_t) ((ppzuavimu_hmc5843.buf[4] << 8) | ppzuavimu_hmc5843.buf[5]); - -#ifdef ASPIRIN_IMU - VECT3_ASSIGN(imu.mag_unscaled, x, -y, -z); -#else // PPZIMU - VECT3_ASSIGN(imu.mag_unscaled, -y, -x, -z); -#endif - - mag_valid = TRUE; - ppzuavimu_hmc5843.status = I2CTransDone; - } -} diff --git a/sw/airborne/modules/sensors/imu_ppzuav.h b/sw/airborne/modules/sensors/imu_ppzuav.h deleted file mode 100644 index 8ffe325d29..0000000000 --- a/sw/airborne/modules/sensors/imu_ppzuav.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * This file is part of paparazzi. - * - * paparazzi 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 2, or (at your option) - * any later version. - * - * paparazzi 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 paparazzi; see the file COPYING. If not, write to - * the Free Software Foundation, 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifndef PPZUAVIMU_H -#define PPZUAVIMU_H - -#include "std.h" -#include "subsystems/imu.h" - -extern volatile bool_t gyr_valid; -extern volatile bool_t acc_valid; -extern volatile bool_t mag_valid; - -/* must be defined in order to be IMU code: declared in imu.h -extern void imu_impl_init(void); -extern void imu_periodic(void); -*/ - -#define ImuEvent(_gyro_handler, _accel_handler, _mag_handler) { \ - ppzuavimu_module_event(); \ - if (gyr_valid) { \ - gyr_valid = FALSE; \ - _gyro_handler(); \ - } \ - if (acc_valid) { \ - acc_valid = FALSE; \ - _accel_handler(); \ - } \ - if (mag_valid) { \ - mag_valid = FALSE; \ - _mag_handler(); \ - } \ -} - -/* Own Extra Functions */ -extern void ppzuavimu_module_event( void ); -extern void ppzuavimu_module_downlink_raw( void ); - - -#endif // PPZUAVIMU_H diff --git a/sw/airborne/subsystems/imu/imu_ppzuav.c b/sw/airborne/subsystems/imu/imu_ppzuav.c new file mode 100644 index 0000000000..bfce8c13a7 --- /dev/null +++ b/sw/airborne/subsystems/imu/imu_ppzuav.c @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2010 Antoine Drouin + * 2013 Felix Ruess + * + * This file is part of paparazzi. + * + * paparazzi 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 2, or (at your option) + * any later version. + * + * paparazzi 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 paparazzi; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * @file subsystems/imu/imu_ppzuav.h + * + * Driver for the PPZUAV IMU. + * + * 9DoM IMU with ITG-3200, ADXL345 and HMC5843, all via I2C. + */ + +#include "subsystems/imu.h" +#include "mcu_periph/i2c.h" + +/* i2c default suitable for Tiny/Twog */ +#ifndef IMU_PPZUAV_I2C_DEV +#define IMU_PPZUAV_I2C_DEV i2c0 +#endif + +/** adxl345 accelerometer output rate, lowpass is set to half of rate */ +#ifndef IMU_PPZUAV_ACCEL_RATE +# if PERIODIC_FREQUENCY <= 60 +# define IMU_PPZUAV_ACCEL_RATE ADXL345_RATE_50HZ +# elif PERIODIC_FREQUENCY <= 120 +# define IMU_PPZUAV_ACCEL_RATE ADXL345_RATE_100HZ +# else +# define IMU_PPZUAV_ACCEL_RATE ADXL345_RATE_200HZ +# endif +#endif +PRINT_CONFIG_VAR(IMU_PPZUAV_ACCEL_RATE) + + +/** gyro internal lowpass frequency */ +#ifndef IMU_PPZUAV_GYRO_LOWPASS +# if PERIODIC_FREQUENCY <= 60 +# define IMU_PPZUAV_GYRO_LOWPASS ITG3200_DLPF_20HZ +# elif PERIODIC_FREQUENCY <= 120 +# define IMU_PPZUAV_GYRO_LOWPASS ITG3200_DLPF_42HZ +# else +# define IMU_PPZUAV_GYRO_LOWPASS ITG3200_DLPF_98HZ +# endif +#endif +PRINT_CONFIG_VAR(IMU_PPZUAV_GYRO_LOWPASS) + + +/** gyro sample rate divider */ +#ifndef IMU_PPZUAV_GYRO_SMPLRT_DIV +# if PERIODIC_FREQUENCY <= 60 +# define IMU_PPZUAV_GYRO_SMPLRT_DIV 19 + INFO("Gyro output rate is 50Hz") +# else +# define IMU_PPZUAV_GYRO_SMPLRT_DIV 9 + INFO("Gyro output rate is 100Hz") +# endif +#endif + PRINT_CONFIG_VAR(IMU_PPZUAV_GYRO_SMPLRT_DIV) + + +struct ImuPpzuav imu_ppzuav; + +void imu_impl_init(void) +{ + imu_ppzuav.accel_valid = FALSE; + imu_ppzuav.gyro_valid = FALSE; + imu_ppzuav.mag_valid = FALSE; + + /* Set accel configuration */ + adxl345_i2c_init(&imu_ppzuav.acc_adxl, &(IMU_PPZUAV_I2C_DEV), ADXL345_ADDR); + /* set the data rate */ + imu_ppzuav.acc_adxl.config.rate = IMU_PPZUAV_ACCEL_RATE; + + /* Gyro configuration and initalization */ + itg3200_init(&imu_ppzuav.gyro_itg, &(IMU_PPZUAV_I2C_DEV), ITG3200_ADDR); + /* change the default config */ + imu_ppzuav.gyro_itg.config.smplrt_div = IMU_PPZUAV_GYRO_SMPLRT_DIV; + imu_ppzuav.gyro_itg.config.dlpf_cfg = IMU_PPZUAV_GYRO_LOWPASS; + + /* initialize mag and set default options */ + hmc58xx_init(&imu_ppzuav.mag_hmc, &(IMU_PPZUAV_I2C_DEV), HMC58XX_ADDR); + /* set the type to the old HMC5843 */ + imu_ppzuav.mag_hmc.type = HMC_TYPE_5843; +} + + +void imu_periodic(void) +{ + adxl345_i2c_periodic(&imu_ppzuav.acc_adxl); + + // Start reading the latest gyroscope data + itg3200_periodic(&imu_ppzuav.gyro_itg); + + // Read HMC58XX at 50Hz (main loop for rotorcraft: 512Hz) + RunOnceEvery(10, hmc58xx_periodic(&imu_ppzuav.mag_hmc)); +} + +void imu_ppzuav_event(void) +{ + adxl345_i2c_event(&imu_ppzuav.acc_adxl); + if (imu_ppzuav.acc_adxl.data_available) { + imu.accel_unscaled.x = -imu_ppzuav.acc_adxl.data.vect.x; + imu.accel_unscaled.y = imu_ppzuav.acc_adxl.data.vect.y; + imu.accel_unscaled.z = -imu_ppzuav.acc_adxl.data.vect.z; + imu_ppzuav.acc_adxl.data_available = FALSE; + imu_ppzuav.accel_valid = TRUE; + } + + /* If the itg3200 I2C transaction has succeeded: convert the data */ + itg3200_event(&imu_ppzuav.gyro_itg); + if (imu_ppzuav.gyro_itg.data_available) { + imu.gyro_unscaled.p = -imu_ppzuav.gyro_itg.data.rates.p; + imu.gyro_unscaled.q = imu_ppzuav.gyro_itg.data.rates.q; + imu.gyro_unscaled.r = -imu_ppzuav.gyro_itg.data.rates.r; + imu_ppzuav.gyro_itg.data_available = FALSE; + imu_ppzuav.gyro_valid = TRUE; + } + + /* HMC58XX event task */ + hmc58xx_event(&imu_ppzuav.mag_hmc); + if (imu_ppzuav.mag_hmc.data_available) { + imu.mag_unscaled.x = -imu_ppzuav.mag_hmc.data.vect.y; + imu.mag_unscaled.y = -imu_ppzuav.mag_hmc.data.vect.x; + imu.mag_unscaled.z = -imu_ppzuav.mag_hmc.data.vect.z; + imu_ppzuav.mag_hmc.data_available = FALSE; + imu_ppzuav.mag_valid = TRUE; + } +} diff --git a/sw/airborne/subsystems/imu/imu_ppzuav.h b/sw/airborne/subsystems/imu/imu_ppzuav.h new file mode 100644 index 0000000000..0774008d80 --- /dev/null +++ b/sw/airborne/subsystems/imu/imu_ppzuav.h @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2010 Antoine Drouin + * 2013 Felix Ruess + * + * This file is part of paparazzi. + * + * paparazzi 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 2, or (at your option) + * any later version. + * + * paparazzi 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 paparazzi; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * @file subsystems/imu/imu_ppzuav.h + * + * Interface and defaults for the PPZUAV IMU. + * + * 9DoM IMU with ITG-3200, ADXL345 and HMC5843, all via I2C. + */ + + +#ifndef IMU_PPZUAV_H +#define IMU_PPZUAV_H + +#include "generated/airframe.h" +#include "subsystems/imu.h" + +#include "peripherals/itg3200.h" +#include "peripherals/hmc58xx.h" +#include "peripherals/adxl345_i2c.h" + +#if !defined IMU_GYRO_P_SENS & !defined IMU_GYRO_Q_SENS & !defined IMU_GYRO_R_SENS +/** default gyro sensitivy and neutral from the datasheet + * ITG3200 has 14.375 LSB/(deg/s) + * sens = 1/14.375 * pi/180 * 2^INT32_RATE_FRAC + * sens = 1/14.375 * pi/180 * 4096 = 4.973126 + */ +#define IMU_GYRO_P_SENS 4.973 +#define IMU_GYRO_P_SENS_NUM 4973 +#define IMU_GYRO_P_SENS_DEN 1000 +#define IMU_GYRO_Q_SENS 4.973 +#define IMU_GYRO_Q_SENS_NUM 4973 +#define IMU_GYRO_Q_SENS_DEN 1000 +#define IMU_GYRO_R_SENS 4.973 +#define IMU_GYRO_R_SENS_NUM 4973 +#define IMU_GYRO_R_SENS_DEN 1000 +#endif + + +#if !defined IMU_ACCEL_X_SENS & !defined IMU_ACCEL_Y_SENS & !defined IMU_ACCEL_Z_SENS +/** default accel sensitivy from the ADXL345 datasheet + * sensitivity of x & y axes depends on supply voltage: + * - 256 LSB/g @ 2.5V + * - 265 LSB/g @ 3.3V + * z sensitivity stays at 256 LSB/g + * fixed point sens: 9.81 [m/s^2] / 256 [LSB/g] * 2^INT32_ACCEL_FRAC + * x/y sens = 9.81 / 265 * 1024 = 37.91 + * z sens = 9.81 / 256 * 1024 = 39.24 + */ +#define IMU_ACCEL_X_SENS 37.91 +#define IMU_ACCEL_X_SENS_NUM 3791 +#define IMU_ACCEL_X_SENS_DEN 100 +#define IMU_ACCEL_Y_SENS 37.91 +#define IMU_ACCEL_Y_SENS_NUM 3791 +#define IMU_ACCEL_Y_SENS_DEN 100 +#define IMU_ACCEL_Z_SENS 39.24 +#define IMU_ACCEL_Z_SENS_NUM 3924 +#define IMU_ACCEL_Z_SENS_DEN 100 +#endif + + +struct ImuPpzuav { + volatile uint8_t accel_valid; + volatile uint8_t gyro_valid; + volatile uint8_t mag_valid; + struct Adxl345_I2c acc_adxl; + struct Itg3200 gyro_itg; + struct Hmc58xx mag_hmc; +}; + +extern struct ImuPpzuav imu_ppzuav; + +extern void imu_ppzuav_event(void); + +static inline void ImuEvent(void (* _gyro_handler)(void), void (* _accel_handler)(void), void (* _mag_handler)(void)) { + imu_ppzuav_event(); + if (imu_ppzuav.gyro_valid) { + imu_ppzuav.gyro_valid = FALSE; + _gyro_handler(); + } + if (imu_ppzuav.accel_valid) { + imu_ppzuav.accel_valid = FALSE; + _accel_handler(); + } + if (imu_ppzuav.mag_valid) { + imu_ppzuav.mag_valid = FALSE; + _mag_handler(); + } +} + +#endif /* IMU_PPZUAV_H */