/**
 * @brief  Set HTS221 Initialization
 * @param  HTS221_Init the configuration setting for the HTS221
 * @retval HUM_TEMP_OK in case of success, an error code otherwise
 */
static HUM_TEMP_StatusTypeDef HTS221_Init(HUM_TEMP_InitTypeDef *HTS221_Init)
{  
    uint8_t tmp = 0x00;

    /* Configure the low level interface ---------------------------------------*/
    if(HTS221_IO_Init() != HUM_TEMP_OK)
    {
      return HUM_TEMP_ERROR;
    }

    if(HTS221_Power_On() != HUM_TEMP_OK)
    {
      return HUM_TEMP_ERROR;
    }

    if(HTS221_Calibration() != HUM_TEMP_OK)
    {
      return HUM_TEMP_ERROR;
    }
    ////////////////////////////////////////////////////////////////////////////////
    if(HTS221_IO_Read(&tmp, HTS221_ADDRESS, HTS221_RES_CONF_ADDR, 1) != HUM_TEMP_OK)
    {
      return HUM_TEMP_ERROR;
    }

    /* Resolution Register */
    tmp &= ~(HTS221_H_RES_MASK);
    tmp |= HTS221_Init->Humidity_Resolutin;
    
    tmp &= ~(HTS221_T_RES_MASK);
    tmp |= HTS221_Init->Temperature_Resolution;

    if(HTS221_IO_Write(&tmp, HTS221_ADDRESS, HTS221_RES_CONF_ADDR, 1) != HUM_TEMP_OK)
    {
      return HUM_TEMP_ERROR;
    }
    //////////////////////////////////////////////////////////////////////////////////
    if(HTS221_IO_Read(&tmp, HTS221_ADDRESS, HTS221_CTRL_REG1_ADDR, 1) != HUM_TEMP_OK)
    {
      return HUM_TEMP_ERROR;
    }

    /* Output Data Rate selection */
    tmp &= ~(HTS221_ODR_MASK);
    tmp |= HTS221_Init->OutputDataRate;

    if(HTS221_IO_Write(&tmp, HTS221_ADDRESS, HTS221_CTRL_REG1_ADDR, 1) != HUM_TEMP_OK)
    {
      return HUM_TEMP_ERROR;
    }
    
    return HUM_TEMP_OK;
}
/**
 * @brief  Read HTS221 output register, and calculate the temperature
 * @param  pfData the pointer to data output
 * @retval HUM_TEMP_OK in case of success, an error code otherwise
 */
static HUM_TEMP_StatusTypeDef HTS221_GetTemperature(float* pfData)
{
  int16_t T_out, temperature_t;
  uint8_t tempReg[2] = {0, 0};
  uint8_t tmp = 0x00;
  float T_degC;
  
  if(HTS221_IO_Read(&tmp, HTS221_ADDRESS, HTS221_CTRL_REG1_ADDR, 1) != HUM_TEMP_OK)
  {
    return HUM_TEMP_ERROR;
  }
  
  /* Output Data Rate selection */
  tmp &= (HTS221_ODR_MASK);
  
  if(tmp == 0x00)
  {
    if(HTS221_IO_Read(&tmp, HTS221_ADDRESS, HTS221_CTRL_REG2_ADDR, 1) != HUM_TEMP_OK)
    {
      return HUM_TEMP_ERROR;
    }
    
    /* Serial Interface Mode selection */
    tmp &= ~(HTS221_ONE_SHOT_MASK);
    tmp |= HTS221_ONE_SHOT_START;
    
    if(HTS221_IO_Write(&tmp, HTS221_ADDRESS, HTS221_CTRL_REG2_ADDR, 1) != HUM_TEMP_OK)
    {
      return HUM_TEMP_ERROR;
    }
    
    do
    {
    
      if(HTS221_IO_Read(&tmp, HTS221_ADDRESS, HTS221_STATUS_REG_ADDR, 1) != HUM_TEMP_OK)
      {
        return HUM_TEMP_ERROR;
      }
      
    }
    while(!(tmp && 0x01));
  }
  
  if(HTS221_IO_Read(&tempReg[0], HTS221_ADDRESS, (HTS221_TEMP_OUT_L_ADDR | HTS221_I2C_MULTIPLEBYTE_CMD),
                    2) != HUM_TEMP_OK)
  {
    return HUM_TEMP_ERROR;
  }
  
  T_out = ((((int16_t)tempReg[1]) << 8) + (int16_t)tempReg[0]);
  
  T_degC = ((float)(T_out - T0_out)) / (T1_out - T0_out) * (T1_degC - T0_degC) + T0_degC;
  
  temperature_t = (int16_t)(T_degC * pow(10, TEMP_DECIMAL_DIGITS));
  
  *pfData = ((float)temperature_t) / pow(10, TEMP_DECIMAL_DIGITS);
  
  return HUM_TEMP_OK;
}
/**
 * @brief  Enter the shutdown mode for HTS221
 * @retval HUM_TEMP_OK in case of success, an error code otherwise
 */
static HUM_TEMP_StatusTypeDef HTS221_Power_OFF(void)
{
  uint8_t tmpReg;
  
  /* Read the register content */
  if(HTS221_IO_Read(&tmpReg, HTS221_ADDRESS, HTS221_CTRL_REG1_ADDR, 1) != HUM_TEMP_OK)
  {
    return HUM_TEMP_ERROR;
  }
  
  /* Reset the power down bit */
  tmpReg &= ~(HTS221_MODE_ACTIVE);
  
  /* Write register */
  if(HTS221_IO_Write(&tmpReg, HTS221_ADDRESS, HTS221_CTRL_REG1_ADDR, 1) != HUM_TEMP_OK)
  {
    return HUM_TEMP_ERROR;
  }
  
  return HUM_TEMP_OK;
}
/**
 * @brief  Reboot memory content of HTS221
 * @retval HUM_TEMP_OK in case of success, an error code otherwise
 */
