barometer plugin: cleanup whitespace
[collectd.git] / src / barometer.c
index 95b05f4..84ffdfc 100644 (file)
 /* ------------ MPL115 defines ------------ */
 /* I2C address of the MPL115 sensor */
 #define MPL115_I2C_ADDRESS          0x60
-                                    
-/* register addresses */            
+
+/* register addresses */
 #define MPL115_ADDR_CONV            0x00
 #define MPL115_ADDR_COEFFS          0x04
-                                    
-/* register sizes */                
+
+/* register sizes */
 #define MPL115_NUM_CONV             4
 #define MPL115_NUM_COEFFS           12
-                                    
-/* commands / addresses */          
+
+/* commands / addresses */
 #define MPL115_CMD_CONVERT_PRESS    0x10
 #define MPL115_CMD_CONVERT_TEMP     0x11
 #define MPL115_CMD_CONVERT_BOTH     0x12
-                                    
+
 #define MPL115_CONVERSION_RETRIES   5
 
 
 #define MPL3115_PT_DATA_DREM        0x04
 #define MPL3115_PT_DATA_PDEF        0x02
 #define MPL3115_PT_DATA_TDEF        0x01
-                                    
+
 #define MPL3115_DR_STATUS_TDR       0x02
 #define MPL3115_DR_STATUS_PDR       0x04
 #define MPL3115_DR_STATUS_PTDR      0x08
 #define MPL3115_DR_STATUS_DR        (MPL3115_DR_STATUS_TDR | MPL3115_DR_STATUS_PDR | MPL3115_DR_STATUS_PTDR)
-                                    
+
 #define MPL3115_DR_STATUS_TOW       0x20
 #define MPL3115_DR_STATUS_POW       0x40
 #define MPL3115_DR_STATUS_PTOW      0x80
 #define MPL3115_NUM_CONV_VALS       5
 
 
+/* ------------ BMP085 defines ------------ */
+/* I2C address of the BMP085 sensor */
+#define BMP085_I2C_ADDRESS          0x77
+
+/* register addresses */
+#define BMP085_ADDR_ID_REG          0xD0
+#define BMP085_ADDR_VERSION         0xD1
+
+#define BMP085_ADDR_CONV            0xF6
+
+#define BMP085_ADDR_CTRL_REG        0xF4
+#define BMP085_ADDR_COEFFS          0xAA
+
+/* register sizes */
+#define BMP085_NUM_COEFFS           22
+
+/* commands, values */
+#define BMP085_CHIP_ID              0x55
+
+#define BMP085_CMD_CONVERT_TEMP     0x2E
+
+#define BMP085_CMD_CONVERT_PRESS_0  0x34
+#define BMP085_CMD_CONVERT_PRESS_1  0x74
+#define BMP085_CMD_CONVERT_PRESS_2  0xB4
+#define BMP085_CMD_CONVERT_PRESS_3  0xF4
+
+/* in us */
+#define BMP085_TIME_CNV_TEMP        4500
+
+#define BMP085_TIME_CNV_PRESS_0     4500
+#define BMP085_TIME_CNV_PRESS_1     7500
+#define BMP085_TIME_CNV_PRESS_2    13500
+#define BMP085_TIME_CNV_PRESS_3    25500
+
+
 /* ------------ Normalization ------------ */
 /* Mean sea level pressure normalization methods */
 #define MSLP_NONE          0
 /** Temperature reference history depth for averaging. See #get_reference_temperature */
 #define REF_TEMP_AVG_NUM   5
 
+
 /* ------------------------------------------ */
+
+/** Supported sensor types */
+enum Sensor_type {
+    Sensor_none = 0,
+    Sensor_MPL115,
+    Sensor_MPL3115,
+    Sensor_BMP085
+};
+
 static const char *config_keys[] =
 {
     "Device",
@@ -133,7 +178,7 @@ static const char *config_keys[] =
 };
 
 static int    config_keys_num     = STATIC_ARRAY_SIZE(config_keys);
-                                  
+
 static char * config_device       = NULL;  /**< I2C bus device */
 static int    config_oversample   = 1;     /**< averaging window */
 
@@ -142,13 +187,19 @@ static double config_temp_offset  = 0.0;   /**< temperature offset */
 
 static double config_altitude     = NAN;   /**< altitude */
 static int    config_normalize    = 0;     /**< normalization method */
-                                  
+
 static _Bool  configured          = 0;     /**< the whole plugin config status */
-                                  
+
 static int    i2c_bus_fd          = -1;    /**< I2C bus device FD */
-                                  
-static _Bool  is_MPL3115          = 0;    /**< is this MPL3115? */
-static __s32  oversample_MPL3115  = 0;    /**< MPL3115 CTRL1 oversample setting */
+
+static enum Sensor_type sensor_type = Sensor_none; /**< detected/used sensor type */
+
+static __s32  mpl3115_oversample  = 0;    /**< MPL3115 CTRL1 oversample setting */
+
+// BMP085 configuration
+static unsigned      bmp085_oversampling; /**< BMP085 oversampling (0-3) */
+static unsigned long bmp085_timeCnvPress; /**< BMP085 conversion time for pressure in us */
+static __u8          bmp085_cmdCnvPress;  /**< BMP085 pressure conversion command */
 
 
 /* MPL115 conversion coefficients */
@@ -159,6 +210,21 @@ static double mpl115_coeffC12;
 static double mpl115_coeffC11;
 static double mpl115_coeffC22;
 
+/* BMP085 conversion coefficients */
+static short bmp085_AC1;
+static short bmp085_AC2;
+static short bmp085_AC3;
+static unsigned short bmp085_AC4;
+static unsigned short bmp085_AC5;
+static unsigned short bmp085_AC6;
+static short bmp085_B1;
+static short bmp085_B2;
+static short bmp085_MB;
+static short bmp085_MC;
+static short bmp085_MD;
+
+
+
 /* ------------------------ averaging ring buffer ------------------------ */
 /*  Used only for MPL115. MPL3115 supports real oversampling in the device so */
 /*  no need for any postprocessing. */
@@ -177,7 +243,7 @@ static averaging_t pressure_averaging    = { NULL, 0, 0L, 0 };
 static averaging_t temperature_averaging = { NULL, 0, 0L, 0 };
 
 
