text: /*
   * I2C_Master_H_file.h
   * http://www.electronicwings.com
   *
   */ 
  
  
  #ifndef I2C_MASTER_H_FILE_H_                    /* Define library H file if not defined */
  #define I2C_MASTER_H_FILE_H_
  
  #define F_CPU 8000000UL                         /* Define CPU clock Frequency e.g. here its 8MHz */
  #include <avr/io.h>                             /* Include AVR std. library file */
  #include <util/delay.h>                         /* Include delay header file */
  #include <math.h>                               /* Include math function */
  #define SCL_CLK 100000L                         /* Define SCL clock frequency */
  #define BITRATE(TWSR)   ((F_CPU/SCL_CLK)-16)/(2*pow(4,(TWSR&((1<<TWPS0)|(1<<TWPS1))))) /* Define bit rate */
  
  void I2C_Init();                                /* I2C initialize function */
  uint8_t  I2C_Start(char);                       /* I2C start function */
  uint8_t  I2C_Repeated_Start(char);              /* I2C repeated start function */
  void I2C_Stop();                                /* I2C stop function */
  void I2C_Start_Wait(char);                      /* I2C start wait function */
  uint8_t  I2C_Write(char);                       /* I2C write function */
  char I2C_Read_Ack();                            /* I2C read ack function */
  char I2C_Read_Nack();                           /* I2C read nack function */
  
  
  #endif                                          /* I2C_MASTER_H_FILE_H_ */
  
  void I2C_Init()                                             /* I2C initialize function */
  {
      TWBR = BITRATE(TWSR = 0x00);                            /* Get bit rate register value by formula */
  }   
  
  uint8_t I2C_Start(char slave_write_address)                     /* I2C start function */
  {
      uint8_t status;                                         /* Declare variable */
      TWCR = (1<<TWSTA)|(1<<TWEN)|(1<<TWINT);                 /* Enable TWI, generate start condition and clear interrupt flag */
      while (!(TWCR & (1<<TWINT)));                           /* Wait until TWI finish its current job (start condition) */
      status = TWSR & 0xF8;                                   /* Read TWI status register with masking lower three bits */
      if (status != 0x08)                                     /* Check weather start condition transmitted successfully or not? */
      return 0;                                               /* If not then return 0 to indicate start condition fail */
      TWDR = slave_write_address;                             /* If yes then write SLA+W in TWI data register */
      TWCR = (1<<TWEN)|(1<<TWINT);                            /* Enable TWI and clear interrupt flag */
      while (!(TWCR & (1<<TWINT)));                           /* Wait until TWI finish its current job (Write operation) */
      status = TWSR & 0xF8;                                   /* Read TWI status register with masking lower three bits */    
      if (status == 0x18)                                     /* Check weather SLA+W transmitted & ack received or not? */
      return 1;                                               /* If yes then return 1 to indicate ack received i.e. ready to accept data byte */
      if (status == 0x20)                                     /* Check weather SLA+W transmitted & nack received or not? */
      return 2;                                               /* If yes then return 2 to indicate nack received i.e. device is busy */
      else
      return 3;                                               /* Else return 3 to indicate SLA+W failed */
  }
  
  uint8_t I2C_Repeated_Start(char slave_read_address)         /* I2C repeated start function */
  {
      uint8_t status;                                         /* Declare variable */
      TWCR = (1<<TWSTA)|(1<<TWEN)|(1<<TWINT);                 /* Enable TWI, generate start condition and clear interrupt flag */
      while (!(TWCR & (1<<TWINT)));                           /* Wait until TWI finish its current job (start condition) */
      status = TWSR & 0xF8;                                   /* Read TWI status register with masking lower three bits */
      if (status != 0x10)                                     /* Check weather repeated start condition transmitted successfully or not? */
      return 0;                                               /* If no then return 0 to indicate repeated start condition fail */
      TWDR = slave_read_address;                              /* If yes then write SLA+R in TWI data register */
      TWCR = (1<<TWEN)|(1<<TWINT);                            /* Enable TWI and clear interrupt flag */
      while (!(TWCR & (1<<TWINT)));                           /* Wait until TWI finish its current job (Write operation) */
      status = TWSR & 0xF8;                                   /* Read TWI status register with masking lower three bits */
      if (status == 0x40)                                     /* Check weather SLA+R transmitted & ack received or not? */
      return 1;                                               /* If yes then return 1 to indicate ack received */ 
      if (status == 0x20)                                     /* Check weather SLA+R transmitted & nack received or not? */
      return 2;                                               /* If yes then return 2 to indicate nack received i.e. device is busy */
      else
      return 3;                                               /* Else return 3 to indicate SLA+W failed */
  }
  
  void I2C_Stop()                                             /* I2C stop function */
  {
      TWCR=(1<<TWSTO)|(1<<TWINT)|(1<<TWEN);                   /* Enable TWI, generate stop condition and clear interrupt flag */
      while(TWCR & (1<<TWSTO));                               /* Wait until stop condition execution */ 
  }
  
  void I2C_Start_Wait(char slave_write_address)               /* I2C start wait function */
  {
      uint8_t status;                                         /* Declare variable */
      while (1)
      {
          TWCR = (1<<TWSTA)|(1<<TWEN)|(1<<TWINT);             /* Enable TWI, generate start condition and clear interrupt flag */
          while (!(TWCR & (1<<TWINT)));                       /* Wait until TWI finish its current job (start condition) */
          status = TWSR & 0xF8;                               /* Read TWI status register with masking lower three bits */
          if (status != 0x08)                                 /* Check weather start condition transmitted successfully or not? */
          continue;                                           /* If no then continue with start loop again */
          TWDR = slave_write_address;                         /* If yes then write SLA+W in TWI data register */
          TWCR = (1<<TWEN)|(1<<TWINT);                        /* Enable TWI and clear interrupt flag */
          while (!(TWCR & (1<<TWINT)));                       /* Wait until TWI finish its current job (Write operation) */
          status = TWSR & 0xF8;                               /* Read TWI status register with masking lower three bits */
          if (status != 0x18 )                                /* Check weather SLA+W transmitted & ack received or not? */
          {
              I2C_Stop();                                     /* If not then generate stop condition */
              continue;                                       /* continue with start loop again */
          }
          break;                                              /* If yes then break loop */
      }
  }
  
  uint8_t I2C_Write(char data)                                /* I2C write function */
  {
      uint8_t status;                                         /* Declare variable */
      TWDR = data;                                            /* Copy data in TWI data register */
      TWCR = (1<<TWEN)|(1<<TWINT);                            /* Enable TWI and clear interrupt flag */
      while (!(TWCR & (1<<TWINT)));                           /* Wait until TWI finish its current job (Write operation) */
      status = TWSR & 0xF8;                                   /* Read TWI status register with masking lower three bits */
      if (status == 0x28)                                     /* Check weather data transmitted & ack received or not? */
      return 0;                                               /* If yes then return 0 to indicate ack received */
      if (status == 0x30)                                     /* Check weather data transmitted & nack received or not? */
      return 1;                                               /* If yes then return 1 to indicate nack received */
      else
      return 2;                                               /* Else return 2 to indicate data transmission failed */
  }
  
  char I2C_Read_Ack()                                     /* I2C read ack function */
  {
      TWCR=(1<<TWEN)|(1<<TWINT)|(1<<TWEA);                    /* Enable TWI, generation of ack and clear interrupt flag */
      while (!(TWCR & (1<<TWINT)));                           /* Wait until TWI finish its current job (read operation) */
      return TWDR;                                            /* Return received data */
  }   
  
  char I2C_Read_Nack()                                        /* I2C read nack function */
  {
      TWCR=(1<<TWEN)|(1<<TWINT);                              /* Enable TWI and clear interrupt flag */
      while (!(TWCR & (1<<TWINT)));                           /* Wait until TWI finish its current job (read operation) */
      return TWDR;                                            /* Return received data */
  }   
  