// This file has been prepared for Doxygen automatic documentation generation.
/*! \file ********************************************************************
 *
 * Atmel Corporation
 *
 * \li File:               OWIHighLevelFunctions.c
 * \li Compiler:           IAR EWAAVR 3.20a
 * \li Support mail:       avr@atmel.com
 *
 * \li Supported devices:  All AVRs.
 *
 * \li Application Note:   AVR318 - Dallas 1-Wire(R) master.
 *
 *
 * \li Description:        High level functions for transmission of full bytes
 *                         on the 1-Wire(R) bus and implementations of ROM
 *                         commands.
 *
 *                         $Revision: 1.3 $
 *                         $Date: 2010-05-21 16:48:30 $
 ****************************************************************************/
//check line 199
#include <avr/io.h>

#include "OWIHighLevelFunctions.h"
#include "OWIBitFunctions.h"
#include "OWIPolled.h"

#include <string.h>
#include <stdio.h>

/*! \brief  Sends one byte of data on the 1-Wire(R) bus(es).
 *  
 *  This function automates the task of sending a complete byte
 *  of data on the 1-Wire bus(es).
 *
 *  \param  data    The data to send on the bus(es).
 *  
 *  \param  pins    A bitmask of the buses to send the data to.
 */
void OWI_SendByte( unsigned char data, unsigned char pins )
{
   unsigned char temp;
   unsigned char i;

   // Do once for each bit
   for ( i = 0; i < 8 ; i++ )
   {
      // Determine if lsb is '0' or '1' and transmit corresponding
      // waveform on the bus.
      temp = data & 0x01;
      if ( temp )
      {
         OWI_WriteBit1(pins);
      }
      else
      {
         OWI_WriteBit0(pins);
      }
      // Right shift the data to get next bit.
      data >>= 1;
   }
}

/*! \brief  Receives one word (2 bytes) of data from the 1-Wire(R) bus.
 *
 *  This function automates the task of receiving a complete word (2 bytes)
 *  of data from the 1-Wire bus.
 *
 *  \param  pin     A bitmask of the bus to read from.
 *  
 *  \return     The word read from the bus.
 */
uint16_t OWI_ReceiveWord( unsigned char pin )
{
   uint16_t data;
   unsigned char i;

   // Clear the temporary input variable.
   data = 0x0000;

   // Do once for each bit
   for ( i = 0; i < 16 ; i++ )
   {
      // Shift temporary input variable right.
      data >>= 1;
      // Set the msb if a '1' value is read from the bus.
      // Leave as it is ('0') else.
      if ( OWI_ReadBit(pin) )
      {
         // Set msb
         data |= 0x8000;
      }
   }
   return data;
}

/*! \brief  Receives one byte of data from the 1-Wire(R) bus.
 *
 *  This function automates the task of receiving a complete byte
 *  of data from the 1-Wire bus.
 *
 *  \param  pin     A bitmask of the bus to read from.
 *
 *  \return     The byte read from the bus.
 */
unsigned char OWI_ReceiveByte( unsigned char pin )
{
   unsigned char data;
   unsigned char i;

   // Clear the temporary input variable.
   data = 0x00;

   // Do once for each bit
   for ( i = 0; i < 8 ; i++ )
   {
      // Shift temporary input variable right.
      data >>= 1;
      // Set the msb if a '1' value is read from the bus.
      // Leave as it is ('0') else.
      if ( OWI_ReadBit(pin) )
      {
         // Set msb
         data |= 0x80;
      }
   }
   return data;
}

/*! \brief  Sends the SKIP ROM command to the 1-Wire bus(es).
 *
 *  \param  pins    A bitmask of the buses to send the SKIP ROM command to.
 */
void OWI_SkipRom( unsigned char pins )
{
   // Send the SKIP ROM command on the bus.
   OWI_SendByte(OWI_ROM_SKIP, pins);
}

/*! \brief  Sends the READ ROM command and reads back the ROM id.
 *
 *  \param  romValue    A pointer where the id will be placed.
 *
 *  \param  pin     A bitmask of the bus to read from.
 */