-/** 
+/**
  * Create / allocate averaging buffer
  *
  * The buffer is initialized with zeros.
@@ -187,11 +253,9 @@ static averaging_t temperature_averaging = { NULL, 0, 0L, 0 };
  *
  * @return Zero when successful
  */
-static int averaging_create(averaging_t * avg, int size)
+static int averaging_create(averaging_t *avg, int size)
 {
-    int a;
-
-    avg->ring_buffer = (long int *) malloc(size * sizeof(*avg));
+    avg->ring_buffer = calloc ((size_t) size, sizeof (*avg->ring_buffer));
     if (avg->ring_buffer == NULL)
     {
         ERROR ("barometer: averaging_create - ring buffer allocation of size %d failed",
@@ -199,11 +263,6 @@ static int averaging_create(averaging_t * avg, int size)
         return -1;
     }
 
-    for (a=0; a<size; ++a)
-    {
-      avg->ring_buffer[a] = 0L;
-    }
-
     avg->ring_buffer_size = size;
     avg->ring_buffer_sum  = 0L;
     avg->ring_buffer_head = 0;
@@ -250,9 +309,9 @@ static double averaging_add_sample(averaging_t * avg, long int sample)
     avg->ring_buffer[avg->ring_buffer_head] = sample;
     avg->ring_buffer_head = (avg->ring_buffer_head+1) % avg->ring_buffer_size;
     result = (double)(avg->ring_buffer_sum) / (double)(avg->ring_buffer_size);
-    
-    DEBUG ("barometer: averaging_add_sample - added %ld, result = %lf", 
-           sample, 
+
+    DEBUG ("barometer: averaging_add_sample - added %ld, result = %lf",
+           sample,
            result);
 
     return result;
@@ -415,7 +474,7 @@ static int get_reference_temperature(double * result)
             list = list->next;
             continue;
         }
-            
+
         for(i=0; i<REF_TEMP_AVG_NUM*list->num_values; ++i)
         {
             DEBUG ("barometer: get_reference_temperature - history %d: %lf",
@@ -474,7 +533,7 @@ static int get_reference_temperature(double * result)
         }
         list = list->next;
     }  /* while sensor list */
-    
+
     if(*result == NAN)
     {
         ERROR("barometer: get_reference_temperature - no sensor available (yet?)");
@@ -484,9 +543,45 @@ static int get_reference_temperature(double * result)
     return 0;
 }
 
+
 /* ------------------------ MPL115 access ------------------------ */
 
-/** 
+/**
+ * Detect presence of a MPL115 pressure sensor.
+ *
+ * Unfortunately there seems to be no ID register so we just try to read first
+ * conversion coefficient from device at MPL115 address and hope it is really
+ * MPL115. We should use this check as the last resort (which would be the typical
+ * case anyway since MPL115 is the least accurate sensor).
+ * As a sideeffect will leave set I2C slave address.
+ *
+ * @return 1 if MPL115, 0 otherwise
+ */
+static int MPL115_detect(void)
+{
+    __s32 res;
+    char errbuf[1024];
+
+    if (ioctl(i2c_bus_fd, I2C_SLAVE_FORCE, MPL115_I2C_ADDRESS) < 0)
+    {
+        ERROR("barometer: MPL115_detect problem setting i2c slave address to 0x%02X: %s",
+              MPL115_I2C_ADDRESS,
+              sstrerror (errno, errbuf, sizeof (errbuf)));
+        return 0 ;
+    }
+
+    res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL115_ADDR_COEFFS);
+    if(res >= 0)
+    {
+        DEBUG ("barometer: MPL115_detect - positive detection");
+        return 1;
+    }
+
+    DEBUG ("barometer: MPL115_detect - negative detection");
+    return 0;
+}
+
+/**
  * Read the MPL115 sensor conversion coefficients.
  *
  * These are (device specific) constants so we can read them just once.
@@ -495,26 +590,26 @@ static int get_reference_temperature(double * result)
  */
 static int MPL115_read_coeffs(void)
 {
-    uint8_t mpl115_coeffs[MPL115_NUM_COEFFS]
+    uint8_t mpl115_coeffs[MPL115_NUM_COEFFS] = { 0 };
     int32_t res;
 
     int8_t  sia0MSB, sia0LSB, sib1MSB, sib1LSB, sib2MSB, sib2LSB;
     int8_t  sic12MSB, sic12LSB, sic11MSB, sic11LSB, sic22MSB, sic22LSB;
     int16_t sia0, sib1, sib2, sic12, sic11, sic22;
-      
+
     char errbuf[1024];
 
-    res = i2c_smbus_read_i2c_block_data(i2c_bus_fd, 
-                                        MPL115_ADDR_COEFFS, 
-                                        MPL115_NUM_COEFFS, 
+    res = i2c_smbus_read_i2c_block_data(i2c_bus_fd,
+                                        MPL115_ADDR_COEFFS,
+                                        STATIC_ARRAY_SIZE (mpl115_coeffs),
                                         mpl115_coeffs);
     if (res < 0)
     {
-        ERROR ("barometer: read_mpl115_coeffs - problem reading data: %s",
+        ERROR ("barometer: MPL115_read_coeffs - problem reading data: %s",
                sstrerror (errno, errbuf, sizeof (errbuf)));
         return -1;
     }
-   
+
     /* Using perhaps less elegant/efficient code, but more readable. */
     /* a0: 16total 1sign 12int 4fract 0pad */
     sia0MSB = mpl115_coeffs[0];
@@ -523,7 +618,7 @@ static int MPL115_read_coeffs(void)
     sia0 += (int16_t) sia0LSB & 0x00FF;    /* Add LSB to 16bit number */
     mpl115_coeffA0 = (double) (sia0);
     mpl115_coeffA0 /= 8.0;                 /* 3 fract bits */
-    
+
     /* b1: 16total 1sign 2int 13fract 0pad */
     sib1MSB= mpl115_coeffs[2];
     sib1LSB= mpl115_coeffs[3];
@@ -531,7 +626,7 @@ static int MPL115_read_coeffs(void)
     sib1 += sib1LSB & 0x00FF;              /* Add LSB to 16bit number */
     mpl115_coeffB1 = (double) (sib1);
     mpl115_coeffB1 /= 8192.0;              /* 13 fract */
-    
+
     /* b2: 16total 1sign 1int 14fract 0pad */
     sib2MSB= mpl115_coeffs[4];
     sib2LSB= mpl115_coeffs[5];
@@ -567,18 +662,18 @@ static int MPL115_read_coeffs(void)
     mpl115_coeffC22 /= 32.0; //16-11=5
     mpl115_coeffC22 /= 33554432.0;          /* 10+15=25 fract */
 
-    DEBUG("barometer: read_mpl115_coeffs: a0=%lf, b1=%lf, b2=%lf, c12=%lf, c11=%lf, c22=%lf",
-          mpl115_coeffA0, 
-          mpl115_coeffB1, 
-          mpl115_coeffB2, 
-          mpl115_coeffC12, 
-          mpl115_coeffC11, 
+    DEBUG("barometer: MPL115_read_coeffs: a0=%lf, b1=%lf, b2=%lf, c12=%lf, c11=%lf, c22=%lf",
+          mpl115_coeffA0,
+          mpl115_coeffB1,
+          mpl115_coeffB2,
+          mpl115_coeffC12,
+          mpl115_coeffC11,
           mpl115_coeffC22);
     return 0;
 }
 
 
-/*
+/**
  * Convert raw adc values to real data using the sensor coefficients.
  *
  * @param adc_pressure adc pressure value to be converted
@@ -595,16 +690,16 @@ static void MPL115_convert_adc_to_real(double   adc_pressure,
     Pcomp = mpl115_coeffA0 +                                            \
         (mpl115_coeffB1 + mpl115_coeffC11*adc_pressure + mpl115_coeffC12*adc_temp) * adc_pressure + \
         (mpl115_coeffB2 + mpl115_coeffC22*adc_temp) * adc_temp;
-    
+
     *pressure = ((1150.0-500.0) * Pcomp / 1023.0) + 500.0;
     *temperature = (472.0 - adc_temp) / 5.35 + 25.0;
-    DEBUG ("barometer: convert_adc_to_real - got %lf hPa, %lf C",
+    DEBUG ("barometer: MPL115_convert_adc_to_real - got %lf hPa, %lf C",
            *pressure,
            *temperature);
 }
 
 
-/** 
+/**
  * Read sensor averegaed measurements
  *
  * @param pressure    averaged measured pressure
@@ -614,7 +709,7 @@ static void MPL115_convert_adc_to_real(double   adc_pressure,
  */
 static int MPL115_read_averaged(double * pressure, double * temperature)
 {
-    uint8_t mpl115_conv[MPL115_NUM_CONV]
+    uint8_t mpl115_conv[MPL115_NUM_CONV] = { 0 };
     int8_t  res;
     int     retries;
     int     conv_pressure;
@@ -625,7 +720,7 @@ static int MPL115_read_averaged(double * pressure, double * temperature)
 
     *pressure    = 0.0;
     *temperature = 0.0;
-   
+
     /* start conversion of both temp and presure */
     retries = MPL115_CONVERSION_RETRIES;
     while (retries>0)
@@ -661,8 +756,8 @@ static int MPL115_read_averaged(double * pressure, double * temperature)
     {
         res = i2c_smbus_read_i2c_block_data(i2c_bus_fd,
                                             MPL115_ADDR_CONV,
-                                            MPL115_NUM_CONV,
-                                            mpl115_conv); 
+                                            STATIC_ARRAY_SIZE (mpl115_conv),
+                                            mpl115_conv);
         if (res >= 0)
             break;
 
@@ -682,7 +777,7 @@ static int MPL115_read_averaged(double * pressure, double * temperature)
             return -1;
         }
     }
-    
+
     conv_pressure    = ((mpl115_conv[0] << 8) | mpl115_conv[1]) >> 6;
     conv_temperature = ((mpl115_conv[2] << 8) | mpl115_conv[3]) >> 6;
     DEBUG ("barometer: MPL115_read_averaged, raw pressure ADC value = %d, " \
@@ -701,20 +796,31 @@ static int MPL115_read_averaged(double * pressure, double * temperature)
            adc_temperature,
            *pressure,
            *temperature);
-    
+
     return 0;
 }
 
 /* ------------------------ MPL3115 access ------------------------ */
 
-/** 
+/**
  * Detect presence of a MPL3115 pressure sensor by checking register "WHO AM I"
- * 
+ *
+ * As a sideeffect will leave set I2C slave address.
+ *
  * @return 1 if MPL3115, 0 otherwise
  */
 static int MPL3115_detect(void)
 {
     __s32 res;
+    char errbuf[1024];
+
+    if (ioctl(i2c_bus_fd, I2C_SLAVE_FORCE, MPL3115_I2C_ADDRESS) < 0)
+    {
+        ERROR("barometer: MPL3115_detect problem setting i2c slave address to 0x%02X: %s",
+              MPL3115_I2C_ADDRESS,
+              sstrerror (errno, errbuf, sizeof (errbuf)));
+        return 0 ;
+    }
 
     res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_WHO_AM_I);
     if(res == MPL3115_WHO_AM_I_RESP)
@@ -727,10 +833,10 @@ static int MPL3115_detect(void)
     return 0;
 }
 
-/** 
+/**
  * Adjusts oversampling to values supported by MPL3115
  *
- * MPL3115 supports only power of 2 in the range 1 to 128. 
+ * MPL3115 supports only power of 2 in the range 1 to 128.
  */
 static void MPL3115_adjust_oversampling(void)
 {
@@ -739,52 +845,52 @@ static void MPL3115_adjust_oversampling(void)
     if(config_oversample > 100)
     {
         new_val = 128;
-        oversample_MPL3115 = MPL3115_CTRL_REG1_OST_128;
+        mpl3115_oversample = MPL3115_CTRL_REG1_OST_128;
     }
     else if(config_oversample > 48)
     {
         new_val = 64;
-        oversample_MPL3115 = MPL3115_CTRL_REG1_OST_64;
+        mpl3115_oversample = MPL3115_CTRL_REG1_OST_64;
     }
     else if(config_oversample > 24)
     {
         new_val = 32;
-        oversample_MPL3115 = MPL3115_CTRL_REG1_OST_32;
+        mpl3115_oversample = MPL3115_CTRL_REG1_OST_32;
     }
     else if(config_oversample > 12)
     {
         new_val = 16;
-        oversample_MPL3115 = MPL3115_CTRL_REG1_OST_16;
+        mpl3115_oversample = MPL3115_CTRL_REG1_OST_16;
     }
     else if(config_oversample > 6)
     {
         new_val = 8;
-        oversample_MPL3115 = MPL3115_CTRL_REG1_OST_8;
+        mpl3115_oversample = MPL3115_CTRL_REG1_OST_8;
     }
     else if(config_oversample > 3)
     {
         new_val = 4;
-        oversample_MPL3115 = MPL3115_CTRL_REG1_OST_4;
+        mpl3115_oversample = MPL3115_CTRL_REG1_OST_4;
     }
     else if(config_oversample > 1)
     {
         new_val = 2;
-        oversample_MPL3115 = MPL3115_CTRL_REG1_OST_2;
+        mpl3115_oversample = MPL3115_CTRL_REG1_OST_2;
     }
     else
     {
         new_val = 1;
-        oversample_MPL3115 = MPL3115_CTRL_REG1_OST_1;
+        mpl3115_oversample = MPL3115_CTRL_REG1_OST_1;
     }
 
-    DEBUG("barometer: correcting oversampling for MPL3115 from %d to %d",
-          config_oversample, 
+    DEBUG("barometer: MPL3115_adjust_oversampling - correcting oversampling from %d to %d",
+          config_oversample,
           new_val);
     config_oversample = new_val;
 }
 
-/** 
- * Read sensor averegaed measurements
+/**
+ * Read sensor averaged measurements
  *
  * @param pressure    averaged measured pressure
  * @param temperature averaged measured temperature
@@ -798,7 +904,7 @@ static int MPL3115_read(double * pressure, double * temperature)
     __u8 data[MPL3115_NUM_CONV_VALS];
     long int tmp_value = 0;
     char errbuf[1024];
-    
+
     /* Set Active - activate the device from standby */
     res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_CTRL_REG1);
     if (res < 0)
@@ -808,8 +914,8 @@ static int MPL3115_read(double * pressure, double * temperature)
         return 1;
     }
     ctrl = res;
