///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// Driver file for SHT1x Temperature & Humidity Sensor                       //
//                                                                           //
// ***** To initialise SHT1x sensor upon power up *****                      //
//                                                                           //
// Function : sht_init()                                                     //
// Return   : none                                                           //
//                                                                           //
//                                                                           //
// ***** To measure and caluculate SHT75 temp & real RH *****                //
//                                                                           //
// Function : sht_rd (temp, truehumid)                                       //
// Return   : temperature & true humidity in float values                    //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

//#define sht_data_pin   PIN_D0
//#define sht_clk_pin    PIN_D1

//#include <math.h>


#define noACK 0
#define ACK   1
                            //adr  command  r/w
#define STATUS_REG_W 0x06   //000   0011    0
#define STATUS_REG_R 0x07   //000   0011    1
#define MEASURE_TEMP 0x03   //000   0001    1
#define MEASURE_HUMI 0x05   //000   0010    1
#define RESET        0x1e   //000   1111    0

//***** Function to alert SHT75 *****
// generates a transmission start 
//       _____         ________
// DATA:      |_______|
//           ___     ___
// SCK : ___|   |___|   |______

void sht_comstart (void)
{
 output_float(sht_data_pin);  //data high
 output_low(sht_clk_pin);  //clk low
 delay_us(2);
 output_high(sht_clk_pin);  //clk high
 delay_us(2);
 output_low(sht_data_pin); //data low
 delay_us(2);
 output_low(sht_clk_pin);  //clk low
 delay_us(5);
 output_high(sht_clk_pin);  //clk high
 delay_us(2);
 output_float(sht_data_pin);  //data high
 delay_us(2);
 output_low(sht_clk_pin);  //clk low
}


//***** Function to write data to SHT75 *****

int1 sht_comwrite (int8 iobyte)
{
 int8 i, mask = 0x80;
 int1 ack;

 //Shift out command
 delay_us(5);
 for(i=0; i<8; i++)
  {
   output_low(sht_clk_pin);                          //clk low
   if((iobyte & mask) > 0) output_float(sht_data_pin);  //data high if MSB high
   else output_low(sht_data_pin);                    //data low if MSB low
   delay_us(2);
   output_high(sht_clk_pin);                          //clk high
   delay_us(2);
   mask = mask >> 1;                                    //shift to next bit
  }

 //Shift in ack
 output_low(sht_clk_pin);  //clk low
 delay_us(2);
 ack = input(sht_data_pin);   //get ack bit
 output_high(sht_clk_pin);  //clk high
 delay_us(2);
 output_low(sht_clk_pin);  //clk low
 return(ack);
}


//***** Function to read data from SHT75 *****

int16 sht_comread (void)
{
 int8 i;
 int16 iobyte = 0;
 const int16 mask0 = 0x0000;
 const int16 mask1 = 0x0001;

 //shift in MSB data
 for(i=0; i<8; i++)
  {
   iobyte = iobyte << 1;
   output_high(sht_clk_pin);                //clk high
   delay_us(2);
   if (input(sht_data_pin)) iobyte |= mask1;  //shift in data bit
   else iobyte |= mask0;
   output_low(sht_clk_pin);                //clk low
   delay_us(2);
  }

 //send ack 0 bit
 output_low(sht_data_pin); //data low
 delay_us(2);
 output_high(sht_clk_pin);  //clk high
 delay_us(5);
 output_low(sht_clk_pin);  //clk low
 delay_us(2);
 output_float(sht_data_pin);  //data high

 //shift in LSB data
 for(i=0; i<8; i++)
  {
   iobyte = iobyte << 1;
   output_high(sht_clk_pin);                //clk high
   delay_us(2);
   if (input(sht_data_pin)) iobyte |= mask1;  //shift in data bit
   else iobyte |= mask0;
   output_low(sht_clk_pin);                //clk low
   delay_us(2);
  }

 //send ack 1 bit
 output_float(sht_data_pin);  //data high
 delay_us(2);
 output_high(sht_clk_pin);  //clk high
 delay_us(5);
 output_low(sht_clk_pin);  //clk low

 return(iobyte);
}


//***** Function to wait for SHT75 reading *****

void sht_comwait (void)
{
 int16 sht_delay;

 output_float(sht_data_pin);                     //data high
 output_low(sht_clk_pin);                     //clk low
 delay_us(2);
 for(sht_delay=0; sht_delay<350; sht_delay++)  // wait for max 350ms (for 14bit measurement)
  {
   if (!input(sht_data_pin)) break;              //if sht_data_pin low, SHT75 ready
   delay_ms(1);
  }
}


