BME680 is an integrated environmental sensor developed specifically for mobile applications and wearables where size and low power consumption are key requirements.

Dependents:   Example_DS3231_test

Files at this revision

API Documentation at this revision

Comitter:
yangcq88517
Date:
Fri Jul 22 17:38:11 2016 +0000
Child:
1:85088a918342
Commit message:
initial upload

Changed in this revision

BME680.cpp Show annotated file Show diff for this revision Revisions of this file
BME680.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BME680.cpp	Fri Jul 22 17:38:11 2016 +0000
@@ -0,0 +1,725 @@
+#include "BME680.h"
+
+// no idea why this is not the same as the PDF
+//const double BME680::const_array1[16] = {1,1,1,1,1,0.99,1,0.992,1,1,0.998,0.995,1,0.99,1,1};
+//const double BME680::const_array2[16] = {8000000,4000000,2000000,1000000,499500.4995,248262.1648,125000,63004.03226,31281.28128,15625,7812.5,3906.25,1953.125,976.5625,488.28125,244.140625};
+
+
+const uint64_t BME680::lookup_k1_range[16] = {
+        2147483647UL, 2147483647UL, 2147483647UL, 2147483647UL, 2147483647UL,
+        2126008810UL, 2147483647UL, 2130303777UL, 2147483647UL, 2147483647UL,
+        2143188679UL, 2136746228UL, 2147483647UL, 2126008810UL, 2147483647UL,
+        2147483647UL
+                                             };
+
+const uint64_t BME680::lookup_k2_range[16] = {
+        4096000000UL, 2048000000UL, 1024000000UL, 512000000UL,
+        255744255UL, 127110228UL, 64000000UL, 32258064UL, 16016016UL,
+        8000000UL, 4000000UL, 2000000UL, 1000000UL, 500000UL, 250000UL,
+        125000UL
+                                             };
+
+const double BME680::_lookup_k1_range[BME680_GAS_RANGE_RL_LENGTH] = {
+    0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, -0.8,
+    0.0, 0.0, -0.2, -0.5, 0.0, -1.0, 0.0, 0.0
+};
+const double BME680::_lookup_k2_range[BME680_GAS_RANGE_RL_LENGTH] = {
+    0.0, 0.0, 0.0, 0.0, 0.1, 0.7, 0.0, -0.8,
+    -0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
+};
+
+
+#ifdef FIXED_POINT_COMPENSATION
+int32_t BME680::getCompensatedTemperature(int field)
+{
+    uint32_t v_uncomp_temperature_u32 = getTemp1Data(field);
+
+    int32_t var1 = ((int32_t)v_uncomp_temperature_u32 >> 3) - ((int32_t)(par_T1 << 1));
+    int32_t var2 = (var1 * (int32_t) par_T2) >> 11;
+    int32_t var3 = ((((var1 >> 1) * (var1 >> 1)) >> 12) * ((int32_t)(par_T3 << 4))) >> 14;
+    t_fine = var2 + var3;
+    return ((t_fine * 5) + 128) >> 8;
+}
+
+int16_t BME680::getTemperatureInt(int field)
+{
+    getCompensatedTemperature(field);
+    return (((t_fine - 122880) * 25) + 128) >> 8;
+}
+
+int32_t BME680::getCompensateHumidity(int field)
+{
+    uint32_t v_uncomp_humidity_u32 = getHumidityData(field);
+
+    int32_t temp_scaled = (t_fine * 5 + 128) >> 8;
+    int32_t var1 = (int32_t)v_uncomp_humidity_u32 -
+                   ((int32_t)((int32_t)par_H1 << 4)) -
+                   (((temp_scaled * (int32_t)par_H3) /
+                     ((int32_t)100)) >> 1);
+
+    int32_t var2 = ((int32_t)par_H2 *
+                    (((temp_scaled * (int32_t)par_H4) /
+                      ((int32_t)100)) + (((temp_scaled *
+                                           ((temp_scaled * (int32_t)par_H5) /
+                                            ((int32_t)100))) >> 6) / ((int32_t)100)) + (int32_t)(1 << 14))) >> 10;
+
+    int32_t var3 = var1 * var2;
+
+    int32_t var4 = ((((int32_t)par_H6) << 7) +
+                    ((temp_scaled * (int32_t)par_H7) /
+                     ((int32_t)100))) >> 4;
+
+    int32_t var5 = ((var3 >> 14) * (var3 >> 14)) >> 10;
+    int32_t var6 = (var4 * var5) >> 1;
+
+    int32_t humidity_comp = (var3 + var6) >> 12;
+    if (humidity_comp > BME680_MAX_HUMIDITY_VALUE)
+        humidity_comp = BME680_MAX_HUMIDITY_VALUE;
+    else if (humidity_comp < BME680_MIN_HUMIDITY_VALUE)
+        humidity_comp = BME680_MIN_HUMIDITY_VALUE;
+
+    return humidity_comp;
+}
+
+uint16_t BME680::getHumidityInt(int field)
+{
+    uint32_t v_x1_u32 = (uint32_t) getCompensateHumidity(field);
+    uint16_t v_x2_u32 = (uint16_t)(v_x1_u32 >> 1);
+    return v_x2_u32;
+}
+
+int32_t BME680::getCompensatePressure(int field)
+{
+    uint32_t v_uncomp_pressure_u32 = getPressureData(field);
+
+    int32_t var1 = (((int32_t)t_fine) >> 1) - 64000;
+    int32_t var2 = ((((var1 >> 2) * (var1 >> 2)) >> 11) * (int32_t)par_P6) >> 2;
+    var2 = var2 + ((var1 * (int32_t)par_P5) << 1);
+    var2 = (var2 >> 2) + ((int32_t)par_P4 << 16);
+    var1 = (((((var1 >> 2) * (var1 >> 2)) >> 13) *
+             ((int32_t)par_P3 << 5)) >> 3) +
+           (((int32_t)par_P2 * var1) >> 1);
+    var1 = var1 >> 18;
+    var1 = ((32768 + var1) * (int32_t)par_P1) >> 15;
+    int32_t pressure_comp = 1048576 - v_uncomp_pressure_u32;
+    pressure_comp = (int32_t)((pressure_comp - (var2 >> 12)) * ((int32_t)3125));
+    int32_t var4 = (1 << 31);
+    if (pressure_comp >= var4)
+        pressure_comp = ((pressure_comp / (int32_t)var1) << 1);
+    else
+        pressure_comp = ((pressure_comp << 1) / (int32_t)var1);
+    var1 = ((int32_t)par_P9 * (int32_t)(((pressure_comp >> 3) *
+                                         (pressure_comp >> 3)) >> 13)) >> 12;
+    var2 = ((int32_t)(pressure_comp >> 2) *
+            (int32_t)par_P8) >> 13;
+    int32_t var3 = ((int32_t)(pressure_comp >> 8) * (int32_t)(pressure_comp >> 8) *
+                    (int32_t)(pressure_comp >> 8) *
+                    (int32_t)par_P10) >> 17;
+
+    pressure_comp = (int32_t)(pressure_comp) + ((var1 + var2 + var3 +
+                    ((int32_t)par_P7 << 7)) >> 4);
+
+    return pressure_comp;
+}
+
+uint32_t BME680::getPressureInt(int field)
+{
+    uint32_t pressure = (uint32_t)getCompensatePressure(field);
+    pressure = (uint32_t)(pressure >> 1);
+    return pressure;
+}
+
+uint8_t BME680::convertTemperatureResistanceInt(uint16_t heater, int16_t ambient)
+{
+    uint8_t res_heat = 0;
+
+
+    if ((heater >= BME680_GAS_PROFILE_TEMPERATURE_MIN)
+            && (heater <= BME680_GAS_PROFILE_TEMPERATURE_MAX)) {
+
+        int32_t var1 = (((int32_t)ambient * par_GH3) / 10) << 8;
+        int32_t var2 = (par_GH1 + 784) *
+                       (((((par_GH2 + 154009) *
+                           heater * 5) / 100) + 3276800) / 10);
+        int32_t var3 = var1 + (var2 >> 1);
+        int32_t var4 = (var3 / (res_heat_range + 4));
+
+        int32_t var5 = (131 * res_heat_val) + 65536;
+
+        int32_t res_heat_x100 = (int32_t)(((var4 / var5) - 250) * 34);
+        res_heat = (uint8_t) ((res_heat_x100 + 50) / 100);
+
+    }
+    return res_heat;
+}
+
+int32_t BME680::getCalculateGasInt(int field)
+{
+    uint8_t gas_range_u8 = getGasResistanceRange(field);
+    uint16_t gas_adc_u16 = getGasResistanceData(field);
+
+    int64_t var1 = (int64_t)((1340 + (5 * (int64_t)range_switching_error)) *
+                             ((int64_t)lookup_k1_range[gas_range_u8])) >> 16;
+    int64_t var2 = (int64_t)((int64_t)gas_adc_u16 << 15) - (int64_t)(1 << 24) + var1;
+    int32_t gas_res = (int32_t)(((((int64_t)lookup_k2_range[gas_range_u8] *
+                                   (int64_t)var1) >> 9) + (var2 >> 1)) / var2);
+    return gas_res;
+}
+
+#else
+double BME680::getTemperatureDouble(int field)
+{
+    uint32_t uncom_temperature_u32 = getTemp1Data(field);
+
+    double data1_d  = ((((double)uncom_temperature_u32 / 16384.0)
+                        - ((double)par_T1 / 1024.0))
+                       * ((double)par_T2));
+    /* calculate x2 data */
+    double data2_d  = (((((double)uncom_temperature_u32 / 131072.0) -
+                         ((double)par_T1 / 8192.0)) *
+                        (((double)uncom_temperature_u32 / 131072.0) -
+                         ((double)par_T1 / 8192.0))) *
+                       ((double)par_T3 * 16.0));
+    /* t fine value*/
+    t_fine = (int32_t)(data1_d + data2_d);
+    /* compensated temperature data*/
+    return (data1_d + data2_d) / 5120.0;
+}
+
+double BME680::getHumidityDouble(int field)
+{
+    double comp_temperature = getTemperatureDouble(field);
+    uint16_t uncom_humidity_u16 = getHumidityData(field);
+
+    double var1 = (double)((double)uncom_humidity_u16) - (((double)
+                  par_H1 * 16.0) +
+                  (((double)par_H3 / 2.0)
+                   * comp_temperature));
+
+    double var2 = var1 * ((double)(
+                              ((double) par_H2 / 262144.0)
+                              *(1.0 + (((double)par_H4 / 16384.0)
+                                       * comp_temperature) + (((double)par_H5
+                                               / 1048576.0) * comp_temperature
+                                               * comp_temperature))));
+    double var3 = (double) par_H6 / 16384.0;
+    double var4 = (double) par_H7 / 2097152.0;
+
+    double humidity_comp = var2 +
+                           ((var3 + (var4 * comp_temperature)) * var2 * var2);
+    if (humidity_comp > BME680_MAX_HUMIDITY_VALUE)
+        humidity_comp = BME680_MAX_HUMIDITY_VALUE;
+    else if (humidity_comp < BME680_MIN_HUMIDITY_VALUE)
+        humidity_comp = BME680_MIN_HUMIDITY_VALUE;
+    return humidity_comp;
+}
+
+double BME680::getPressureDouble(int field)
+{
+    uint32_t uncom_pressure_u32 = getPressureData(field);
+
+    double data1_d = (((double)t_fine / 2.0) - 64000.0);
+    double data2_d = data1_d * data1_d * (((double)par_P6) / (131072.0));
+    data2_d = data2_d + (data1_d * ((double)par_P5) * 2.0);
+    data2_d = (data2_d / 4.0) + (((double)par_P4) * 65536.0);
+    data1_d = (((((double)par_P3 * data1_d * data1_d) / 16384.0) + ((double)par_P2 * data1_d)) / 524288.0);
+    data1_d = ((1.0 + (data1_d / 32768.0)) * ((double)par_P1));
+    double pressure_comp = (1048576.0 - ((double)uncom_pressure_u32));
+    /* Avoid exception caused by division by zero */
+    if ((int)data1_d != 0) {
+        pressure_comp = (((pressure_comp - (data2_d / 4096.0)) * 6250.0) / data1_d);
+        data1_d = (((double)par_P9) * pressure_comp * pressure_comp) /  2147483648.0;
+        data2_d = pressure_comp * (((double)par_P8) / 32768.0);
+        double data3_d = ((pressure_comp / 256.0) * (pressure_comp / 256.0) * (pressure_comp / 256.0) * (par_P10 / 131072.0));
+        pressure_comp = (pressure_comp + (data1_d + data2_d + data3_d + ((double)par_P7 * 128.0)) / 16.0);
+        return pressure_comp;
+    } else
+        return 0;
+}
+
+double BME680::convertTemperatureResistanceDouble(uint16_t heater, int16_t ambient)
+{
+    double var1 = 0;
+    double var2 = 0;
+    double var3 = 0;
+    double var4 = 0;
+    double var5 = 0;
+    double res_heat = 0;
+
+    if ((heater >= BME680_GAS_PROFILE_TEMPERATURE_MIN)
+            && (heater <= BME680_GAS_PROFILE_TEMPERATURE_MAX)) {
+#ifdef  HEATER_C1_ENABLE
+        var1 = (((double)par_GH1 / (16.0)) + 49.0);
+        var2 = ((((double)par_GH2 / (32768.0)) * (0.0005)) + 0.00235);
+#endif
+        var3 = ((double)par_GH3 / (1024.0));
+        var4 = (var1 * (1.0 + (var2 * (double)heater)));
+        var5 = (var4 + (var3 * (double)ambient));
+
+#ifdef  HEATER_C1_ENABLE
+        res_heat = (uint8_t)(3.4 * ((var5 * (4 / (4 + (double)res_heat_range)) * (1/(1 + ((double)res_heat_val * 0.002)))) - 25));
+#else
+        res_heat = (((var5 * (4.0 / (4.0 + (double)res_heat_range))) - 25.0) * 3.4);
+#endif
+
+    }
+    return (uint8_t)res_heat;
+}
+
+double BME680::getCalculateGasDouble(int field)
+{
+    uint8_t gas_range_u8 = getGasResistanceRange(field);
+    uint16_t gas_adc_u16 = getGasResistanceData(field);
+    double gas_res_d = 0;
+
+
+#ifdef HEATER_C1_ENABLE
+
+    double var1 = 0;
+    double var2 = 0;
+    double var3 = 0;
+
+
+    var1 = (1340.0 + (5.0 * range_switching_error));
+    var2 = (var1) * (1.0 + _lookup_k1_range[gas_range_u8]/100.0);
+    var3 = 1.0 + (_lookup_k2_range[gas_range_u8]/100.0);
+
+    gas_res_d = 1.0 / (double)(var3 * (0.000000125) *
+                               (double)(1 << gas_range_u8)
+                               * (((((double)gas_adc_u16) - 512.00)/var2) + 1.0));
+
+#else
+    gas_res_d = 1.0 / ((0.000000125) * (double)(1 << gas_range_u8) *
+                       ((((double)(gas_adc_u16) - 512.00) / 1365.3333) + 1.0));
+#endif
+    return gas_res_d;
+}
+#endif
+
+
+
+BME680::BME680(PinName sda, PinName scl, bool SDO)
+    :_i2c_bus(sda, scl)
+{
+    if (SDO)
+        _addr = 0x77 << 1;
+    else _addr = 0x76 << 1;
+
+    _i2c_bus.frequency(FREQUENCY_FAST);
+}
+
+bool BME680::init()
+{
+    if (getChipID() != 0x61)
+        return false;
+
+    uint8_t cali[41];
+    readRegister(0x89, 25);
+    memcpy(cali, data, 25);
+    readRegister(0xE1, 16);
+    memcpy(cali + 25, data, 16);
+
+    /* read temperature calibration*/
+    par_T1 = (cali[DIG_T1_MSB_REG] << 8) | cali[DIG_T1_LSB_REG];
+    par_T2 = (cali[DIG_T2_MSB_REG] << 8) | cali[DIG_T2_LSB_REG];
+    par_T3 = cali[DIG_T3_REG];
+
+    /* read pressure calibration*/
+    par_P1 = (cali[DIG_P1_MSB_REG] << 8) | cali[DIG_P1_LSB_REG];
+    par_P2 = (cali[DIG_P2_MSB_REG] << 8) | cali[DIG_P2_LSB_REG];
+    par_P3 = cali[DIG_P3_REG];
+    par_P4 = (cali[DIG_P4_MSB_REG] << 8) | cali[DIG_P4_LSB_REG];
+    par_P5 = (cali[DIG_P5_MSB_REG] << 8) | cali[DIG_P5_LSB_REG];
+    par_P6 = cali[DIG_P6_REG];
+    par_P7 = cali[DIG_P7_REG];
+    par_P8 = (cali[DIG_P8_MSB_REG] << 8) | cali[DIG_P8_LSB_REG];
+    par_P9 = (cali[DIG_P9_MSB_REG] << 8) | cali[DIG_P9_LSB_REG];
+    par_P10 = cali[DIG_P10_REG];
+
+    /* read humidity calibration*/
+    par_H1 = (cali[DIG_H1_MSB_REG] << 4) | (cali[DIG_H1_LSB_REG] & BME680_BIT_MASK_H1_DATA);
+    par_H2 = (cali[DIG_H2_MSB_REG] << 4) | (cali[DIG_H2_LSB_REG] >> 4);
+    par_H3 = cali[DIG_H3_REG];
+    par_H4 = cali[DIG_H4_REG];
+    par_H5 = cali[DIG_H5_REG];
+    par_H6 = cali[DIG_H6_REG];
+    par_H7 = cali[DIG_H7_REG];
+
+    /* read gas calibration*/
+    par_GH1 = cali[DIG_GH1_REG];
+    par_GH2 = (cali[DIG_GH2_MSB_REG] <<8) | cali[DIG_GH2_LSB_REG];
+    par_GH3 = cali[DIG_GH3_REG];
+
+    /**<resistance calculation*/
+    readRegister(0x02);
+    res_heat_range = (data[0] >> 4) & 0x03;
+
+    /**<correction factor*/
+    readRegister(0x00);
+    res_heat_val = data[0];
+
+    /**<range switching error*/
+    readRegister(0x04);
+    range_switching_error = (data[0] & 0xF0) >> 4;
+    /*
+       uint16_t BME680::getParG1()
+    {
+       readRegister(0xEB, 2);
+       return (data[1] << 8) | data[0];
+    }
+
+    uint8_t BME680::getParG2()
+    {
+       readRegister(0xED);
+       return data[0];
+    }
+
+    uint8_t BME680::getParG3()
+    {
+       readRegister(0xEE);
+       return data[0];
+    }
+    */
+    return true;
+}
+
+uint32_t BME680::getPressureData(int field)
+{
+    readRegister(0x1F + field * 0x11, 3);
+    return (data[0] << 12) | (data[1] << 4) | (data[2] >> 4);
+}
+
+uint32_t BME680::getTemp1Data(int field)
+{
+    readRegister(0x22 + field * 0x11, 3);
+    return (data[0] << 12) | (data[1] << 4) | (data[2] >> 4);
+}
+
+uint32_t BME680::getHumidityData(int field)
+{
+    readRegister(0x25 + field * 0x11, 2);
+    return (data[0] << 8) | data[1];
+}
+
+uint16_t BME680::getGasResistanceData(int field)
+{
+    readRegister(0x2A + field * 0x11, 2);
+    return (data[0] << 2) | (data[1] >> 6);
+}
+
+uint8_t BME680::getGasResistanceRange(int field)
+{
+    readRegister(0x2B + field * 0x11);
+    return data[0] & 0x0F;
+}
+
+bool BME680::isNewData(int field)
+{
+    readRegister(0x1D + field * 0x11);
+    return (data[0] & 0x80) == 0x80 ? true : false;
+}
+
+bool BME680::isGasMeasuring(int field)
+{
+    readRegister(0x1D + field * 0x11);
+    return (data[0] & 0x40) == 0x40 ? true : false;
+}
+
+bool BME680::isMeasuring(int field)
+{
+    readRegister(0x1D + field * 0x11);
+    return (data[0] & 0x20) == 0x20 ? true : false;
+}
+
+int BME680::getGasMeasurementIndex(int field)
+{
+    readRegister(0x1D + field * 0x11);
+    return data[0] & 0x0F;
+}
+
+int BME680::getSubMeasurementIndex(int field)
+{
+    readRegister(0x1E + field * 0x11);
+    return data[0];
+}
+
+bool BME680::isGasValid(int field)
+{
+    readRegister(0x2B + field * 0x11);
+    return (data[0] & 0x20) == 0x20 ? true : false;
+}
+
+bool BME680::isHeaterStable(int field)
+{
+    readRegister(0x2B + field * 0x11);
+    return (data[0] & 0x10) == 0x10 ? true : false;
+}
+
+uint8_t BME680::getHeaterCurrent(int setPoint)
+{
+    readRegister(0x50 + setPoint);
+    return data[0] >> 1;
+}
+
+void BME680::setHeaterCurrent(int setPoint, uint8_t value)
+{
+    writeRegister(0x50 + setPoint, value << 1);
+}
+
+int8_t BME680::getTargetHeaterResistance(int setPoint)
+{
+    readRegister(0x5A + setPoint);
+    return data[0];
+}
+
+void BME680::setTargetHeaterResistance(int setPoint, int8_t value)
+{
+    writeRegister(0x5A + setPoint, value);
+}
+
+int BME680::getGasWaitTime(int setPoint)
+{
+    readRegister(0x64 + setPoint);
+    return (data[0] & 0x3F) * (data[0] >> 6);
+}
+
+void BME680::setGasWaitTime(int setPoint, int time, int multiplication)
+{
+    writeRegister(0x64 + setPoint, (multiplication << 6) | (time & 0x3F));
+}
+
+int BME680::getGasWaitShared()
+{
+    readRegister(0x6E);
+    return (data[0] & 0x1F) * (data[0] >> 6);
+}
+
+void BME680::setGasWaitShared(int time, int multiplication)
+{
+    writeRegister(0x6E, (multiplication << 6) | (time & 0x1F));
+}
+
+void BME680::setHeaterOff()
+{
+    readRegister(0x70);
+    data[0] |= 0x08;
+    writeRegister(0x70, data[0]);
+}
+
+int BME680::getHeaterProfile()
+{
+    readRegister(0x70);
+    return data[0] &= 0x08;
+}
+
+void BME680::setHeaterProfile(int vlaue)
+{
+    readRegister(0x71);
+    data[0] &= 0xF0;
+    data[0] |= vlaue & 0x0F;
+    writeRegister(0x71, data[0]);
+}
+
+void BME680::runGasConversion()
+{
+    readRegister(0x71);
+    data[0] |= 0x10;
+    writeRegister(0x71, data[0]);
+}
+
+float BME680::getWakePeriod()
+{
+    readRegister(0x71);
+    int temp = (data[0] & 0x80) >> 4;
+    readRegister(0x75);
+    temp |= data[0] >> 5;
+
+    switch(temp) {
+        case 0:
+            return 0.59f;
+        case 1:
+            return 62.5f;
+        case 2:
+            return 125;
+        case 3:
+            return 250;
+        case 4:
+            return 500;
+        case 5:
+            return 1000;
+        case 6:
+            return 10;
+        case 7:
+            return 20;
+        default:
+            return 0;
+    }
+}
+
+void  BME680::setWakePeriod(int value)
+{
+    readRegister(0x71);
+    data[0] = (data[0] & 0x7F) | ((value & 0x0F) >> 3);
+    writeRegister(0x71, data[0]);
+
+    readRegister(0x75);
+    data[0] = (data[0] & 0x1F) | ((value & 0x07) << 5);
+    writeRegister(0x75, data[0]);
+}
+
+int BME680::getOversamplingHumidity()
+{
+    readRegister(0x72);
+    switch (data[0] & 0x07) {
+        case 0:
+            return 0;
+        case 1:
+            return 1;
+        case 2:
+            return 2;
+        case 3:
+            return 4;
+        case 4:
+            return 8;
+        case 5:
+            return 16;
+    }
+
+    return 0;
+}
+
+void BME680::setOversamplingHumidity(int value)
+{
+    readRegister(0x72);
+    data[0] = (data[0] & 0xF8) | (value & 0x07);
+    writeRegister(0x72, data[0]);
+}
+
+int BME680::getOversamplingPressure()
+{
+    readRegister(0x74);
+    switch ((data[0] & 0x1C) >> 2) {
+        case 0:
+            return 0;
+        case 1:
+            return 1;
+        case 2:
+            return 2;
+        case 3:
+            return 4;
+        case 4:
+            return 8;
+        case 5:
+            return 16;
+    }
+
+    return 0;
+}
+
+void BME680::setOversamplingPressure(int value)
+{
+    readRegister(0x74);
+    data[0] = (data[0] & 0xE3) | ((value & 0x07) << 2);
+    writeRegister(0x74, data[0]);
+}
+
+int BME680::getOversamplingTemperature()
+{
+    readRegister(0x74);
+    switch ((data[0] & 0xE0) >> 5) {
+        case 0:
+            return 0;
+        case 1:
+            return 1;
+        case 2:
+            return 2;
+        case 3:
+            return 4;
+        case 4:
+            return 8;
+        case 5:
+            return 16;
+    }
+
+    return 0;
+}
+
+void BME680::setOversamplingTemperature(int value)
+{
+    readRegister(0x74);
+    data[0] = (data[0] & 0x1F) | ((value & 0x07) << 5);
+    writeRegister(0x74, data[0]);
+}
+
+int BME680::getIIRfilterCoefficient()
+{
+    readRegister(0x75);
+    switch ((data[0] & 0x1C) >> 2) {
+        case 0:
+            return 0;
+        case 1:
+            return 1;
+        case 2:
+            return 3;
+        case 3:
+            return 7;
+        case 4:
+            return 15;
+        case 5:
+            return 31;
+        case 6:
+            return 63;
+        case 7:
+            return 127;
+    }
+    return 0;
+}
+
+void BME680::setIIRfilterCoefficient(int value)
+{
+    readRegister(0x75);
+    data[0] = (data[0] & 0xE3) | ((value & 0x07) << 2);
+    writeRegister(0x75, data[0]);
+}
+
+int BME680::getMode()
+{
+    readRegister(0x74);
+    return data[0] & 0x03;
+}
+
+void BME680::setMode(int mode)
+{
+    readRegister(0x74);
+    data[0] = (data[0] & 0xFC) | (mode & 0x03);
+    writeRegister(0x74, data[0]);
+}
+
+int BME680::getChipID()
+{
+    readRegister(0xD0);
+    return data[0];
+}
+
+void BME680::readRegister(int reg, int size)
+{
+    _i2c_bus.start();
+    _i2c_bus.write(_addr);
+    _i2c_bus.write(reg);
+    _i2c_bus.start();
+    _i2c_bus.write(_addr | 0x01);
+    int i = 0;
+    for (; i< size -1; i++)
+        data[i] = _i2c_bus.read(1);
+    data[i] = _i2c_bus.read(0);
+    _i2c_bus.stop();
+}
+
+void BME680::writeRegister(int reg, int value)
+{
+    _i2c_bus.start();
+    _i2c_bus.write(_addr);
+    _i2c_bus.write(reg);
+    _i2c_bus.write(value);
+    _i2c_bus.stop();
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BME680.h	Fri Jul 22 17:38:11 2016 +0000
@@ -0,0 +1,736 @@
+#ifndef UK_AC_HERTS_SMARTLAB_BME680
+#define UK_AC_HERTS_SMARTLAB_BME680
+
+#include "mbed.h"
+#include "stdint.h"
+
+/*
+* Use below macro for fixed Point Calculation
+* else Floating Point calculation will be used
+*/
+#define FIXED_POINT_COMPENSATION
+
+// no idea what it is for
+#define HEATER_C1_ENABLE
+
+// Sensor Specific constants */
+#define BME680_SLEEP_MODE               (0x00)
+#define BME680_FORCED_MODE              (0x01)
+#define BME680_PARALLEL_MODE            (0x02)
+#define BME680_SEQUENTIAL_MODE          (0x03)
+#define BME680_GAS_PROFILE_TEMPERATURE_MIN  (200)
+#define BME680_GAS_PROFILE_TEMPERATURE_MAX  (400)
+#define BME680_GAS_RANGE_RL_LENGTH      (16)
+#define BME680_SIGN_BIT_MASK            (0x08)
+
+#ifdef FIXED_POINT_COMPENSATION
+//< Multiply by 1000, In order to convert float value into fixed point
+#define BME680_MAX_HUMIDITY_VALUE       (102400)
+#define BME680_MIN_HUMIDITY_VALUE       (0)
+#else
+#define BME680_MAX_HUMIDITY_VALUE       (double)(100.0)
+#define BME680_MIN_HUMIDITY_VALUE       (double)(0.0)
+#endif
+
+/// BME680 integrated environmental sensor. This API supports FIXED and FLOATING compenstion. By default it supports FIXED, to use FLOATING user need to disable "FIXED_POINT_COMPENSATION" in the BME680.h file.
+class BME680
+{
+private:
+    static const int FREQUENCY_STANDARD = 100000;
+    static const int FREQUENCY_FULL = 400000;
+    static const int FREQUENCY_FAST = 1000000;
+    static const int FREQUENCY_HIGH = 3200000;
+
+    I2C _i2c_bus;
+    int _addr;
+    uint8_t data[30];
+
+    //static const double const_array1[];
+    //static const double const_array2[];
+    static const uint64_t lookup_k1_range[];
+    static const uint64_t lookup_k2_range[];
+    static const double _lookup_k1_range[];
+    static const double _lookup_k2_range[];
+
+    /* For Calibration Data*/
+    static const int DIG_T2_LSB_REG = 1;
+    static const int DIG_T2_MSB_REG = 2;
+    static const int DIG_T3_REG = 3;
+    static const int DIG_P1_LSB_REG = 5;
+    static const int DIG_P1_MSB_REG = 6;
+    static const int DIG_P2_LSB_REG = 7;
+    static const int DIG_P2_MSB_REG = 8;
+    static const int DIG_P3_REG = 9;
+    static const int DIG_P4_LSB_REG = 11;
+    static const int DIG_P4_MSB_REG = 12;
+    static const int DIG_P5_LSB_REG = 13;
+    static const int DIG_P5_MSB_REG = 14;
+    static const int DIG_P7_REG = 15;
+    static const int DIG_P6_REG = 16;
+    static const int DIG_P8_LSB_REG = 19;
+    static const int DIG_P8_MSB_REG = 20;
+    static const int DIG_P9_LSB_REG = 21;
+    static const int DIG_P9_MSB_REG = 22;
+    static const int DIG_P10_REG = 23;
+    static const int DIG_H2_MSB_REG = 25;
+    static const int DIG_H2_LSB_REG = 26;
+    static const int DIG_H1_LSB_REG = 26;
+    static const int DIG_H1_MSB_REG  = 27;
+    static const int DIG_H3_REG = 28;
+    static const int DIG_H4_REG = 29;
+    static const int DIG_H5_REG = 30;
+    static const int DIG_H6_REG = 31;
+    static const int DIG_H7_REG = 32;
+    static const int DIG_T1_LSB_REG = 33;
+    static const int DIG_T1_MSB_REG = 34;
+    static const int DIG_GH2_LSB_REG = 35;
+    static const int DIG_GH2_MSB_REG = 36;
+    static const int DIG_GH1_REG = 37;
+    static const int DIG_GH3_REG = 38;
+
+    static const int BME680_BIT_MASK_H1_DATA = 0x0F;
+
+    int8_t  par_T3;/**<calibration T3 data*/
+    int8_t  par_P3;/**<calibration P3 data*/
+    int8_t  par_P6;/**<calibration P6 data*/
+    int8_t  par_P7;/**<calibration P7 data*/
+    uint8_t  par_P10;/**<calibration P10 data*/
+    int8_t  par_H3;/**<calibration H3 data*/
+    int8_t  par_H4;/**<calibration H4 data*/
+    int8_t  par_H5;/**<calibration H5 data*/
+    uint8_t  par_H6;/**<calibration H6 data*/
+    int8_t  par_H7;/**<calibration H7 data*/
+    int8_t  par_GH1;/**<calibration GH1 data*/
+    uint8_t  res_heat_range;/**<resistance calculation*/
+    int8_t  res_heat_val; /**<correction factor*/
+    int8_t  range_switching_error;/**<range switching error*/
+    int16_t par_GH2;/**<calibration GH2 data*/
+    uint16_t par_T1;/**<calibration T1 data*/
+    int16_t par_T2;/**<calibration T2 data*/
+    uint16_t par_P1;/**<calibration P1 data*/
+    int16_t par_P2;/**<calibration P2 data*/
+    int16_t par_P4;/**<calibration P4 data*/
+    int16_t par_P5;/**<calibration P5 data*/
+    int16_t par_P8;/**<calibration P8 data*/
+    int16_t par_P9;/**<calibration P9 data*/
+    uint16_t par_H1;/**<calibration H1 data*/
+    uint16_t par_H2;/**<calibration H2 data*/
+    int32_t t_fine;/**<calibration T_FINE data*/
+    int8_t  par_GH3;/**<calibration GH3 data*/
+
+    void readRegister(int reg, int size = 1);
+
+    void writeRegister(int reg, int value);
+
+public:
+
+    /// NOT IMPLEMENTED
+    void setSequentialMode();
+    
+    /// NOT IMPLEMENTED
+    void setForcedMode();
+    
+    /// NOT IMPLEMENTED
+    void setParallelMode();
+
+    /*
+    * @param sda I2C sda signal
+    * @param scl I2C scl signal
+    * @param SDO Slave address LSB (High->true, Low->false)
+    */
+    BME680(PinName sda, PinName scl, bool SDO);
+
+    /**
+    * !! MUST CALL THIS FIRST !!
+    * read the chip id and calibration data of the BME680 sensor
+    */
+    bool init();
+    // DATA #########################################################################
+
+#ifdef FIXED_POINT_COMPENSATION
+    /**
+    *  This function is used to convert the uncompensated
+    *  temperature data to compensated temperature data using
+    *  compensation formula(integer version)
+    *  @note Returns the value in 0.01 degree Centigrade
+    *  Output value of "5123" equals 51.23 DegC.
+    *
+    * @param field 0-2
+    *
+    *  @return Returns the compensated temperature data
+    *
+    */
+    int32_t getCompensatedTemperature(int field = 0);
+
+    /**
+    * Reads actual temperature from uncompensated temperature
+    * @note Returns the value with 500LSB/DegC centred around 24 DegC
+    * output value of "5123" equals(5123/500)+24 = 34.246DegC
+    *
+    *
+    *  @param v_uncomp_temperature_u32: value of uncompensated temperature
+    *  @param bme680: structure pointer.
+    *
+    *
+    *  @return Return the actual temperature as s16 output
+    *
+    */
+    int16_t getTemperatureInt(int field = 0);
+
+    /**
+    *  @brief This function is used to convert the uncompensated
+    *  humidity data to compensated humidity data using
+    *  compensation formula(integer version)
+    *
+    *  @note Returns the value in %rH as unsigned 32bit integer
+    *  in Q22.10 format(22 integer 10 fractional bits).
+    *  @note An output value of 42313
+    *  represents 42313 / 1024 = 41.321 %rH
+    *
+    *
+    *
+    *  @param  v_uncomp_humidity_u32: value of uncompensated humidity
+    *  @param bme680: structure pointer.
+    *
+    *  @return Return the compensated humidity data
+    *
+    */
+    int32_t getCompensateHumidity(int field = 0);
+
+    /**
+    * @brief Reads actual humidity from uncompensated humidity
+    * @note Returns the value in %rH as unsigned 16bit integer
+    * @note An output value of 42313
+    * represents 42313/512 = 82.643 %rH
+    *
+    *
+    *
+    *  @param v_uncomp_humidity_u32: value of uncompensated humidity
+    *  @param bme680: structure pointer.
+    *
+    *  @return Return the actual relative humidity output as u16
+    *
+    */
+    uint16_t getHumidityInt(int field = 0);
+
+    /**
+    * @brief This function is used to convert the uncompensated
+    *  pressure data to compensated pressure data data using
+    *  compensation formula(integer version)
+    *
+    * @note Returns the value in Pascal(Pa)
+    * Output value of "96386" equals 96386 Pa =
+    * 963.86 hPa = 963.86 millibar
+    *
+    *
+    *
+    *  @param v_uncomp_pressure_u32 : value of uncompensated pressure
+    *  @param bme680: structure pointer.
+    *
+    *  @return Return the compensated pressure data
+    *
+    */
+    int32_t getCompensatePressure(int field = 0);
+
+    /**
+     * @brief Reads actual pressure from uncompensated pressure
+     * @note Returns the value in Pa.
+     * @note Output value of "12337434"
+     * @note represents 12337434 / 128 = 96386.2 Pa = 963.862 hPa
+     *
+     *
+     *
+     *  @param v_uncomp_pressure_u32 : value of uncompensated pressure
+     *  @param bme680: structure pointer.
+     *
+     *  @return the actual pressure in u32
+     *
+    */
+    uint32_t getPressureInt(int field = 0);
+
+    /**
+     *  @brief This function is used to convert temperature to resistance
+     *  using the integer compensation formula
+     *
+     *  @param heater_temp_u16: The value of heater temperature
+     *  @param ambient_temp_s16: The value of ambient temperature
+     *  @param bme680: structure pointer.
+     *
+     *  @return calculated resistance from temperature
+     *
+     *
+     *
+    */
+    uint8_t convertTemperatureResistanceInt(uint16_t heater, int16_t ambient);
+
+
+    /**
+     *  @brief This function is used to convert uncompensated gas data to
+     *  compensated gas data using compensation formula(integer version)
+     *
+     *  @param gas_adc_u16: The value of gas resistance calculated
+     *       using temperature
+     *  @param gas_range_u8: The value of gas range form register value
+     *  @param bme680: structure pointer.
+     *
+     *  @return calculated compensated gas from compensation formula
+     *  @retval compensated gas data
+     *
+     *
+    */
+    int32_t getCalculateGasInt(int field = 0);
+
+#else
+    /**
+    * This function used to convert temperature data
+    * to uncompensated temperature data using compensation formula
+    * @note returns the value in Degree centigrade
+    * @note Output value of "51.23" equals 51.23 DegC.
+    * @param field 0-2
+    * @return  Return the actual temperature in floating point
+    */
+    double getTemperatureDouble(int field = 0);
+
+    /**
+    * @brief This function is used to convert the uncompensated
+    *  humidity data to compensated humidity data data using
+    *  compensation formula
+    * @note returns the value in relative humidity (%rH)
+    * @note Output value of "42.12" equals 42.12 %rH
+    *
+    *  @param uncom_humidity_u16 : value of uncompensated humidity
+    *  @param comp_temperature   : value of compensated temperature
+    *  @param bme680: structure pointer.
+    *
+    *
+    *  @return Return the compensated humidity data in floating point
+    *
+    */
+    double getHumidityDouble(int field = 0);
+
+    /**
+     * @brief This function is used to convert the uncompensated
+     * pressure data to compensated data using compensation formula
+     * @note Returns pressure in Pa as double.
+     * @note Output value of "96386.2"
+     * equals 96386.2 Pa = 963.862 hPa.
+     *
+     *
+     *  @param uncom_pressure_u32 : value of uncompensated pressure
+     *  @param bme680: structure pointer.
+     *
+     *  @return  Return the compensated pressure data in floating point
+     *
+    */
+    double getPressureDouble(int field = 0);
+
+    /**
+     *  @brief This function is used to convert temperature to resistance
+     *  using the compensation formula
+     *
+     *  @param heater_temp_u16: The value of heater temperature
+     *  @param ambient_temp_s16: The value of ambient temperature
+     *  @param bme680: structure pointer.
+     *
+     *  @return calculated resistance from temperature
+     *
+     *
+     *
+    */
+    double convertTemperatureResistanceDouble(uint16_t heater, int16_t ambient);
+
+    /**
+     *  @brief This function is used to convert uncompensated gas data to
+     *  compensated gas data using compensation formula
+     *
+     *  @param gas_adc_u16: The value of gas resistance calculated
+     *       using temperature
+     *  @param gas_range_u8: The value of gas range form register value
+     *  @param bme680: structure pointer.
+     *
+     *  @return calculated compensated gas from compensation formula
+     *  @retval compensated gas
+     *
+     *
+    */
+    double getCalculateGasDouble(int field = 0);
+#endif
+
+
+    /**
+    * [press_msb] [press_lsb] [press_xlsb]
+    * Pressure, temperature, humidity and gas data of BME680 are stored in 3 data field registers
+    * named field0, field1, and field2. The data fields are updated sequentially and always results of
+    * the three latest measurements are available for the user; if the last but one conversion was written
+    * to field number k, the current conversion results are written to field with number (k+1) mod 3. All
+    * data outputs from data fields are buffered using shadowing registers to ensure keeping stable
+    * data if update of the data registers comes simultaneously with serial interface reading out.
+    * Note: Only field0 will be updated in forced mode
+    * @param field 0-2
+    */
+    uint32_t getPressureData(int field);
+
+    /**
+    * [temp1_msb] [temp1_lsb] [temp1_xlsb]
+    * Pressure, temperature, humidity and gas data of BME680 are stored in 3 data field registers
+    * named field0, field1, and field2. The data fields are updated sequentially and always results of
+    * the three latest measurements are available for the user; if the last but one conversion was written
+    * to field number k, the current conversion results are written to field with number (k+1) mod 3. All
+    * data outputs from data fields are buffered using shadowing registers to ensure keeping stable
+    * data if update of the data registers comes simultaneously with serial interface reading out.
+    * Note: Only field0 will be updated in forced mode
+    * @param field 0-2
+    */
+    uint32_t getTemp1Data(int field);
+
+    /**
+    * [hum_msb] [hum_lsb]
+    * Pressure, temperature, humidity and gas data of BME680 are stored in 3 data field registers
+    * named field0, field1, and field2. The data fields are updated sequentially and always results of
+    * the three latest measurements are available for the user; if the last but one conversion was written
+    * to field number k, the current conversion results are written to field with number (k+1) mod 3. All
+    * data outputs from data fields are buffered using shadowing registers to ensure keeping stable
+    * data if update of the data registers comes simultaneously with serial interface reading out.
+    * Note: Only field0 will be updated in forced mode
+    * @param field 0-2
+    */
+    uint32_t getHumidityData(int field);
+
+    /**
+    * [gas_rl]
+    * Pressure, temperature, humidity and gas data of BME680 are stored in 3 data field registers
+    * named field0, field1, and field2. The data fields are updated sequentially and always results of
+    * the three latest measurements are available for the user; if the last but one conversion was written
+    * to field number k, the current conversion results are written to field with number (k+1) mod 3. All
+    * data outputs from data fields are buffered using shadowing registers to ensure keeping stable
+    * data if update of the data registers comes simultaneously with serial interface reading out.
+    * Note: Only field0 will be updated in forced mode
+    * @param field 0-2
+    */
+    uint16_t getGasResistanceData(int field);
+
+    /**
+    * [gas_range_rl]
+    * Pressure, temperature, humidity and gas data of BME680 are stored in 3 data field registers
+    * named field0, field1, and field2. The data fields are updated sequentially and always results of
+    * the three latest measurements are available for the user; if the last but one conversion was written
+    * to field number k, the current conversion results are written to field with number (k+1) mod 3. All
+    * data outputs from data fields are buffered using shadowing registers to ensure keeping stable
+    * data if update of the data registers comes simultaneously with serial interface reading out.
+    * Contains ADC range of measured gas resistance
+    * Note: Only field0 will be updated in forced mode
+    * @param field 0-2
+    */
+    uint8_t getGasResistanceRange(int field);
+
+
+    // STATUS #########################################################################
+
+    /**
+    * [new_data_x]
+    * The measured data are stored into the output data registers at the end of each TPHG conversion
+    * phase along with status flags and index of measurement. The part of the register map for output
+    * data storage is composed of 3 data fields (TPHG data field0|1|2)) keeping results from the last 3
+    * measurements. Availability of new (yet unread) results is indicated by new_data_0|1|2 flags.
+    * @param field 0-2
+    */
+    bool isNewData(int field);
+
+    /**
+    * [gas_measuring]
+    * Measuring bit is set to “1‟ only during gas measurements, goes to “0‟ as soon as measurement
+    * is completed and data transferred to data registers. The registers storing the configuration values
+    * for the measurement (gas_wait_shared, gas_wait_x, res_heat_x, idac_heat_x, image registers)
+    * should not be changed when the device is measuring.
+    * @param field 0-2
+    */
+    bool isGasMeasuring(int field);
+
+    /**
+    * [measuring]
+    * Measuring status will be set to ‘1’ whenever a conversion (Pressure, Temperature, humidity &
+    * gas) is running and back to ‘0’ when the results have been transferred to the data registers.
+    * @param field 0-2
+    */
+    bool isMeasuring(int field);
+
+    /**
+    * [gas_meas_index_x]
+    * User can program a sequence of up to 10 conversions by setting nb_conv<3:0>. Each conversion
+    * has its own heater resistance target but 3 field registers to store conversion results. The actual
+    * gas conversion number in the measurement sequence (up to 10 conversions numbered from 0
+    * to 9) is stored in gas_meas_index register.
+    * @param field 0-2
+    */
+    int getGasMeasurementIndex(int field);
+
+    /**
+    * [sub_meas_index_x]
+    * sub_meas_index_x registers form “virtual time sensor” and contain a snapshot of the internal 8
+    * bit conversion counter. Conversion counter is incremented with each TPHG conversion; the
+    * counter thus contains the number of conversions modulo 256 executed since the last change of
+    * device mode.
+    * Note: This index is incremented only if gas conversion is active.
+    * @param field 0-2
+    */
+    int getSubMeasurementIndex(int field);
+
+    /**
+    * [gas_valid_rl]
+    * In parallel mode, each TPHG sequence contains a gas measurement slot, either a real one which
+    * result is used or a dummy one to keep a constant sampling rate and predictable device timing. A
+    * real gas conversion (i.e., not a dummy one) is indicated by the gas_valid_rl status register.
+    * @param field 0-2
+    */
+    bool isGasValid(int field);
+
+    /**
+    * [heat_stab_rl]
+    * Heater temperature stability for target heater resistance is indicated heat_stab_x status bits.
+    * @param field 0-2
+    */
+    bool isHeaterStable(int field);
+
+    // GAS CONTROL #########################################################################
+
+    /**
+    * [idac_heat_x]
+    * BME680 contains a heater control block that will inject enough current into the heater resistance
+    * to achieve the requested heater temperature. There is a control loop which periodically measures
+    * heater resistance value and adapts the value of current injected from a DAC.
+    * BME680 heater operation could be speeded up by setting an initial heater current for a target
+    * heater temperature by using register idac_heat_x<7:0>. This step is optional since the control
+    * loop will find the current after a few iterations anyway.
+    * Current injected to the heater in mA = (idac_heat_7_1 + 1) / 8
+    * Where: idac_heat_7_1 = decimal value stored in idac_heat<7:1> (unsigned, value from 0 to 127)
+    * @param setPoint 0-9
+    */
+    uint8_t getHeaterCurrent(int setPoint);
+
+    /**
+    * [idac_heat_x]
+    * BME680 contains a heater control block that will inject enough current into the heater resistance
+    * to achieve the requested heater temperature. There is a control loop which periodically measures
+    * heater resistance value and adapts the value of current injected from a DAC.
+    * BME680 heater operation could be speeded up by setting an initial heater current for a target
+    * heater temperature by using register idac_heat_x<7:0>. This step is optional since the control
+    * loop will find the current after a few iterations anyway.
+    * Current injected to the heater in mA = (idac_heat_7_1 + 1) / 8
+    * Where: idac_heat_7_1 = decimal value stored in idac_heat<7:1> (unsigned, value from 0 to 127)
+    * @param setPoint 0-9
+    */
+    void setHeaterCurrent(int setPoint, uint8_t value);
+
+    /**
+    * [res_heat_x]
+    * Target heater resistance is programmed by user through res_heat_x<7:0> registers.
+    * res_heat_x = 3.4* ((R_Target*(4/4+res_heat_range))-25) / ((res_heat_val * 0.002) + 1))
+    * Where
+    * R_Target is the target heater resistance in Ohm
+    * res_heat_x is the decimal value that needs to be stored in register with same name
+    * res_heat_range is heater range stored in register address 0x02 <5:4>
+    * res_heat_val is heater resistance correction factor stored in register address 0x00 (signed, value from -128 to 127)
+    * @param setPoint 0-9
+    */
+    int8_t getTargetHeaterResistance(int setPoint);
+
+    /**
+    * [res_heat_x]
+    * Target heater resistance is programmed by user through res_heat_x<7:0> registers.
+    * res_heat_x = 3.4* ((R_Target*(4/4+res_heat_range))-25) / ((res_heat_val * 0.002) + 1))
+    * Where
+    * R_Target is the target heater resistance in Ohm
+    * res_heat_x is the decimal value that needs to be stored in register with same name
+    * res_heat_range is heater range stored in register address 0x02 <5:4>
+    * res_heat_val is heater resistance correction factor stored in register address 0x00 (signed, value from -128 to 127)
+    * @param setPoint 0-9
+    */
+    void setTargetHeaterResistance(int setPoint, int8_t value);
+
+    /**
+    * [gas_wait_x]
+    * gas_wait_x controls heater timing of the gas sensor. Functionality of this register will vary based on power modes.
+    * Forced Mode & Sequential mode
+    * Time between beginning of heat phase and start of sensor resistance conversion depend on gas_wait_x settings as mentioned below.
+    * Parallel Mode
+    * The number of TPHG sub-measurement sequences within the one Gas conversion for one target
+    * temperature resistance is defined by gas_wait_x settings.
+    * Note: Please take care about gas_wait_x on shifting modes between parallel & sequential/forced mode as register functionality will change.
+    * @return result * 0.477 ms
+    * @param setPoint 0-9
+    */
+    int getGasWaitTime(int setPoint);
+
+    /**
+    * [gas_wait_x]
+    * gas_wait_x controls heater timing of the gas sensor. Functionality of this register will vary based on power modes.
+    * Forced Mode & Sequential mode
+    * Time between beginning of heat phase and start of sensor resistance conversion depend on gas_wait_x settings as mentioned below.
+    * Parallel Mode
+    * The number of TPHG sub-measurement sequences within the one Gas conversion for one target
+    * temperature resistance is defined by gas_wait_x settings.
+    * Note: Please take care about gas_wait_x on shifting modes between parallel & sequential/forced mode as register functionality will change.
+    * @return result * 0.477 ms
+    * @param setPoint 0-9
+    * @param time 64 timer values with 1ms step sizes, all zeros means no wait.
+    * @param multiplication [0, 1, 2, 3] -> [1, 4, 16, 64]
+    */
+    void setGasWaitTime(int setPoint, int time, int multiplication);
+
+    /**
+    * [gas_wait_shared]
+    * The programmable wait time between two TPHG sub-measurement sequences of parallel mode depends on gas_wait_shared settings as follows
+    */
+    int getGasWaitShared();
+
+    /**
+    * [gas_wait_shared]
+    * The programmable wait time between two TPHG sub-measurement sequences of parallel mode depends on gas_wait_shared settings as follows
+    * @param setPoint 0-9
+    * @param time 64 timer values with 0.477 ms step sizes, all zeros means no wait.
+    * @param multiplication [0x00, 0x01, 0x10, 0x11] -> [1, 4, 16, 64]
+    */
+    void setGasWaitShared(int time, int multiplication);
+
+    /**
+    * [heat_off]
+    * Turn off current injected to heater
+    */
+    void setHeaterOff();
+
+    /**
+    * [nb_conv]
+    * is used to select heater set-points of BME680
+    * Sequential & Parallel Mode
+    * User can program a sequence of up to 10 conversions by setting nb_conv<3:0>. Each conversion has its own heater resistance target but 3 field registers to store conversion results. The actual
+    * gas conversion number in the measurement sequence (up to 10 conversions numbered from 0 to 9) is stored in gas measurement index register
+    * In parallel mode, no TPH conversions are ran at all. In sequential mode, TPH conversions are run according to osrs_t|p|h settings, gas is skipped
+    * @return Sequential & Parallel : number of profiles (0-10), 0 means no gas conversion
+    * @return Forced : indicates index of heater profile
+    */
+    int getHeaterProfile();
+
+    /**
+    * [nb_conv]
+    * is used to select heater set-points of BME680
+    * Sequential & Parallel Mode
+    * User can program a sequence of up to 10 conversions by setting nb_conv<3:0>. Each conversion has its own heater resistance target but 3 field registers to store conversion results. The actual
+    * gas conversion number in the measurement sequence (up to 10 conversions numbered from 0 to 9) is stored in gas measurement index register
+    * In parallel mode, no TPH conversions are ran at all. In sequential mode, TPH conversions are run according to osrs_t|p|h settings, gas is skipped
+    * @param Sequential & Parallel : number of profiles (0-10), 0 means no gas conversion
+    * @param Forced : indicates index of heater profile
+    */
+    void setHeaterProfile(int value);
+
+    /**
+    * [run_gas_l]
+    * The gas conversions are started only in appropriate mode if run_gas_l=1
+    */
+    void runGasConversion();
+
+    /**
+    * [odr]
+    * Wake period in sequential mode – odr
+    * In the sequential mode operation the device periodically enters stand-by state and returns to an operational state after a given wake-up period. Wake period can be programmed by odr<3:0> register as shown below
+    * @return in ms, 0 means device does not go to standby
+    */
+    float getWakePeriod();
+
+    /**
+    * [odr]
+    * Wake period in sequential mode – odr
+    * In the sequential mode operation the device periodically enters stand-by state and returns to an operational state after a given wake-up period. Wake period can be programmed by odr<3:0> register as shown below
+    * @param value : [0 - 8+] [0.59,62.5,125,250,500,1000,10,20,no standby]
+    */
+    void setWakePeriod(int value);
+
+    // PRESSURE TEMPERATURE HUMIDITY CONTROL #########################################################################
+
+    /**
+    * [osrs_h]
+    * @return value : [0,1,2,4,8,16] -> [skip,X1,X2,X4,X8,X16], 0 means skipped (output set to 0x8000)
+    */
+    int getOversamplingHumidity();
+
+    /**
+    * [osrs_h]
+    * @param value : [0,1,2,3,4,5] -> [skip,X1,X2,X4,X8,X16], 0 means skipped (output set to 0x8000)
+    */
+    void setOversamplingHumidity(int value);
+
+    /**
+    * [osrs_p]
+    * @return value : [0,1,2,4,8,16] -> [skip,X1,X2,X4,X8,X16], 0 means skipped (output set to 0x8000)
+    */
+    int getOversamplingPressure();
+
+    /**
+    * [osrs_p]
+    * @param value : [0,1,2,3,4,5] -> [skip,X1,X2,X4,X8,X16], 0 means skipped (output set to 0x8000)
+    */
+    void setOversamplingPressure(int value);
+
+    /**
+    * [osrs_t]
+    * @return value : [0,1,2,4,8,16] -> [skip,X1,X2,X4,X8,X16], 0 means skipped (output set to 0x8000)
+    */
+    int getOversamplingTemperature();
+
+    /**
+    * [osrs_t]
+    * @param value : [0,1,2,3,4,5] -> [skip,X1,X2,X4,X8,X16], 0 means skipped (output set to 0x8000)
+    */
+    void setOversamplingTemperature(int value);
+
+    /**
+    * [filter]
+    * IIR filter control
+    * IIR filter applies to temperature and pressure data but not to humidity and gas data. The data
+    * coming from the ADC are filtered and then loaded into the data registers. The T, P result registers
+    * are updated together at the same time at the end of measurement. IIR filter output resolution is
+    * 20 bits. The T, P result registers are reset to value 0x80000 when the T, P measurements have
+    * been skipped (osrs_x=”000‟). The appropriate filter memory is kept unchanged (the value fromt he last measurement is kept). When the appropriate OSRS register is set back to nonzero, then
+    * the first value stored to the T, P result register is filtered.
+    * @return value : [0,1,3,7,15,31,63,127]
+    */
+    int getIIRfilterCoefficient();
+
+    /**
+    * [filter]
+    * IIR filter control
+    * IIR filter applies to temperature and pressure data but not to humidity and gas data. The data
+    * coming from the ADC are filtered and then loaded into the data registers. The T, P result registers
+    * are updated together at the same time at the end of measurement. IIR filter output resolution is
+    * 20 bits. The T, P result registers are reset to value 0x80000 when the T, P measurements have
+    * been skipped (osrs_x=”000‟). The appropriate filter memory is kept unchanged (the value fromt he last measurement is kept). When the appropriate OSRS register is set back to nonzero, then
+    * the first value stored to the T, P result register is filtered.
+    * @param value : [0,1,2,3,4,5,6,7] -> [0,1,3,7,15,31,63,127]
+    */
+    void setIIRfilterCoefficient(int value);
+
+    // GENERAL CONTROL #########################################################################
+
+    /**
+    * [mode]
+    * Four measurement modes are available for BME680; that is sleep, sequential, parallel and forced
+    * mode.Four measurement modes are available for BME680; that is sleep, sequential, parallel and forced mode.
+    * @param mode : [0,1,2,3] -> [Sleep, Forced, Parallel, Sequential]
+    */
+    void setMode(int mode);
+
+    /**
+    * [mode]
+    * Four measurement modes are available for BME680; that is sleep, sequential, parallel and forced
+    * mode.Four measurement modes are available for BME680; that is sleep, sequential, parallel and forced mode.
+    * @return value : [0,1,2,3] -> [Sleep, Forced, Parallel, Sequential]
+    */
+    int getMode();
+
+    /**
+    * [chip_id]
+    * Chip id of the device, this should give 0x61
+    */
+    int getChipID();
+};
+
+#endif
\ No newline at end of file