diff --git a/conf/messages.xml b/conf/messages.xml
index c711ad6535a..a820592b135 100644
--- a/conf/messages.xml
+++ b/conf/messages.xml
@@ -1172,7 +1172,11 @@
-
+
+
+
+
+
diff --git a/conf/modules/airspeed_ms45xx_i2c.xml b/conf/modules/airspeed_ms45xx_i2c.xml
new file mode 100644
index 00000000000..dfcf660ed11
--- /dev/null
+++ b/conf/modules/airspeed_ms45xx_i2c.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+ MS45XX Driver for differential pressure (airspeed) measurements.
+ Based on I2C
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sw/airborne/modules/sensors/airspeed_ms45xx_i2c.c b/sw/airborne/modules/sensors/airspeed_ms45xx_i2c.c
new file mode 100644
index 00000000000..35f487e28fd
--- /dev/null
+++ b/sw/airborne/modules/sensors/airspeed_ms45xx_i2c.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2014 Freek van Tienen
+ * 2014 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 modules/sensors/airspeed_ms45xx_i2c.c
+ * Airspeed sensor module using the MS45xxDO digital pressure sensor via I2C.
+ * Needs one of the differential versions with 14bit pressure and 11bit temperature.
+ */
+
+#include "std.h"
+#include "mcu_periph/i2c.h"
+#include "modules/sensors/airspeed_ms45xx_i2c.h"
+
+/** Default I2C device
+ */
+#ifndef MS45XX_I2C_DEV
+#define MS45XX_I2C_DEV i2c2
+#endif
+
+/** Sensor I2C slave address (defaults 0x50, 0x6C and 0x8C) */
+#ifndef MS45XX_I2C_ADDR
+#define MS45XX_I2C_ADDR 0x50
+#endif
+
+/** MS45xx pressure range in psi.
+ * The sensor is available in 1, 2, 5, 15, 30, 50, 100, 150 psi ranges.
+ */
+#ifndef MS45XX_PRESSURE_RANGE
+#define MS45XX_PRESSURE_RANGE 5
+#endif
+
+/** MS45xx output Type.
+ * 0 = Output Type A with 10% to 90%
+ * 1 = Output Type B with 5% to 95%
+ */
+#ifndef MS45XX_OUTPUT_TYPE
+#define MS45XX_OUTPUT_TYPE 0
+#endif
+
+/** Conversion factor from psi to Pa */
+#define PSI_TO_PA 6894.75729
+
+#ifndef MS45XX_SYNC_SEND
+#define MS45XX_SYNC_SEND FALSE
+#endif
+
+struct i2c_transaction ms45xx_trans;
+struct AirspeedMs45xx ms45xx;
+
+
+/** Quadratic scale factor for airspeed.
+ * airspeed = sqrt(2*p_diff/density)
+ * With p_diff in Pa and standard air density of 1.225 kg/m^3,
+ * default airspeed scale is 2/1.225
+ */
+#ifndef MS45XX_AIRSPEED_SCALE
+#define MS45XX_AIRSPEED_SCALE 1.6327
+#endif
+
+#include "mcu_periph/uart.h"
+#include "messages.h"
+#include "subsystems/datalink/downlink.h"
+
+#if PERIODIC_TELEMETRY
+#include "subsystems/datalink/telemetry.h"
+#endif
+
+static void ms45xx_downlink(void)
+{
+ DOWNLINK_SEND_MS45XX_AIRSPEED(DefaultChannel, DefaultDevice,
+ &ms45xx.diff_pressure,
+ &ms45xx.temperature, &ms45xx.airspeed);
+}
+
+void ms45xx_i2c_init(void)
+{
+ ms45xx.diff_pressure = 0;
+ ms45xx.temperature = 0;
+ ms45xx.airspeed = 0.;
+ ms45xx.sync_send = MS45XX_SYNC_SEND;
+
+#if MS45XX_OUTPUT_TYPE == 0
+ /* Offset and scaling for OUTPUT TYPE A:
+ * p_raw = (0.8*16383)/ (Pmax - Pmin) * (pressure - Pmin) + 0.1*16383
+ * For differential sensors Pmax = MS45XX_PRESSURE_RANGE = -Pmin.
+ *
+ * p_diff = (p_raw - 0.1*16383) * 2*RANGE/(0.8*16383) - RANGE
+ * p_diff = p_raw * 2*RANGE/(0.8*16383) - (RANGE + (0.1 * 16383) * 2*RANGE/(0.8*16383)
+ * p_diff = p_raw * 2*RANGE/(0.8*16383) - (1.25 * RANGE)
+ * p_diff = p_raw * scale - offset
+ * then convert to Pascal
+ */
+ ms45xx.pressure_scale = 2 * MS45XX_PRESSURE_RANGE / (0.8 * 16383) * PSI_TO_PA;
+ ms45xx.pressure_offset = 1.25 * MS45XX_PRESSURE_RANGE * PSI_TO_PA;
+#else
+ /* Offset and scaling for OUTPUT TYPE B:
+ * p_raw = (0.9*16383)/ (Pmax - Pmin) * (pressure - Pmin) + 0.05*16383
+ */
+ ms45xx.pressure_scale = 2 * MS45XX_PRESSURE_RANGE / (0.9 * 16383) * PSI_TO_PA;
+ ms45xx.pressure_offset = (1.0 + 0.1 / 0.9) * MS45XX_PRESSURE_RANGE * PSI_TO_PA;
+#endif
+
+ ms45xx_trans.status = I2CTransDone;
+
+#if PERIODIC_TELEMETRY
+ register_periodic_telemetry(DefaultPeriodic, "MS45XX_AIRSPEED", ms45xx_downlink);
+#endif
+}
+
+void ms45xx_i2c_periodic(void)
+{
+ // Initiate next read
+ if (ms45xx_trans.status == I2CTransDone) {
+ i2c_receive(&MS45XX_I2C_DEV, &ms45xx_trans, MS45XX_I2C_ADDR, 4);
+ }
+}
+
+void ms45xx_i2c_event(void)
+{
+ /* Check if transaction is succesfull */
+ if (ms45xx_trans.status == I2CTransSuccess) {
+
+ /* 2 MSB of data are status bits, 0 = good data, 2 = already fetched, 3 = fault */
+ uint8_t status = (0xC0 & ms45xx_trans.buf[0]) >> 6;
+
+ if (status == 0) {
+ /* 14bit raw pressure */
+ uint16_t p_raw = 0x3FFF & (((uint16_t)(ms45xx_trans.buf[0]) << 8) |
+ (uint16_t)(ms45xx_trans.buf[1]));
+ /* Output is proportional to the difference between Port 1 and Port 2. Output
+ * swings positive when Port 1> Port 2. Output is 50% of total counts
+ * when Port 1=Port 2.
+ * p_diff = p_raw * scale - offset
+ */
+ ms45xx.diff_pressure = p_raw * ms45xx.pressure_scale - ms45xx.pressure_offset;
+
+ /* 11bit raw temperature, 5 LSB bits not used */
+ uint16_t temp_raw = 0xFFE0 & (((uint16_t)(ms45xx_trans.buf[2]) << 8) |
+ (uint16_t)(ms45xx_trans.buf[3]));
+ temp_raw = temp_raw >> 5;
+ /* 0 = -50degC, 20147 = 150degC
+ * ms45xx_temperature in 0.1 deg Celcius
+ */
+ ms45xx.temperature = ((uint32_t)temp_raw * 2000) / 2047 - 500;
+
+ // Compute airspeed
+ ms45xx.airspeed = sqrtf(ms45xx.diff_pressure * ms45xx.airspeed_scale);
+#if USE_AIRSPEED
+ stateSetAirspeed_f(&ms45xx_airspeed);
+#endif
+ if (ms45xx.sync_send) {
+ ms45xx_downlink();
+ }
+ }
+
+ // Set to done
+ ms45xx_trans.status = I2CTransDone;
+ } else if (ms45xx_trans.status == I2CTransFailed) {
+ // Just retry if failed
+ ms45xx_trans.status = I2CTransDone;
+ }
+}
diff --git a/sw/airborne/modules/sensors/airspeed_ms45xx_i2c.h b/sw/airborne/modules/sensors/airspeed_ms45xx_i2c.h
new file mode 100644
index 00000000000..6b95c3c863b
--- /dev/null
+++ b/sw/airborne/modules/sensors/airspeed_ms45xx_i2c.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 Freek van Tienen
+ * 2014 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, see
+ * .
+ */
+
+/** @file modules/sensors/airspeed_ms45xx_i2c.h
+ * Airspeed driver for the MS45xx via I2C.
+ */
+
+#ifndef AIRSPEED_MS45XX_I2C_H
+#define AIRSPEED_MS45XX_I2C_H
+
+#include "std.h"
+
+struct AirspeedMs45xx {
+ float diff_pressure; ///< differential pressure in Pascal
+ int16_t temperature; ///< temperature in 0.1 deg Celcius
+ float airspeed; ///< Airspeed in m/s estimated from differential pressure.
+ float airspeed_scale; ///< quadratic scale factor to convert differential pressure to airspeed
+ float pressure_scale; ///< scaling factor from raw measurement to Pascal
+ float pressure_offset; ///< offset in Pascal
+ bool_t sync_send; ///< flag to enable sending every new measurement via telemetry
+};
+
+extern struct AirspeedMs45xx ms45xx;
+
+extern void ms45xx_i2c_init(void);
+extern void ms45xx_i2c_periodic(void);
+extern void ms45xx_i2c_event(void);
+
+#endif