/******************************************************************************
*
*  AVR Code example to read a TSIC-206 / TSIC-306 digital temperatur probe
*
*  Based on C++ Samplecode in 
*  "Tech Notes - ZACwireTM Digital Output, Rev. 2.3, October 17, 2006"
*
*  Tested with ATMega8, avr-gcc (GCC) 4.3.0 and a TSIC-206
*
*  see also discussion at http://www.mikrocontroller.net/topic/82087
*
******************************************************************************/

#define F_CPU 8000000UL    // Clock of target system
#include <avr/io.h>
#include <util/delay.h>


/******************************************************************************
* Hardware Connection of the TSIC-Sensor
******************************************************************************/

#define TSIC_PORT             PORTD  // Port to use
#define TSIC_PIN              PIND
#define TSIC_PORT_DDR         DDRD
#define TSCI_POWER_PIN        PD6    // Where TSIC-Sensors VCC is connected
#define TSIC_SIGNAL_PIN       PD7    // Where TSIC-Sensors "Signal"-Pin is con.


/******************************************************************************
* FUNCTION MACROS
******************************************************************************/

// Define TSCI_POWER_PIN as output, TSIC_SIGNAL_PIN as input
#define TSIC_INIT()           { TSIC_PORT_DDR |= (1<<TSCI_POWER_PIN); \
                              TSIC_PORT_DDR &= ~(1<<TSIC_SIGNAL_PIN); }

// Power up the TSIC-Sensor
#define TSIC_ON()             TSIC_PORT |=  (1<<TSCI_POWER_PIN)

// Power down the TSIC-Sensor
#define TSIC_OFF()            TSIC_PORT &= ~(1<<TSCI_POWER_PIN)

//#define TSIC_SIGNAL           (TSIC_PORT &   (1<<TSIC_SIGNAL_PIN))

// Low/High Signal of the TSIC-Sensor, e.g. "if(TSIC_SIGNAL_HIGH)..."
#define TSIC_SIGNAL_HIGH      TSIC_PIN & ( 1 << TSIC_SIGNAL_PIN )
#define TSIC_SIGNAL_LOW       !( TSIC_PIN & ( 1 << TSIC_SIGNAL_PIN ))


/******************************************************************************
* Function    :   getTSicTemp(*temp_value16);
* Description :   reads from the TSic its output value
* Parameters  :   pointer for return value
* Returns     :   1: reading sucessfull, 0: parity error
******************************************************************************/
uint8_t getTSicTemp (uint16_t *temp_value16) {

  uint16_t temp_value1 = 0;
  uint16_t temp_value2 = 0;
  uint8_t i;
  uint16_t Temperature;
  uint8_t parity;

  TSIC_ON();
  _delay_us(60);  // wait for stabilization
  _delay_us(60);

  while (TSIC_SIGNAL_HIGH); // wait until start bit starts

  // wait, TStrobe
  while (TSIC_SIGNAL_LOW);

  // first data byte
  // read 8 data bits and 1 parity bit
  for (i = 0; i < 9; i++) {
    while (TSIC_SIGNAL_HIGH);              // wait for falling edge
    _delay_us(60);
    if (TSIC_SIGNAL_HIGH)
        temp_value1 |= 1 << (8-i);         // get the bit
      else
        while (TSIC_SIGNAL_LOW);           // wait until line comes high again
  }

  // second byte
  while (TSIC_SIGNAL_HIGH);
  // wait, TStrobe
  while (TSIC_SIGNAL_LOW);
  // read 8 data bits and 1 parity bit
  for (i = 0; i < 9; i++) {
    while (TSIC_SIGNAL_HIGH);               // wait for falling edge
    _delay_us(60);
    if (TSIC_SIGNAL_HIGH)
        temp_value2 |= 1 << (8-i);          // get the bit
      else
        while (TSIC_SIGNAL_LOW);            // wait until line comes high again
  }

  TSIC_OFF();                               // switch TSic off

  // check parity for byte 1
  parity = 0;
  for (i = 0; i < 9; i++)
    if (temp_value1 & (1 << i))
        parity++;
  if (parity % 2)
  return 0;

  // check parity for byte 2
  parity = 0;
  for (i = 0; i < 9; i++)
    if (temp_value2 & (1 << i))
        parity++;
  if (parity % 2)
        return 0;
  temp_value1 >>= 1;                 // delete parity bit
  temp_value2 >>= 1;                 // delete parity bit
  Temperature = (temp_value1 << 8) | temp_value2;
  *temp_value16 = Temperature;

  return 1;                       // parity is OK
}


/******************************************************************************
* Test application
******************************************************************************/
int main (void) {

  uint16_t temperatur;  // 11-bit temperature value
  uint8_t returnvalue;  // return value of getTSicTemp(*temp);
  uint8_t Temp_celsius; // converted temperature in °C

  TSIC_INIT();          // set data direction of IO-Pins


  while(1){

    returnvalue = getTSicTemp(&temperatur);  // pull the TSIC-Sensor

    // conversion equation from TSic's data sheet
    Temp_celsius = ((float)temperatur / 2047 * 200) - 50;

    // DO SOMETHING USEFUL WITH THE VALUES HERE!
    // e.g. display them ;)


  }

}