static HUM_TEMP_StatusTypeDef HTS221_RebootCmd(void)
{
  uint8_t tmpreg;
  
  /* Read CTRL_REG2 register */
  if(HTS221_IO_Read(&tmpreg, HTS221_ADDRESS, HTS221_CTRL_REG2_ADDR, 1) != HUM_TEMP_OK)
  {
    return HUM_TEMP_ERROR;
  }
  
  /* Enable or Disable the reboot memory */
  tmpreg |= HTS221_BOOT_REBOOTMEMORY;
  
  /* Write value to MEMS CTRL_REG2 regsister */
  if(HTS221_IO_Write(&tmpreg, HTS221_ADDRESS, HTS221_CTRL_REG2_ADDR, 1) != HUM_TEMP_OK)
  {
    return HUM_TEMP_ERROR;
  }
  
  return HUM_TEMP_OK;
}
/**
 * @brief  Set HTS221 Initialization
 * @param  HTS221_Init the configuration setting for the HTS221
 * @retval HUM_TEMP_OK in case of success, an error code otherwise
 */
static HUM_TEMP_StatusTypeDef HTS221_Init(HUM_TEMP_InitTypeDef *HTS221_Init)
{
  uint8_t tmp = 0x00;
  
  /* Configure the low level interface ---------------------------------------*/
	/* I2C1 already configured in MX_I2C1_Init - JBD */
//  if(HTS221_IO_Init() != HUM_TEMP_OK)
//  {
//    return HUM_TEMP_ERROR;
//  }
  
  if(HTS221_Power_On() != HUM_TEMP_OK)
  {
    return HUM_TEMP_ERROR;
  }
  
  if(HTS221_Calibration() != HUM_TEMP_OK)
  {
    return HUM_TEMP_ERROR;
  }
  
  if(HTS221_IO_Read(&tmp, HTS221_ADDRESS, HTS221_CTRL_REG1_ADDR, 1) != HUM_TEMP_OK)
  {
    return HUM_TEMP_ERROR;
  }
  
  /* Output Data Rate selection */
  tmp &= ~(HTS221_ODR_MASK);
  tmp |= HTS221_Init->OutputDataRate;
  
  if(HTS221_IO_Write(&tmp, HTS221_ADDRESS, HTS221_CTRL_REG1_ADDR, 1) != HUM_TEMP_OK)
  {
    return HUM_TEMP_ERROR;
  }
  
  HTS221_IO_ITConfig();
  
  return HUM_TEMP_OK;
}
/**
 * @brief  Read HTS221 output register, and calculate the humidity
 * @param  pfData the pointer to data output
 * @retval HUM_TEMP_OK in case of success, an error code otherwise
 */
static HUM_TEMP_StatusTypeDef HTS221_GetHumidity(float* pfData)
{
  int16_t H_T_out, humidity_t;
  uint8_t tempReg[2] = {0, 0};
  uint8_t tmp = 0x00;
  float H_rh;
  
  if(HTS221_IO_Read(&tmp, HTS221_ADDRESS, HTS221_CTRL_REG1_ADDR, 1) != HUM_TEMP_OK)
  {
    return HUM_TEMP_ERROR;
  }
  
  /* Output Data Rate selection */
  tmp &= (HTS221_ODR_MASK);
  
  if(tmp == 0x00)
  {
    if(HTS221_IO_Read(&tmp, HTS221_ADDRESS, HTS221_CTRL_REG2_ADDR, 1) != HUM_TEMP_OK)
    {
      return HUM_TEMP_ERROR;
    }
    
    /* Serial Interface Mode selection */
    tmp &= ~(HTS221_ONE_SHOT_MASK);
    tmp |= HTS221_ONE_SHOT_START;
    
    if(HTS221_IO_Write(&tmp, HTS221_ADDRESS, HTS221_CTRL_REG2_ADDR, 1) != HUM_TEMP_OK)
    {
      return HUM_TEMP_ERROR;
    }
    
    do
    {
    
      if(HTS221_IO_Read(&tmp, HTS221_ADDRESS, HTS221_STATUS_REG_ADDR, 1) != HUM_TEMP_OK)
      {
        return HUM_TEMP_ERROR;
      }
      
    }
    while(!(tmp && 0x02));
  }
  
  
  if(HTS221_IO_Read(&tempReg[0], HTS221_ADDRESS, (HTS221_HUMIDITY_OUT_L_ADDR | HTS221_I2C_MULTIPLEBYTE_CMD),
                    2) != HUM_TEMP_OK)
  {
    return HUM_TEMP_ERROR;
  }
  
  H_T_out = ((((int16_t)tempReg[1]) << 8) + (int16_t)tempReg[0]);
  
  H_rh = ( float )(((( H_T_out - H0_T0_out ) * ( H1_rh - H0_rh )) / ( H1_T0_out - H0_T0_out )) + H0_rh );
  
  // Truncate to specific number of decimal digits
  humidity_t = (uint16_t)(H_rh * pow(10, HUM_DECIMAL_DIGITS));
  *pfData = ((float)humidity_t) / pow(10, HUM_DECIMAL_DIGITS);
  
  // Prevent data going below 0% and above 100% due to linear interpolation
  if ( *pfData <   0.0f ) *pfData =   0.0f;
  if ( *pfData > 100.0f ) *pfData = 100.0f;
  
  return HUM_TEMP_OK;
}