void OWI_ReadRom( unsigned char * romValue, unsigned char pin )
{
   unsigned char bytesLeft = 8;

   // Send the READ ROM command on the bus.
   OWI_SendByte(OWI_ROM_READ, pin);

   // Do 8 times.
   while ( bytesLeft > 0 )
   {
      // Place the received data in memory.
      *romValue++ = OWI_ReceiveByte(pin);
      bytesLeft--;
   }
}

/*! \brief  Sends the MATCH ROM command and the ROM id to match against.
 *
 *  \param  romValue    A pointer to the ID to match against.
 *
 *  \param  pins    A bitmask of the buses to perform the MATCH ROM command on.
 */
void OWI_MatchRom( unsigned char * romValue, unsigned char pins )
{
   //      break_point(70,"matchrom");
   unsigned char bytesLeft = 8;

   // Send the MATCH ROM command.
   OWI_SendByte(OWI_ROM_MATCH, pins);
   //    break_point(71,"matchrom");
   // Do once for each byte.
   while ( bytesLeft > 0 )
   {
      // Transmit 1 byte of the ID to match.
      OWI_SendByte(*romValue++, pins);
      bytesLeft--;
   }
   // break_point(72,"matchrom");
}

/*! \brief  Sends the SEARCH ROM command and returns 1 id found on the 
 *          1-Wire(R) bus.
 *
 *  \param  bitPattern      A pointer to an 8 byte char array where the 
 *                          discovered identifier will be placed. When 
 *                          searching for several slaves, a copy of the 
 *                          last found identifier should be supplied in 
 *                          the array, or the search will fail.
 *
 *  \param  lastDeviation   The bit position where the algorithm made a 
 *                          choice the last time it was run. This argument 
 *                          should be 0 when a search is initiated. Supplying 
 *                          the return argument of this function when calling 
 *                          repeatedly will go through the complete slave 
 *                          search.
 *
 *  \param  pin             A bit-mask of the bus to perform a ROM search on.
 *
 *  \return The last bit position where there was a discrepancy between slave addresses the last time this function was run. Returns OWI_ROM_SEARCH_FAILED if an error was detected (e.g. a device was connected to the bus during the search), or OWI_ROM_SEARCH_FINISHED when there are no more devices to be discovered.
 *
 *  \note   See main.c for an example of how to utilize this function.
 */
unsigned char OWI_SearchRom( unsigned char * bitPattern, unsigned char lastDeviation, unsigned char pin )
{
   unsigned char currentBit = 1;
   unsigned char newDeviation = 0;
   unsigned char bitMask = 0x01;
   unsigned char bitA;
   unsigned char bitB;
   //break_point(30,"searchrom");
   // Send SEARCH ROM command on the bus.
   OWI_SendByte(OWI_ROM_SEARCH, pin);

   // Walk through all 64 bits.
   while ( currentBit <= 64 )
   {
      // Read bit from bus twice.
      bitA = OWI_ReadBit(pin);
      bitB = OWI_ReadBit(pin);
      //break_point(32,"searchrom");
      if ( bitA && bitB )
      {
         // Both bits 1 (Error).
         newDeviation = OWI_ROM_SEARCH_FAILED;
         //  break_point(33,"OWI failed");
         return newDeviation;
      }
      else if ( bitA ^ bitB )
      {
         //	    break_point(34,"searchrom");
         // Bits A and B are different. All devices have the same bit here.
         // Set the bit in bitPattern to this value.
         if ( bitA )
         {
            //	    break_point(35,"searchrom");
            ( *bitPattern ) |= bitMask;

         }
         else
         {
            //    break_point(36,"searchrom");
            ( *bitPattern ) &= ~bitMask;
         }
      }
      else // Both bits 0
      {
         // If this is where a choice was made the last time,
         // a '1' bit is selected this time.
         if ( currentBit == lastDeviation )
         {
            //break_point(38,"searchrom");
            ( *bitPattern ) |= bitMask;
         }
         // For the rest of the id, '0' bits are selected when
         // discrepancies occur.
         else if ( currentBit > lastDeviation )
         {
            //  break_point(39,"searchrom");
            ( *bitPattern ) &= ~bitMask;
            newDeviation = currentBit;
         }
         // If current bit in bit pattern = 0, then this is
         // out new deviation.
         else if ( !( *bitPattern & bitMask ) )
         {
            //break_point(40,"searchrom");
            newDeviation = currentBit;
         }
         // IF the bit is already 1, do nothing.
         else
         {
            //break_point(41,"searchrom");
         }
      }

      // Send the selected bit to the bus.
      if ( ( *bitPattern ) & bitMask )
      {
         //break_point(42,"searchrom");
         OWI_WriteBit1(pin);
      }
      else
      {
         //break_point(43,"searchrom");
         OWI_WriteBit0(pin);
      }

      // Increment current bit.
      currentBit++;
      //    break_point(44,"searchrom");
      // Adjust bitMask and bitPattern pointer.
      bitMask <<= 1;
      if ( !bitMask )
      {
         //  break_point(45,"searchrom");
         bitMask = 0x01;
         bitPattern++;
      }
   }
   /*    uint8_t str[80];
    sprintf(str,"ID %x% x% x% x% x% x% x% x",bitPattern[0],bitPattern[1],bitPattern[2],bitPattern[3],bitPattern[4],bitPattern[5],bitPattern[6],bitPattern[7]);
    break_point(52,str);//it only reads a lot of 0*/
   //    break_point(14,"OWI search");
   return newDeviation;
}