-    res = i2c_smbus_write_byte_data(i2c_bus_fd, 
-                                    MPL3115_REG_CTRL_REG1, 
+    res = i2c_smbus_write_byte_data(i2c_bus_fd,
+                                    MPL3115_REG_CTRL_REG1,
                                     ctrl | MPL3115_CTRL_REG1_SBYB);
     if (res < 0)
     {
@@ -817,10 +923,10 @@ static int MPL3115_read(double * pressure, double * temperature)
                sstrerror (errno, errbuf, sizeof (errbuf)));
         return 1;
     }
-    
+
     /* base sleep is 5ms x OST */
     usleep(5000 * config_oversample);
-      
+
     /* check the flags/status if ready */
     res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_STATUS);
     if (res < 0)
@@ -829,12 +935,12 @@ static int MPL3115_read(double * pressure, double * temperature)
                sstrerror (errno, errbuf, sizeof (errbuf)));
         return 1;
     }
-    
+
     while ((res & MPL3115_DR_STATUS_DR) != MPL3115_DR_STATUS_DR)
     {
         /* try some extra sleep... */
         usleep(10000);
-        
+
         /* ... and repeat the check. The conversion has to finish sooner or later. */
         res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_STATUS);
         if (res < 0)
@@ -844,10 +950,10 @@ static int MPL3115_read(double * pressure, double * temperature)
             return 1;
         }
     }
