#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <xc.h>

#include "HardwareProfile.h"
#include "i2c1.h"
#include "timer.h"

#ifndef FCY
#define FCY _XTAL_FREQ/2
#endif



unsigned short i2c1_init(void)
{
    int temp;
 /*   if(!I2C1CONbits.I2CEN)
    {
        // initialize the hardware
        // STAT Setting 
        I2C1STAT = 0x0;
  
        // Baud Rate Generator Value: I2CBRG 100000;   
        I2C1BRG = 33;
        //I2C1BRG = 19;
        //I2C1BRG = 9;
        msWait(10);
        
        // CON Setting
        I2C1CON = 0x8000;
        //I2C1CONbits.I2CEN = 1;

        return (1);
    }
    else
        return (0); */
    
       

   // I2CBRG = 194 for 10Mhz OSCI with PPL with 100kHz I2C clock
   I2C1BRG = 33;
   I2C1CONbits.I2CEN = 0;  // Disable I2C Mode
   I2C1CONbits.DISSLW = 1; // Disable slew rate control
   IFS1bits.MI2C1IF = 0;    // Clear Interrupt
   I2C1CONbits.I2CEN = 1;  // Enable I2C Mode
   temp = I2C1RCV;    // read buffer to clear buffer full
   reset_i2c1_bus();// set bus to idle
   return(0);
}

//Resets the I2C bus to Idle
void reset_i2c1_bus(void)
{
   int x = 0;

   //initiate stop bit
   I2C1CONbits.PEN = 1;

   //wait for hardware clear of stop bit
   while (I2C1CONbits.PEN)
   {
      usWait(1);
      x ++;
      if (x > 20) break;
   }
   I2C1CONbits.RCEN = 0;
   IFS1bits.MI2C1IF = 0; // Clear Interrupt
   I2C1STATbits.IWCOL = 0;
   I2C1STATbits.BCL = 0;
   usWait(10);
}

void i2c1_start(void)
{
    I2C1CONbits.SEN = 1;
}

void i2c1_stop(void)
{
    //initiate stop bit
    I2C1CONbits.PEN = 1;
}

unsigned short i2c1_wait_for_ACK(unsigned short us)
{
    unsigned short i = 0;
    
    while (i < us)
    {   
        usWait(1);
        if (!I2C1STATbits.ACKSTAT)return(0);
        i++;
    }
    return(1);
}

void i2c1_sendACK(void)
{
    //I2C1CONbits.ACKDT = 0;
    I2C1CONbits.ACKEN = 1; // start the ACK/NACK
}

void i2c1_TXData(uint8_t d)
{
   int i;

   while (I2C1STATbits.TBF) { }
   IFS1bits.MI2C1IF = 0; // Clear Interrupt
   I2C1TRN = d; // load the outgoing data byte

   // wait for transmission
   for (i=0; i<500; i++)
   {
      if (!I2C1STATbits.TRSTAT) {break;}
      usWait(1);
      if (i == 500) {return;}
   }

   // Check for NO_ACK from slave, abort if not found
   if (I2C1STATbits.ACKSTAT == 1)
   {
      reset_i2c1_bus();
      return;
   }
   usWait(10);
   return;
}

unsigned short i2c1_RXData(void)
{
    return I2C1RCV;
}

void i2c1_restart(void)
{
   int x = 0;

   I2C1CONbits.RSEN = 1;   //Initiate restart condition
   Nop();

   //the hardware will automatically clear restart bit
   //wait for automatic clear before proceding
   while (I2C1CONbits.RSEN)
   {
      usWait(1);
      x++;
      if (x > 20) break;
   }

   usWait(2);
}