//***** Function to reset SHT75 communication *****
// communication reset: DATA-line=1 and at least 9 SCK cycles followed by transstart
//       _____________________________________________________         ________
// DATA:                                                      |_______|
//          _    _    _    _    _    _    _    _    _        ___     ___
// SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______|   |___|   |______

void sht_comreset (void)
{
 int8 i;

 output_float(sht_data_pin);    //data high
 output_low(sht_clk_pin);    //clk low
 delay_us(5);
 for(i=0; i<9; i++)
  {
   output_high(sht_clk_pin);  //toggle clk 9 times
   delay_us(5);
   output_low(sht_clk_pin);
   delay_us(5);
 }
 sht_comstart();
}


//***** Function to soft reset SHT75 *****

void sht_soft_reset (void)
{
 sht_comreset();           //SHT75 communication reset
 sht_comwrite(0x1e);       //send SHT75 reset command
 delay_ms(15);         //pause 15 ms
}

//----------------------------------------------------------------------------------
char sht_write_statusreg(unsigned char *p_value)
//----------------------------------------------------------------------------------
// writes the status register with checksum (8-bit)
{ 
  unsigned char error=0;
  sht_comstart();                   //transmission start
  error+=sht_comwrite(STATUS_REG_W);//send command to sensor
  error+=sht_comwrite(*p_value);    //send value of status register
  return error;                     //error>=1 in case of no response form the sensor
}

//***** Function to measure SHT75 temperature *****

int16 sht_measuretemp ()
{
 int1 ack;
 int16 iobyte;

 sht_comstart();             //alert SHT75
 ack = sht_comwrite(0x03);   //send measure temp command and read ack status
 if(ack == 1) return;
 sht_comwait();              //wait for SHT75 measurement to complete
 iobyte = sht_comread();     //read SHT75 temp data
 return(iobyte);
}


//***** Function to measure SHT75 RH *****

int16 sht_measurehumid ()
{
 int1 ack;
 int16 iobyte;

 sht_comstart();            //alert SHT75
 ack = sht_comwrite(0x05);  //send measure RH command and read ack status
 if(ack == 1) return;
 sht_comwait();             //wait for SHT75 measurement to complete
 iobyte = sht_comread();    //read SHT75 temp data
 return(iobyte);
}


//***** Function to calculate SHT75 temp & RH *****

void calculate_data (int16 temp, int16 humid, float & tc, float & rhlin, float & rhtrue)
{
 const float C1=-2.0468;           // for 12 Bit RH
  const float C2=+0.0367;           // for 12 Bit RH
  const float C3=-0.0000015955;     // for 12 Bit RH
//  const float T1=+0.01;             // for 12 Bit RH
//  const float T2=+0.00008;          // for 12 Bit RH
 float rh;

 //calculate temperature reading
 tc = ((float) temp * 0.01) - 40.0;

 //calculate Real RH reading
 rh = (float) humid;

 rhlin = C1 + (rh * C2) + (rh * rh * C3);

 //calculate True RH reading
 rhtrue = ((tc - 25.0) * (0.01 + (0.00008 * rh))) + rhlin;
 
  if(rhtrue>99)rhtrue=100;       //cut if the value is outside of
  if(rhtrue<0.1)rhtrue=0.1;       //the physical possible range
}


//***** Function to measure & calculate SHT75 temp & RH *****

void sht_rd (float & temp, float & truehumid)
{
 int16 restemp, reshumid;
 float realhumid;
 restemp = 0; truehumid = 0;

 restemp = sht_measuretemp();    //measure temp
 reshumid = sht_measurehumid();  //measure RH
calculate_data (restemp, reshumid, temp, realhumid, truehumid);  //calculate temp & RH
}


//***** Function to initialise SHT75 on power-up *****

void sht_init (void)
{
 sht_comreset();    //reset SHT75
 delay_ms(20);  //delay for power-up
}

//--------------------------------------------------------------------
//float calc_dewpoint(float h,float t)
//--------------------------------------------------------------------
// calculates dew point
// input:   humidity [%RH], temperature [K]
// output:  dew point [K]
//{ float k,dew_point ;
//  
//  k = (log10(h)-2)/0.4343 + (17.62*t)/(243.12+t);
//  dew_point = 243.12*k/(17.62-k);
//  return dew_point;
//}