-    
+
     /* Now read all the data in one block. There is address autoincrement. */
-    res = i2c_smbus_read_i2c_block_data(i2c_bus_fd, 
-                                        MPL3115_REG_OUT_P_MSB, 
+    res = i2c_smbus_read_i2c_block_data(i2c_bus_fd,
+                                        MPL3115_REG_OUT_P_MSB,
                                         MPL3115_NUM_CONV_VALS,
                                         data);
     if (res < 0)
@@ -856,11 +962,11 @@ static int MPL3115_read(double * pressure, double * temperature)
                sstrerror (errno, errbuf, sizeof (errbuf)));
         return 1;
     }
-    
+
     tmp_value = (data[0] << 16) | (data[1] << 8) | data[2];
     *pressure = ((double) tmp_value) / 4.0 / 16.0 / 100.0;
-    DEBUG ("barometer: MPL3115_read, absolute pressure = %lf hPa", *pressure);
-    
+    DEBUG ("barometer: MPL3115_read - absolute pressure = %lf hPa", *pressure);
+
     if(data[3] > 0x7F)
     {
         data[3] = ~data[3] + 1;
@@ -871,16 +977,16 @@ static int MPL3115_read(double * pressure, double * temperature)
     {
         *temperature = data[3];
     }
-    
+
     *temperature += (double)(data[4]) / 256.0;
-    DEBUG ("barometer: MPL3115_read, temperature = %lf C", *temperature);
-    
+    DEBUG ("barometer: MPL3115_read - temperature = %lf C", *temperature);
+
     return 0;
 }
 
-/** 
+/**
  * Initialize MPL3115 for barometeric measurements
- * 
+ *
  * @return 0 if successful
  */
 static int MPL3115_init_sensor(void)
@@ -888,18 +994,18 @@ static int MPL3115_init_sensor(void)
     __s32 res;
     __s8 offset;
     char errbuf[1024];
-    
+
     /* Reset the sensor. It will reset immediately without ACKing */
     /* the transaction, so no error handling here. */
-    i2c_smbus_write_byte_data(i2c_bus_fd, 
-                              MPL3115_REG_CTRL_REG1, 
+    i2c_smbus_write_byte_data(i2c_bus_fd,
+                              MPL3115_REG_CTRL_REG1,
                               MPL3115_CTRL_REG1_RST);
-    
+
     /* wait some time for the reset to finish */
     usleep(100000);
 
     /* now it should be in standby already so we can go and configure it */
-    
+
     /*  Set temperature offset. */
     /*  result = ADCtemp + offset [C] */
     offset = (__s8) (config_temp_offset * 16.0);
@@ -910,7 +1016,7 @@ static int MPL3115_init_sensor(void)
                sstrerror (errno, errbuf, sizeof (errbuf)));
         return -1;
     }
