/****************************************************************************
 Title	:	TERMINAL FOR VISUALIZATION AND CONTROL CONDITIONS IN HOUSE
 Author	:	Patrik Szalay <xszala01@stud.feec.vutbr.cz>
 File	:	htu21d.c
 Software:	CodeWarrior Development Studio Version: 10.6 Build Id:140329
 Target	:	MC9S08LH64

 DESCRIPTION
       Code for the HTU21D temperature/humidity sensor

 USAGE
       
*****************************************************************************/
#include "htu21d.h"

void htu21d_set_reg(ADDRESS addr, unsigned char ConfR, char* data){
	data[0] = HTU21D_READ_USER_REG;
	IICTransmit(addr,1,data);
	delay(1000);
	IICReceive(addr,1,data);
	data[0] = HTU21D_WRITE_USER_REG;
	data[1] = ConfR;
	IICTransmit(addr,1,data);	
}

unsigned char htu21d_get_reg(ADDRESS addr, char* data){
	data[0] = HTU21D_READ_USER_REG;
	IICTransmit(addr,1,data);
	delay(1000);
	IICReceive(addr,1,data);
	return data[0];
}

void htu21d_soft_reset(ADDRESS addr, char* data){
	data[0] = HTU21D_SOFT_RESET;
	IICTransmit(addr,1,data);		
}

void htud21d_trigTempMeas(ADDRESS addr, char* data){
	data[0] = HTU21D_TRIG_TEMP_MEAS_NO_HOLD_MASTER;
	IICTransmit(addr,1,data);
}

void htud21d_trigHumMeas(ADDRESS addr, char* data){
	data[0] = HTU21D_TRIG_HUM_MEAS_NO_HOLD_MASTER;
	IICTransmit(addr,1,data);
}

#ifdef __NO_FLOAT__
decimal htu21d_readTemp_decimal(ADDRESS addr, char* data){
	int i = 0;
	unsigned long long int temp = 0;
	unsigned int message_from_sensor;
	data[0] = HTU21D_TRIG_TEMP_MEAS_NO_HOLD_MASTER;
	IICTransmit(addr,1,data);
	delay(10000);
	IICReceive(addr,3,data);
	if(data[0] & data[1] == 0xFF) return IIC_INVALID_DATA; /* I2C timeout */
	message_from_sensor = (((unsigned int)data[0])<<8 | data[1]);
	if(htu21d_check_crc(message_from_sensor, data[2]) != 0) return CRC_ERR; /* CRC wrong */
	data[1] &= ~HTU21D_MEAS_STAT_MASK;
	temp = (message_from_sensor>>1)*100000;
	temp = ((temp>>15)*17572)/100000;
	return (temp-4685);
}

decimal htu21d_readHum_decimal(ADDRESS addr, char* data){
	int i = 0;
	unsigned long long int temp = 0;
	unsigned int message_from_sensor;
	char tempData[4];
	decimal hum = 0, temperature = 0;
	data[0] = HTU21D_TRIG_HUM_MEAS_NO_HOLD_MASTER;
	IICTransmit(addr,1,data);
	delay(10000);
	IICReceive(addr,3,data);
	if(data[0] & data[1] == 0xFF) return IIC_INVALID_DATA; /* I2C timeout */
	message_from_sensor = (((unsigned int)data[0])<<8 | data[1]);
	if(htu21d_check_crc(message_from_sensor, data[2]) != 0) return CRC_ERR; /* CRC wrong */
	data[1] &= ~HTU21D_MEAS_STAT_MASK;
	temp = (message_from_sensor>>1)*100000;
	temp = ((temp>>15) * 12500) / 100000;
	hum = (temp-600);
	temperature = htu21d_readTemp_decimal(addr, tempData);
	if(temperature > 0 && temperature < 8000){
		hum = ((hum * 100) - (((2500 - temperature) * HTU21D_RH_TEMP_COEFF_DECIMAL)))/100;
	}
	if(hum < 0) return 0;
	else if (hum > 10000) return 10000;
	else return hum;
}

char htu21d_readTemp_char(ADDRESS addr, char* data){
	return (char) htu21d_readTemp_decimal(addr, data)/100;
}

char htu21d_readHum_char(ADDRESS addr, char* data){
	return (char) htu21d_readHum_decimal(addr, data)/100;
}

#else

float htu21d_readTemp_float(ADDRESS addr, char* data){
	int i = 0;
	data[0] = HTU21D_TRIG_TEMP_MEAS_NO_HOLD_MASTER;
	IICTransmit(addr,1,data);
	for(i = 0; i < 10000; i++) __RESET_WATCHDOG();
	IICReceive(addr,2,data);
	if(data[0] & data[1] == 0xFF) return 9999;
	data[1] &= ~HTU21D_MEAS_STAT_MASK;
	return (-46.85 + 175.72 * (( ((unsigned int)data[0])<<8 | data[1])) / 65536.0);
}

float htu21d_readHum_float(ADDRESS addr, char* data){
	int i = 0;
	float hum = 0, temp = 0;
	data[0] = HTU21D_TRIG_HUM_MEAS_NO_HOLD_MASTER;
	IICTransmit(addr,1,data);
	for(i = 0; i < 10000; i++) __RESET_WATCHDOG();
	IICReceive(addr,2,data);
	if(data[0] & data[1] == 0xFF) return 9999;
	data[1] &= ~HTU21D_MEAS_STAT_MASK;
	hum = (-6.0 + 125.0 * (((unsigned int)data[0]<<8 | data[1])) / 65536.0);
	temperature = htu21d_readTemp_float(addr, tempData);
	if(temperature > 0 && temperature < 8000){
		hum = hum - ((25.0 - temperature) * HTU21D_RH_TEMP_COEFF_FLOAT);
	}
	if( hum < 0.0) return 0.0;
	else if ( hum > 100.0) return 100.0;
	else return hum;
}
 
char htu21d_readTemp_char(unsigned char addr){
	return (char) htu21d_readTemp_float(addr);
}

 char htu21d_readHum_char(unsigned char addr){
 	return (char) htu21d_readHum_float(addr);
} 
 
#endif
 
unsigned char htu21d_check_crc(unsigned int message_from_sensor, unsigned char check_value_from_sensor)
{
  unsigned long int remainder = (unsigned long int)message_from_sensor << 8; /* Pad with 8 bits because we have to add in the check value */
  unsigned long int divsor = (unsigned long int)HTU21D_SHIFTED_DIVISOR;
  int i = 0;
  
  remainder |= check_value_from_sensor; /* Add on the check value */

  for (i = 0 ; i < 16 ; i++) /* Operate on only 16 positions of max 24. The remaining 8 are our remainder and should be zero when we're done. */
  {
	  
    if( remainder & (unsigned long int)1<<(unsigned char)(23 - i) ) /* Check if there is a one in the left position */
      remainder ^= divsor;

    divsor >>= 1; /* Rotate the divisor max 16 times so that we have 8 bits left of a remainder */
  }

  return (unsigned char)remainder;
}



