/*************************************************************
I2C.C

This program contains I2C routines.

Written for Hi-Tech PICC compiler vX.XX
**************************************************************/

#include	<pic.h>
#include 	"I2C.H"

/********************************************************************
   Function Name:  OpenI2C                                         
   Return Value:   void                                            
   Parameters:     SSP peripheral setup bytes                     
   Description:    This function sets up the SSP module on a       
                   PIC16 device for use with a Microchip I2C       
                   EEPROM device or I2C bus device.                
********************************************************************/
void OpenI2C(unsigned char sync_mode, unsigned char slew)
{
  SSPSTAT &= 0x00;      // power on state  3f
  SSPCON = 0x00;        // power on state
  SSPCON |= sync_mode;  // select serial mode 

  CKP = 1;						  // Releases clock (no clock stretching)
  SSPEN = 1;            // enable synchronous serial port 
}

/*************************************************************
   Function Name:  I2CStart                                         
   Return Value:   void                                            
   Parameters:     void                     
   Description:    Sends an I2C Start bit       
**************************************************************/
void I2CStart()
{
    //Precondition SCL and SDA
    SCL_L;				      //SCL LOW just in case it is not already LOW
    SDA_H;				      //SDA HIGH
    SCL_H;				      //SCL HIGH

    //START Condition
    SDA_L;
    while(!START);      //wait for START
    while(!SSPIF);  	  //Wait for flag to set
    SSPIF = 0;
}
  
/*************************************************************
   Function Name:  I2CReStart                                         
   Return Value:   void                                            
   Parameters:     void                     
   Description:    Sends an I2C Re-start bit       
**************************************************************/
void I2CReStart()
{
  //Precondition SCL and SDA
  SCL_L;				    //SCL LOW just in case it is not already LOW
  SDA_H;				    //SDA HIGH
  SCL_H;				    //SCL HIGH

  //START Condition
  SDA_L;
  while(!START);    //wait for START
  while(!SSPIF);  	//Wait for flag to set
  SSPIF = 0;
}

/********************************************************************
     Function Name:    AckI2C                                     
     Return Value:     void                                        
     Parameters:       void                                        
     Description:      Initiate ACK bus condition.                 
********************************************************************/
void ACKI2C(void)
{
  ACK;  					  //Start ACK sequence
}

/*************************************************************
   Function Name:  WaitForACK                                         
   Return Value:   Returns 0 if ACK; returns -1 if timeout                                            
   Parameters:     void                     
   Description:    Waits for an ACK from the slave device       
**************************************************************/
unsigned char WaitForACK()
{
	unsigned char n = 0;
	
	SDA_H;              //Float SDA
	
	SCL_H;					    //Starts ACK pulse
	while(SDA_LEVEL)    //Waits for slave ACK
	{
  	n++;
  	if(!n) return -1; //return -1 on timeout
  }
  SCL_L;					    //Ends ACK pulse
  return 0;	
}

/*************************************************************
   Function Name:  I2CStop                                         
   Return Value:   void                                            
   Parameters:     void                     
   Description:    Sends a Stop bit       
**************************************************************/
void I2CStop()
{
  SSPIF = 0;
  //Precondition SCL and SDA
  SCL_L;					//SCL LOW just in case it is not already LOW
  SDA_L;					//SDA LOW
  SCL_H;					//SCL HIGH

  SDA_H;    	  	//Stop condition
  while(!STOP);		//wait for STOP
  while(!SSPIF);	//Wait for flag to set
  SSPIF = 0;
}

/********************************************************************
     Function Name:    WriteI2C                                   
     Return Value:     Status             
     Parameters:       Single data byte for I2C bus.              
     Description:      This routine writes a single byte to the     
                       I2C bus.                     
********************************************************************/
unsigned char WriteI2C( unsigned char data_out )
{
  unsigned char n;
  SCL_L;					//SCL LOW... just in case

	for(n=0; n<8; n++)
	{
		if((data_out << n) & 0x80)
		{
  		SDA_H;
  		SCL_H;
  		SCL_L;
  	}
  	else
  	{
  		SDA_L;
  		SCL_H;
  		SCL_L;
  	}
	}
  return 0;
}

/********************************************************************
     Function Name:    ReadI2C                   
     Return Value:     Read value               
     Parameters:       void                                        
     Description:      Read single byte from I2C bus.             
********************************************************************/
unsigned char ReadI2C(void)
{
	unsigned char n, data_in;
	data_in = 0;
	for(n=0; n<8; n++)
	{
		SCL_H;
		data_in = ((data_in + SDA_LEVEL) << 1);
		SCL_L;
	}
	data_in = data_in >> 1;
	return(data_in);
}

/*************************************************************
   Function Name:  nACK                                         
   Return Value:   void                                            
   Parameters:     void                     
   Description:    Sends an ACK bit       
**************************************************************/
void nACK()
{
  NACK;    				//Start ACK sequence
}

/*************************************************************
   Function Name:  I2CDataReady                                         
   Return Value:   BF bit                                            
   Parameters:     void                     
   Description:    Sends a Stop bit       
**************************************************************/
unsigned char I2CDataReady()
{
  if (BF)			        // test if buffer full bit is set     
    return ( +1 );    // data in SSPBUF register
  else
    return ( 0 );			// no data in SSPBUF register
}