-    
+
     /*  Set pressure offset. */
     /*  result = ADCpress + offset [hPa] */
     offset = (__s8) (config_press_offset * 100.0 / 4.0);
@@ -923,7 +1029,7 @@ static int MPL3115_init_sensor(void)
     }
 
     /* Enable Data Flags in PT_DATA_CFG - flags on both pressure and temp */
-    res = i2c_smbus_write_byte_data(i2c_bus_fd, 
+    res = i2c_smbus_write_byte_data(i2c_bus_fd,
                                     MPL3115_REG_PT_DATA_CFG,
                                     MPL3115_PT_DATA_DREM        \
                                     | MPL3115_PT_DATA_PDEF      \
@@ -935,10 +1041,10 @@ static int MPL3115_init_sensor(void)
         return -1;
     }
 
-    /* Set to barometer with an OSR */ 
-    res = i2c_smbus_write_byte_data(i2c_bus_fd, 
-                                    MPL3115_REG_CTRL_REG1, 
-                                    oversample_MPL3115);
+    /* Set to barometer with an OSR */
+    res = i2c_smbus_write_byte_data(i2c_bus_fd,
+                                    MPL3115_REG_CTRL_REG1,
+                                    mpl3115_oversample);
     if (res < 0)
     {
         ERROR ("barometer: MPL3115_init_sensor - problem configuring CTRL_REG1: %s",
@@ -949,6 +1055,327 @@ static int MPL3115_init_sensor(void)
     return 0;
 }
 
+/* ------------------------ BMP085 access ------------------------ */
+
+/**
+ * Detect presence of a BMP085 pressure sensor by checking its ID register
+ *
+ * As a sideeffect will leave set I2C slave address.
+ *
+ * @return 1 if BMP085, 0 otherwise
+ */
+static int BMP085_detect(void)
+{
+    __s32 res;
+    char errbuf[1024];
+
+    if (ioctl(i2c_bus_fd, I2C_SLAVE_FORCE, BMP085_I2C_ADDRESS) < 0)
+    {
+        ERROR("barometer: BMP085_detect - problem setting i2c slave address to 0x%02X: %s",
+              BMP085_I2C_ADDRESS,
+              sstrerror (errno, errbuf, sizeof (errbuf)));
+        return 0 ;
+    }
+
+    res = i2c_smbus_read_byte_data(i2c_bus_fd, BMP085_ADDR_ID_REG);
+    if(res == BMP085_CHIP_ID)
+    {
+        DEBUG ("barometer: BMP085_detect - positive detection");
+
+        /* get version */
+        res = i2c_smbus_read_byte_data(i2c_bus_fd, BMP085_ADDR_VERSION );
+        if (res < 0)
+        {
+            ERROR("barometer: BMP085_detect - problem checking chip version: %s",
+                  sstrerror (errno, errbuf, sizeof (errbuf)));
+            return 0 ;
+        }
+        DEBUG ("barometer: BMP085_detect - chip version ML:0x%02X AL:0x%02X",
+               res & 0x0f,
+               (res & 0xf0) >> 4);
+        return 1;
+    }
+
+    DEBUG ("barometer: BMP085_detect - negative detection");
+    return 0;
+}
+
+
+/**
+ * Adjusts oversampling settings to values supported by BMP085
+ *
+ * BMP085 supports only 1,2,4 or 8 samples.
+ */
+static void BMP085_adjust_oversampling(void)
+{
+    int new_val = 0;
+
+    if( config_oversample > 6 ) /* 8 */
+    {
+        new_val = 8;
+        bmp085_oversampling = 3;
+        bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_3;
+        bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_3;
+    }
+    else if( config_oversample > 3 ) /* 4 */
+    {
+        new_val = 4;
+        bmp085_oversampling = 2;
+        bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_2;
+        bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_2;
+    }
+    else if( config_oversample > 1 ) /* 2 */
+    {
+        new_val = 2;
+        bmp085_oversampling = 1;
+        bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_1;
+        bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_1;
+    }
+    else /* 1 */
+    {
+        new_val = 1;
+        bmp085_oversampling = 0;
+        bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_0;
+        bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_0;
+    }
+
+    DEBUG("barometer: BMP085_adjust_oversampling - correcting oversampling from %d to %d",
+          config_oversample,
+          new_val);
+    config_oversample = new_val;
+}
+
+
+/**
+ * Read the BMP085 sensor conversion coefficients.
+ *
+ * These are (device specific) constants so we can read them just once.
+ *
+ * @return Zero when successful
+ */
+static int BMP085_read_coeffs(void)
+{
+    __s32 res;
+    __u8 coeffs[BMP085_NUM_COEFFS];
+    char errbuf[1024];
+
+    res = i2c_smbus_read_i2c_block_data(i2c_bus_fd,
+                                        BMP085_ADDR_COEFFS,
+                                        BMP085_NUM_COEFFS,
+                                        coeffs);
+    if (res < 0)
+    {
+        ERROR ("barometer: BMP085_read_coeffs - problem reading data: %s",
+               sstrerror (errno, errbuf, sizeof (errbuf)));
+        return -1;
+    }
+
+    bmp085_AC1 = ((int16_t)  coeffs[0]  <<8) | (int16_t)  coeffs[1];
+    bmp085_AC2 = ((int16_t)  coeffs[2]  <<8) | (int16_t)  coeffs[3];
+    bmp085_AC3 = ((int16_t)  coeffs[4]  <<8) | (int16_t)  coeffs[5];
+    bmp085_AC4 = ((uint16_t) coeffs[6]  <<8) | (uint16_t) coeffs[7];
+    bmp085_AC5 = ((uint16_t) coeffs[8]  <<8) | (uint16_t) coeffs[9];
+    bmp085_AC6 = ((uint16_t) coeffs[10] <<8) | (uint16_t) coeffs[11];
+    bmp085_B1 =  ((int16_t)  coeffs[12] <<8) | (int16_t)  coeffs[13];
+    bmp085_B2 =  ((int16_t)  coeffs[14] <<8) | (int16_t)  coeffs[15];
+    bmp085_MB =  ((int16_t)  coeffs[16] <<8) | (int16_t)  coeffs[17];
+    bmp085_MC =  ((int16_t)  coeffs[18] <<8) | (int16_t)  coeffs[19];
+    bmp085_MD =  ((int16_t)  coeffs[20] <<8) | (int16_t)  coeffs[21];
+
+    DEBUG("barometer: BMP085_read_coeffs - AC1=%d, AC2=%d, AC3=%d, AC4=%u,"\
+          " AC5=%u, AC6=%u, B1=%d, B2=%d, MB=%d, MC=%d, MD=%d",
+          bmp085_AC1,
+          bmp085_AC2,
+          bmp085_AC3,
+          bmp085_AC4,
+          bmp085_AC5,
+          bmp085_AC6,
+          bmp085_B1,
+          bmp085_B2,
+          bmp085_MB,
+          bmp085_MC,
+          bmp085_MD);
+
+    return 0;
+}
+
+
+/**
+ * Convert raw BMP085 adc values to real data using the sensor coefficients.
+ *
+ * @param adc_pressure adc pressure value to be converted
+ * @param adc_temp     adc temperature value to be converted
+ * @param pressure     computed real pressure
+ * @param temperature  computed real temperature
+ */
+static void BMP085_convert_adc_to_real(long adc_pressure,
+                                       long adc_temperature,
+                                       double * pressure,
+                                       double * temperature)
+
+{
+    long X1, X2, X3;
+    long B3, B5, B6;
+    unsigned long B4, B7;
+
+    long T;
+    long P;
+
+
+    /* calculate real temperature */
+    X1 = ( (adc_temperature - bmp085_AC6) * bmp085_AC5) >> 15;
+    X2 = (bmp085_MC << 11) / (X1 + bmp085_MD);
+
+    /* B5, T */
+    B5 = X1 + X2;
+    T = (B5 + 8) >> 4;
+    *temperature = (double)T * 0.1;
+
+    /* calculate real pressure */
+    /* in general X1, X2, X3 are recycled while values of B3, B4, B5, B6 are kept */
+
+    /* B6, B3 */
+    B6 = B5 - 4000;
+    X1 = ((bmp085_B2 * ((B6 * B6)>>12)) >> 11 );
+    X2 = (((long)bmp085_AC2 * B6) >> 11);
+    X3 = X1 + X2;
+    B3 = (((((long)bmp085_AC1 * 4) + X3) << bmp085_oversampling) + 2) >> 2;
+
+    /* B4 */
+    X1 = (((long)bmp085_AC3*B6) >> 13);
+    X2 = (bmp085_B1*((B6*B6) >> 12) ) >> 16;
+    X3 = ((X1 + X2) + 2 ) >> 2;
+    B4 = ((long)bmp085_AC4* (unsigned long)(X3 + 32768)) >> 15;
+
+    /* B7, P */
+    B7 =  (unsigned long)(adc_pressure - B3)*(50000>>bmp085_oversampling);
+    if( B7 < 0x80000000 )
+    {
+        P = (B7 << 1) / B4;
+    }
+    else
+    {
+        P = (B7/B4) << 1;
+    }
+    X1 = (P >> 8) * (P >> 8);
+    X1 = (X1 * 3038) >> 16;
+    X2 = ((-7357) * P) >> 16;
+    P = P + ( ( X1 + X2 + 3791 ) >> 4);
+
+    *pressure = P / 100.0; // in [hPa]
+    DEBUG ("barometer: BMP085_convert_adc_to_real - got %lf hPa, %lf C",
+           *pressure,
+           *temperature);
+}
+
+
+/**
+ * Read compensated sensor measurements
+ *
+ * @param pressure    averaged measured pressure
+ * @param temperature averaged measured temperature
+ *
+ * @return Zero when successful
+ */
+static int BMP085_read(double * pressure, double * temperature)
+{
+    __s32 res;
+    __u8 measBuff[3];
+
+    long adc_pressure;
+    long adc_temperature;
+
+    char errbuf[1024];
+
+    /* start conversion of temperature */
+    res = i2c_smbus_write_byte_data( i2c_bus_fd,
+                                     BMP085_ADDR_CTRL_REG,
+                                     BMP085_CMD_CONVERT_TEMP );
+    if (res < 0)
+    {
+        ERROR ("barometer: BMP085_read - problem requesting temperature conversion: %s",
+               sstrerror (errno, errbuf, sizeof (errbuf)));
+        return 1;
+    }
+
+    usleep(BMP085_TIME_CNV_TEMP); /* wait for the conversion */
+
+    res = i2c_smbus_read_i2c_block_data( i2c_bus_fd,
+                                         BMP085_ADDR_CONV,
+                                         2,
+                                         measBuff);
+    if (res < 0)
+    {
+        ERROR ("barometer: BMP085_read - problem reading temperature data: %s",
+               sstrerror (errno, errbuf, sizeof (errbuf)));
+        return 1;
+    }
+
+    adc_temperature = ( (unsigned short)measBuff[0] << 8 ) + measBuff[1];
+
+
+    /* get presure */
+    res = i2c_smbus_write_byte_data( i2c_bus_fd,
+                                     BMP085_ADDR_CTRL_REG,
+                                     bmp085_cmdCnvPress );
+    if (res < 0)
+    {
+        ERROR ("barometer: BMP085_read - problem requesting pressure conversion: %s",
+               sstrerror (errno, errbuf, sizeof (errbuf)));
+        return 1;
+    }
+
+    usleep(bmp085_timeCnvPress); /* wait for the conversion */
+
+    res = i2c_smbus_read_i2c_block_data( i2c_bus_fd,
+                                         BMP085_ADDR_CONV,
+                                         3,
+                                         measBuff );
+    if (res < 0)
+    {
+        ERROR ("barometer: BMP085_read - problem reading pressure data: %s",
+               sstrerror (errno, errbuf, sizeof (errbuf)));
+        return 1;
+    }
+
+    adc_pressure = (long)((((ulong)measBuff[0]<<16) | ((ulong)measBuff[1]<<8) | (ulong)measBuff[2] ) >> (8 - bmp085_oversampling));
+
+
+    DEBUG ("barometer: BMP085_read - raw pressure ADC value = %ld, " \
+           "raw temperature ADC value = %ld",
+           adc_pressure,
+           adc_temperature);
+
+    BMP085_convert_adc_to_real(adc_pressure, adc_temperature, pressure, temperature);
+
+    return 0;
+}
+
+
+
+/* ------------------------ Sensor detection ------------------------ */
+/**
+ * Detect presence of a supported sensor.
+ *
+ * As a sideeffect will leave set I2C slave address.
+ * The detection is done in the order BMP085, MPL3115, MPL115 and stops after
+ * first sensor beeing found.
+ *
+ * @return detected sensor type
+ */
+enum Sensor_type Detect_sensor_type(void)
+{
+    if(BMP085_detect())
+        return Sensor_BMP085;
+
+    else if(MPL3115_detect())
+        return Sensor_MPL3115;
+
+    else if(MPL115_detect())
+        return Sensor_MPL115;
+
+    return Sensor_none;
+}
 
 /* ------------------------ Common functionality ------------------------ */
 
@@ -961,7 +1388,7 @@ static int MPL3115_init_sensor(void)
  * - MSLP_INTERNATIONAL - see http://en.wikipedia.org/wiki/Atmospheric_pressure#Altitude_atmospheric_pressure_variation
  *           Requires #config_altitude
  *
- * - MSLP_DEU_WETT - formula as recommended by the Deutsche Wetterdienst. See 
+ * - MSLP_DEU_WETT - formula as recommended by the Deutsche Wetterdienst. See
  *                http://de.wikipedia.org/wiki/Barometrische_H%C3%B6henformel#Theorie
  *           Requires both #config_altitude and temperature reference(s).
  *
@@ -975,10 +1402,6 @@ static double abs_to_mean_sea_level_pressure(double abs_pressure)
     double temp = 0.0;
     int result = 0;
 
-    DEBUG ("barometer: abs_to_mean_sea_level_pressure: absPressure = %lf, method = %d",
-           abs_pressure,
-           config_normalize);
-
     if (config_normalize >= MSLP_DEU_WETT)
     {
         result = get_reference_temperature(&temp);
@@ -993,12 +1416,12 @@ static double abs_to_mean_sea_level_pressure(double abs_pressure)
     case MSLP_NONE:
         mean = abs_pressure;
         break;
-        
+
     case MSLP_INTERNATIONAL:
         mean = abs_pressure / \
-            pow(1.0 - 0.0065*config_altitude/288.15, 0.0065*0.0289644/(8.31447*0.0065));
+            pow(1.0 - 0.0065*config_altitude/288.15, 9.80665*0.0289644/(8.31447*0.0065));
         break;
-        
+
     case MSLP_DEU_WETT:
     {
         double E; /* humidity */
@@ -1013,23 +1436,28 @@ static double abs_to_mean_sea_level_pressure(double abs_pressure)
     break;
 
     default:
-        ERROR ("barometer: abs_to_mean_sea_level_pressure: wrong conversion method %d", 
+        ERROR ("barometer: abs_to_mean_sea_level_pressure: wrong conversion method %d",
                config_normalize);
         mean = abs_pressure;
         break;
     }
 
-    return mean; 
+    DEBUG ("barometer: abs_to_mean_sea_level_pressure: absPressure = %lf hPa, method = %d, meanPressure = %lf hPa",
+           abs_pressure,
+           config_normalize,
+           mean);
+
+    return mean;
 }
 
 /* ------------------------ main plugin callbacks ------------------------ */
 
-/** 
+/**
  * Main plugin configuration callback (using simple config)
- * 
+ *
  * @param key   configuration key we should process
  * @param value configuration value we should process
- * 
+ *
  * @return Zero when successful.
  */
 static int collectd_barometer_config (const char *key, const char *value)
@@ -1047,7 +1475,7 @@ static int collectd_barometer_config (const char *key, const char *value)
         if (oversampling_tmp < 1 || oversampling_tmp > 1024)
         {
             WARNING ("barometer: collectd_barometer_config: invalid oversampling: %d." \
-                     " Allowed values are 1 to 1024 (for MPL115) or 128 (for MPL3115).",
+                     " Allowed values are 1 to 1024 (for MPL115) or 1 to 128 (for MPL3115) or 1 to 8 (for BMP085).",
                      oversampling_tmp);
             return 1;
         }
@@ -1083,7 +1511,7 @@ static int collectd_barometer_config (const char *key, const char *value)
     {
         config_temp_offset = atof(value);
     }
-    else 
+    else
     {
         return -1;
     }
@@ -1092,18 +1520,18 @@ static int collectd_barometer_config (const char *key, const char *value)
 }
 
 
-/** 
+/**
  * Shutdown callback.
- * 
+ *
  * Close I2C and delete all the buffers.
- * 
+ *
  * @return Zero when successful (at the moment the only possible outcome)
  */
 static int collectd_barometer_shutdown(void)
 {
     DEBUG ("barometer: collectd_barometer_shutdown");
 
-    if(!is_MPL3115)
+    if(sensor_type == Sensor_MPL115)
     {
         averaging_delete (&pressure_averaging);
         averaging_delete (&temperature_averaging);
@@ -1122,9 +1550,9 @@ static int collectd_barometer_shutdown(void)
 }
 
 
-/** 
+/**
  * Plugin read callback for MPL115.
- * 
+ *
  *  Dispatching will create values:
  *  - <hostname>/barometer-mpl115/pressure-normalized
  *  - <hostname>/barometer-mpl115/pressure-absolute
@@ -1142,7 +1570,7 @@ static int MPL115_collectd_barometer_read (void)
 
     value_list_t vl = VALUE_LIST_INIT;
     value_t      values[1];
-    
+
     DEBUG("barometer: MPL115_collectd_barometer_read");
 
     if (!configured)
@@ -1204,9 +1632,9 @@ static int MPL115_collectd_barometer_read (void)
 }
 
 
-/** 
+/**
  * Plugin read callback for MPL3115.
- * 
+ *
  *  Dispatching will create values:
  *  - <hostname>/barometer-mpl3115/pressure-normalized
  *  - <hostname>/barometer-mpl3115/pressure-absolute
@@ -1217,21 +1645,21 @@ static int MPL115_collectd_barometer_read (void)
 static int MPL3115_collectd_barometer_read (void)
 {
     int result = 0;
-    
+
     double pressure        = 0.0;
     double temperature     = 0.0;
     double norm_pressure   = 0.0;
-    
+
     value_list_t vl = VALUE_LIST_INIT;
     value_t      values[1];
-    
+
     DEBUG("barometer: MPL3115_collectd_barometer_read");
-    
+
     if (!configured)
     {
         return -1;
     }
-    
+
     result = MPL3115_read(&pressure, &temperature);
     if(result)
         return result;
@@ -1267,12 +1695,75 @@ static int MPL3115_collectd_barometer_read (void)
 }
 
 
-/** 
+/**
+ * Plugin read callback for BMP085.
+ *
+ *  Dispatching will create values:
+ *  - <hostname>/barometer-bmp085/pressure-normalized
+ *  - <hostname>/barometer-bmp085/pressure-absolute
+ *  - <hostname>/barometer-bmp085/temperature
+ *
+ * @return Zero when successful.
+ */
+static int BMP085_collectd_barometer_read (void)
+{
+    int result = 0;
+
+    double pressure        = 0.0;
+    double temperature     = 0.0;
+    double norm_pressure   = 0.0;
+
+    value_list_t vl = VALUE_LIST_INIT;
+    value_t      values[1];
+
+    DEBUG("barometer: BMP085_collectd_barometer_read");
+
+    if (!configured)
+    {
+        return -1;
+    }
+
+    result = BMP085_read(&pressure, &temperature);
+    if(result)
+        return result;
+
+    norm_pressure = abs_to_mean_sea_level_pressure(pressure);
+
+    sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+    sstrncpy (vl.plugin, "barometer", sizeof (vl.plugin));
+    sstrncpy (vl.plugin_instance, "bmp085", sizeof (vl.plugin_instance));
+
+    vl.values_len = 1;
+    vl.values = values;
+
+    /* dispatch normalized air pressure */
+    sstrncpy (vl.type, "pressure", sizeof (vl.type));
+    sstrncpy (vl.type_instance, "normalized", sizeof (vl.type_instance));
+    values[0].gauge = norm_pressure;
+    plugin_dispatch_values (&vl);
+
+    /* dispatch absolute air pressure */
+    sstrncpy (vl.type, "pressure", sizeof (vl.type));
+    sstrncpy (vl.type_instance, "absolute", sizeof (vl.type_instance));
+    values[0].gauge = pressure;
+    plugin_dispatch_values (&vl);
+
+    /* dispatch sensor temperature */
+    sstrncpy (vl.type, "temperature", sizeof (vl.type));
+    sstrncpy (vl.type_instance, "", sizeof (vl.type_instance));
+    values[0].gauge = temperature;
+    plugin_dispatch_values (&vl);
+
+    return 0;
+}
+
+
+/**
  * Initialization callback
- * 
+ *
  * Check config, initialize I2C bus access, conversion coefficients and averaging
  * ring buffers
- * 
+ *
  * @return Zero when successful.
  */
 static int collectd_barometer_init (void)
@@ -1313,19 +1804,14 @@ static int collectd_barometer_init (void)
         return -1;
     }
 
-    if (ioctl(i2c_bus_fd, I2C_SLAVE_FORCE, MPL115_I2C_ADDRESS) < 0)
-    {
-        ERROR("barometer: collectd_barometer_init problem setting i2c slave address to 0x%02X: %s",
-              MPL115_I2C_ADDRESS,
-              sstrerror (errno, errbuf, sizeof (errbuf)));
-        return -1;
-    }
-
-    /* detect sensor type - MPL115 or MPL3115 */
-    is_MPL3115 = MPL3115_detect();
+    /* detect sensor type - this will also set slave address */
+    sensor_type = Detect_sensor_type();
 
     /* init correct sensor type */
-    if(is_MPL3115) /* MPL3115 */
+    switch(sensor_type)
+    {
+/* MPL3115 */
+    case Sensor_MPL3115:
     {
         MPL3115_adjust_oversampling();
 
@@ -1334,25 +1820,48 @@ static int collectd_barometer_init (void)
 
         plugin_register_read ("barometer", MPL3115_collectd_barometer_read);
     }
-    else /* MPL115 */
+    break;
+
+/* MPL115 */
+    case Sensor_MPL115:
     {
         if (averaging_create (&pressure_averaging, config_oversample))
         {
             ERROR("barometer: collectd_barometer_init pressure averaging init failed");
             return -1;
         }
-        
+
         if (averaging_create (&temperature_averaging, config_oversample))
         {
             ERROR("barometer: collectd_barometer_init temperature averaging init failed");
             return -1;
         }
-        
+
         if (MPL115_read_coeffs() < 0)
             return -1;
 
         plugin_register_read ("barometer", MPL115_collectd_barometer_read);
     }
+    break;
+
+/* BMP085 */
+    case Sensor_BMP085:
+    {
+        BMP085_adjust_oversampling();
+
+        if (BMP085_read_coeffs() < 0)
+            return -1;
+
+        plugin_register_read ("barometer", BMP085_collectd_barometer_read);
+    }
+    break;
+
+/* anything else -> error */
+    default:
+        ERROR("barometer: collectd_barometer_init - no supported sensor found");
+        return -1;
+    }
+
 
     configured = 1;
     return 0;
@@ -1360,15 +1869,15 @@ static int collectd_barometer_init (void)
 
 /* ------------------------ plugin register / entry point ------------------------ */
 
-/** 
+/**
  * Plugin "entry" - register all callback.
- * 
+ *
  */
 void module_register (void)
 {
-    plugin_register_config ("barometer", 
-                            collectd_barometer_config, 
-                            config_keys, 
+    plugin_register_config ("barometer",
+                            collectd_barometer_config,
+                            config_keys,
                             config_keys_num);
     plugin_register_init ("barometer", collectd_barometer_init);
     plugin_register_shutdown ("barometer", collectd_barometer_shutdown);