//-----------------------------------------------------------------------------
///
/// \brief  BME680 Boch environment sensor
///
///         I2C connected
///
/// \date   20200229
/// \author Maximilian Seesslen <mes@seesslen.net>
///
//-----------------------------------------------------------------------------


//---Includes------------------------------------------------------------------


//---General--------------------------

//#include <string.h>     // strlen

//---Own------------------------------

#include <biwak/bme680.hpp>
#include <biwak/systick.h>    // USEC_PER_MSEC
#include <bosch/bme680.h>
#include <lepto/log.h>
#include <string.h>           // memset

//---Defines-------------------------------------------------------------------


extern "C"
{
   int8_t user_i2c_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len);
   int8_t user_i2c_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len);
   void user_delay_ms(uint32_t period);
}


namespace BME680
{
   struct bme680_field_data data;
   struct bme680_dev gas_sensor;
   CI2cSlave *i2cSlave=nullptr;
};


CBme680::CBme680(CI2c &i2c, int address /*= 0x76*/ )
   :CI2cSlave(i2c, address)
{
   uint8_t set_required_settings;
   //int rslt;

   BME680::i2cSlave=this;

   BME680::gas_sensor.dev_id = BME680_I2C_ADDR_PRIMARY;
   BME680::gas_sensor.intf = BME680_I2C_INTF;
   BME680::gas_sensor.read = user_i2c_read;
   BME680::gas_sensor.write = user_i2c_write;
   BME680::gas_sensor.delay_ms = user_delay_ms;
   /* amb_temp can be set to 25 prior to configuring the gas sensor
    * or by performing a few temperature readings without operating the gas sensor.
    */
   BME680::gas_sensor.amb_temp = 25;

   int8_t rslt = BME680_OK;
   rslt = bme680_init(&BME680::gas_sensor);
   (void)rslt;

   /* Set the temperature, pressure and humidity settings */
   BME680::gas_sensor.tph_sett.os_hum = BME680_OS_2X;
   BME680::gas_sensor.tph_sett.os_pres = BME680_OS_4X;
   BME680::gas_sensor.tph_sett.os_temp = BME680_OS_8X;
   BME680::gas_sensor.tph_sett.filter = BME680_FILTER_SIZE_3;

   /* Set the remaining gas sensor settings and link the heating profile */
   BME680::gas_sensor.gas_sett.run_gas = BME680_ENABLE_GAS_MEAS;
   /* Create a ramp heat waveform in 3 steps */
   BME680::gas_sensor.gas_sett.heatr_temp = 320; /* degree Celsius */
   BME680::gas_sensor.gas_sett.heatr_dur = 150; /* milliseconds */

   /* Select the power mode */
   /* Must be set before writing the sensor configuration */
   BME680::gas_sensor.power_mode = BME680_FORCED_MODE;

   /* Set the required sensor settings needed */
   set_required_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_FILTER_SEL
       | BME680_GAS_SENSOR_SEL;

   /* Set the desired sensor configuration */
   rslt = bme680_set_sensor_settings(set_required_settings,&BME680::gas_sensor);
   (void)rslt;

   /* Set the power mode */
   rslt = bme680_set_sensor_mode(&BME680::gas_sensor);
   (void)rslt;

   memset((void *)&BME680::data, 0, sizeof(BME680::data));

   uint16_t meas_period;
   bme680_get_profile_dur(&meas_period, &BME680::gas_sensor);
   lInfo ( "BME680 meas: %d ms", meas_period );

   return;
}

int CBme680::getTemperature(int &sta)
{
   //int sta;

   sta = bme680_get_sensor_data(&BME680::data, &BME680::gas_sensor);
   if(!sta)
   {
      if ( BME680::gas_sensor.power_mode == BME680_FORCED_MODE )
      {
         sta=bme680_set_sensor_mode(&BME680::gas_sensor)*0x100;
      }
   }
   if(sta<0)   // >0 are warnings
   {
      BME680::data.temperature=0x0;
      BME680::data.gas_resistance=0x0;
      BME680::data.humidity=sta;
   }
   return(BME680::data.temperature);
}

int CBme680::getGasResistance()
{
   if( ! (BME680::data.status & BME680_GASM_VALID_MSK) )
   {
      return(0);
   }
   return(BME680::data.gas_resistance);
}

int CBme680::getPressure()
{
   if( ! (BME680::data.status & BME680_GASM_VALID_MSK) )
   {
      return(0);
   }
   return(BME680::data.pressure);
}

int CBme680::getHumidity()
{
   if( ! (BME680::data.status & BME680_GASM_VALID_MSK) )
   {
      return(0);
   }
   return(BME680::data.humidity);
}


int8_t user_i2c_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)
{
    int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */
    rslt=BME680::i2cSlave->i2cReadData(reg_addr, (void *)reg_data, len);
    return rslt;
}

int8_t user_i2c_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)
{
    int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */
    rslt=BME680::i2cSlave->i2cWriteData(reg_addr, (void *)reg_data, len);
    return rslt;
}

void user_delay_ms(uint32_t period)
{
   usleep(period*USECS_PER_MSEC);
}


//---fin-----------------------------------------------------------------------
