#ifndef TG_BME_280_H
#define TG_BME_280_H

#include <Wire.h>

#define BME280_ADDRESS (0x76)
#define BME280_ADDRESS_ALTERNATE (0x77)


//////////////////////////////////////////////////////////////////
/// BME280 - Driver class for Bosch Bme280 sensor
///
/// Based on the data sheet provided by Bosch for
/// the Bme280 environmental sensor.
///
class BME280 {
public:

    enum PresUnit {
        PresUnit_Pa,
        PresUnit_hPa,
        PresUnit_atm,
        PresUnit_bar,
    };

    enum OSR {
        OSR_Off =  0,
        OSR_X1  =  1,
        OSR_X2  =  2,
        OSR_X4  =  3,
        OSR_X8  =  4,
        OSR_X16 =  5
    };

    enum Mode {
        Mode_Sleep  = 0,
        Mode_Forced = 1,
        Mode_Normal = 3
    };

    enum StandbyTime {
        StandbyTime_500us   = 0,
        StandbyTime_62500us = 1,
        StandbyTime_125ms   = 2,
        StandbyTime_250ms   = 3,
        StandbyTime_50ms    = 4,
        StandbyTime_1000ms  = 5,
        StandbyTime_10ms    = 6,
        StandbyTime_20ms    = 7
    };

    enum Filter {
        Filter_Off = 0,
        Filter_2   = 1,
        Filter_4   = 2,
        Filter_8   = 3,
        Filter_16  = 4
    };

    enum ChipModel {
        ChipModel_UNKNOWN = 0,
        ChipModel_BMP280 = 0x58,
        ChipModel_BME280 = 0x60
    };

    BME280(TwoWire* i2c): m_initialized(false), i2c(i2c) {}
    ChipModel chipModel();

    bool begin();
    bool reset();

    float temp();
    float pres(PresUnit unit = PresUnit_hPa);
    float hum();
    void  read(float& pressure,float& temperature,float& humidity, PresUnit  presUnit = PresUnit_hPa);

protected:
    bool Initialize();

private:
    TwoWire* i2c;
    uint8_t m_dig[32];
    ChipModel m_chip_model;
    bool m_initialized;


    static const uint8_t CTRL_HUM_ADDR   = 0xF2;
    static const uint8_t CTRL_MEAS_ADDR  = 0xF4;
    static const uint8_t CONFIG_ADDR     = 0xF5;
    static const uint8_t PRESS_ADDR      = 0xF7;
    static const uint8_t TEMP_ADDR       = 0xFA;
    static const uint8_t HUM_ADDR        = 0xFD;
    static const uint8_t TEMP_DIG_ADDR   = 0x88;
    static const uint8_t PRESS_DIG_ADDR  = 0x8E;
    static const uint8_t HUM_DIG_ADDR1   = 0xA1;
    static const uint8_t HUM_DIG_ADDR2   = 0xE1;
    static const uint8_t ID_ADDR         = 0xD0;
    static const uint8_t RESET_ADDR	= 0xE0;

    static const uint8_t RESET_VALUE	= 0xB6;

    static const uint8_t TEMP_DIG_LENGTH         = 6;
    static const uint8_t PRESS_DIG_LENGTH        = 18;
    static const uint8_t HUM_DIG_ADDR1_LENGTH    = 1;
    static const uint8_t HUM_DIG_ADDR2_LENGTH    = 7;
    static const uint8_t DIG_LENGTH              = 32;
    static const uint8_t SENSOR_DATA_LENGTH      = 8;


    void WriteSettings();
    bool ReadChipID();
    bool ReadTrim();

    bool ReadData(int32_t data[8]);

    bool WriteRegister(uint8_t addr,uint8_t data);
    bool ReadRegister(uint8_t addr,uint8_t data[],uint8_t length);

    float CalculateTemperature(int32_t raw,int32_t& t_fine);
    float CalculateHumidity(int32_t raw,int32_t t_fine);
    float CalculatePressure(int32_t raw,int32_t t_fine,PresUnit unit = PresUnit_hPa);
};

#endif // TG_BME_280_H