unsigned char OWI_SearchAlarm( unsigned char * bitPattern, unsigned char lastDeviation, unsigned char pin )
{
   unsigned char currentBit = 1;
   unsigned char newDeviation = 0;
   unsigned char bitMask = 0x01;
   unsigned char bitA;
   unsigned char bitB;

   // Send SEARCH ROM command on the bus.
   OWI_SendByte(OWI_ROM_ALARM, pin);

   // Walk through all 64 bits.
   while ( currentBit <= 64 )
   {
      // Read bit from bus twice.
      bitA = OWI_ReadBit(pin);
      bitB = OWI_ReadBit(pin);

      if ( bitA && bitB )
      {
         // Both bits 1 (Error).
         newDeviation = OWI_ROM_SEARCH_FAILED;
         //	    break_point(14,"OWI failed");
         return newDeviation;
      }
      else if ( bitA ^ bitB )
      {
         // Bits A and B are different. All devices have the same bit here.
         // Set the bit in bitPattern to this value.
         if ( bitA )
         {
            ( *bitPattern ) |= bitMask;

         }
         else
         {
            ( *bitPattern ) &= ~bitMask;
         }
      }
      else // Both bits 0
      {
         // If this is where a choice was made the last time,
         // a '1' bit is selected this time.
         if ( currentBit == lastDeviation )
         {
            ( *bitPattern ) |= bitMask;
         }
         // For the rest of the id, '0' bits are selected when
         // discrepancies occur.
         else if ( currentBit > lastDeviation )
         {
            ( *bitPattern ) &= ~bitMask;
            newDeviation = currentBit;
         }
         // If current bit in bit pattern = 0, then this is
         // out new deviation.
         else if ( !( *bitPattern & bitMask ) )
         {
            newDeviation = currentBit;
         }
         // IF the bit is already 1, do nothing.
         else
         {

         }
      }

      // Send the selected bit to the bus.
      if ( ( *bitPattern ) & bitMask )
      {
         OWI_WriteBit1(pin);
      }
      else
      {
         OWI_WriteBit0(pin);
      }

      // Increment current bit.
      currentBit++;

      // Adjust bitMask and bitPattern pointer.
      bitMask <<= 1;
      if ( !bitMask )
      {
         bitMask = 0x01;
         bitPattern++;
      }
   }
   //    char str[80];
   //    sprintf((char *)str,"ID %d %d %d %d %d %d %d %d",bitPattern[0],bitPattern[1],bitPattern[2],bitPattern[3],bitPattern[4],bitPattern[5],bitPattern[6],bitPattern[7]);
   //    break_point(51,str);
   //    break_point(52,"ciao");//it only reads a lot of 0
   return newDeviation;
}

