/*◄■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ I2CM.c ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■►*/

// <editor-fold defaultstate="collapsed" desc="Title">
/*╔══════════════════════════════════════════════════════════════════════════╗*/
/*║                        © John William Darsow                             ║*/
/*║ Created on Tuesday, April 17, 2018                                       ║*/
/*║ Current Version Date: (see File Date)                                    ║*/
/*║                                                                          ║*/
/*║ Microchip PIC18F46K80 I²C Base Routines                                  ║*/
/*║                                                                          ║*/
/*║ Compiled using:     MPLAB X IDE v4.05 and XC8 v1.44                      ║*/
/*╚══════════════════════════════════════════════════════════════════════════╝*/
// </editor-fold>

/*═════════════════════════════════ INCLUDEs ═════════════════════════════════*/
#include "I2CM.h"

/*═══════════════════════════ FUNCTION  DEFINITIONS ══════════════════════════*/
// <editor-fold defaultstate="collapsed" desc="Functions Definitions">

/*═════════════════════════════════ I²C APIs ═════════════════════════════════*/

/* * * * * * * * * * * * *  Lower level I²C routines  * * * * * * * * * * * * */
// <editor-fold defaultstate="collapsed" desc="Lower level I²C routines">
/*───────────────────── Generate I²C Start Condition ─────────────────────────*/
void i2c_start(void)
{// A HIGH to LOW transition on the SDA line while SCL is HIGH
   SSPCON2bits.SEN = 1;                // Initiate Start condition
   while(SSPCON2bits.SEN);             // Wait till Start sequence is completed
   PIR1bits.SSPIF = 0;                 // Clear interrupt flag
}

/*──────────────────── Generate I²C ReStart Condition ────────────────────────*/
void i2c_reStart(void)
{// A HIGH to LOW transition on the SDA line while SCL is HIGH
   SSPCON2bits.RSEN = 1;               // Initiate ReStart condition
   while(SSPCON2bits.RSEN);            // Wait till ReStart sequence is completed
   PIR1bits.SSPIF = 0;                 // Clear interrupt flag
}

/*───────────────────── Generate I²C Stop Condition ──────────────────────────*/
void i2c_stop(void)
{// A LOW to HIGH transition on the SDA line while SCL is HIGH
   SSPCON2bits.PEN = 1;                // Call Peripherals Lib
   while(SSPCON2bits.PEN);             // Wait till Stop sequence is completed
   PIR1bits.SSPIF = 0;                 // Clear interrupt flag
}

/*────────────────────── Write byte to the I²C bus ───────────────────────────*/
Int8 i2c_byte_out(Byte data)
{
   PIR1bits.SSPIF = 0;                 // clear SSP interrupt bit
   SSPBUF = data;

   if(SSPCON1bits.WCOL)                // If write collision occurs,return -1
      return -1;
   else
   {
      while(!PIR1bits.SSPIF ||         // Interrupt Flag lo or any *EN bit hi
            (SSPCON2 & I2C_Idle));     // wait until write cycle is complete 
      if (SSPCON2bits.ACKSTAT)         // test for ACK condition received
         return (-2);                  // NACK - No Acknowledgment
	   else
      {
         return (0);                   // if WCOL bit is not set return non-negative #
      }
   }
}

/*──────────────────── Get Acknowledgment from Slave ──────────────not used───────────*/
bool i2c_GetAck(void)
{
   return SSPCON2bits.ACKSTAT;         // 
}

/*─────────────────────── Read byte from the I²C bus ─────────────────────────*/
Byte i2c_byte_in(void)
{
   PIR1bits.SSPIF = 0;                 // clear SSP interrupt bit
   SSPCON2bits.RCEN = 1;               // Initiate Read
   while (!PIR1bits.SSPIF);            // Wait for interrupt flag to go high indicating transmission is complete
   return (SSPBUF);                    // Data is now in the SSPBUF so return that value
}

/*───────────────────── Give Acknowledgment to Slave ─────────────────────────*/
void i2c_GiveAck(Byte anACK)
{
   SSPCON2bits.ACKDT=anACK;            // Load the Acknowledge Data Bit - nACK or NACK
   SSPCON2bits.ACKEN = 1;              // Initiate Acknowledge Read condition
}

/*─────────────────────────── Poll for ACK bit ───────────────────────────────*/
void i2c_PollAck(Byte AddrW)           // Bus Addr & R/nW=0 bit ( Use to see if chip there?what if not timeout timer)
{                                      // Since the device will not acknowledge during a write cycle,
                                       // this is be used to determine when the write cycle is complete.
   
   do
   {                                   // If the device is still busy with the write cycle, no nACK will be returned.                        
      i2c_start();                     // Generate Start Condition
      SSPBUF = AddrW;                  // Write the address
      while(SSPSTATbits.BF ||          // Interrupt Flag lo or any *EN bit hi
            (SSPCON2 & I2C_Idle));     // wait until write cycle is complete
   } while(SSPCON2bits.ACKSTAT);       // Loop and keep trying as long as the nACK bit is high
}                                      // If the write cycle is complete, the device will return the nACK

//Lower level I²C routines </editor-fold>

//Functions Definitions </editor-fold>

