Example #1
0
void event_i2c_abuse_test(void)
{
  if (i2c_idle(&I2C_ABUSE_PORT))
  {
    LED_ON(5);	// green = idle
    LED_OFF(4);
  }
  else
  {
    LED_ON(4); // red = busy
    LED_OFF(5);
  }

  // Wait for I2C transaction object to be released by the I2C driver before changing anything
  if ((i2c_abuse_test_counter < 12) && (i2c_abuse_test_counter > 3))
  {
	  if ((i2c_test2.status == I2CTransFailed) || (i2c_test2.status == I2CTransSuccess))
	  {
		  //i2c_test2.slave_addr = 0x90;
		  i2c_test2.type = I2CTransRx;
		  i2c_test2.slave_addr = 0x92;
		  i2c_test2.len_r = 2;
	    i2c_submit(&I2C_ABUSE_PORT,&i2c_test2);
	  }
  }


  if ((i2c_test1.status == I2CTransFailed) || (i2c_test1.status == I2CTransSuccess))
  {
	    if (i2c_abuse_test_counter < 16)
	    {
	       i2c_abuse_test_counter++;
	    }
	    else
	    {
		// wait until ready:
		if (i2c_idle(&I2C_ABUSE_PORT))
		{
			      i2c_abuse_test_counter = 1;

			      i2c_setbitrate(&I2C_ABUSE_PORT, i2c_abuse_test_bitrate);

			      i2c_abuse_test_bitrate += 17000;
			      if (i2c_abuse_test_bitrate > 410000)
			      {
				i2c_abuse_test_bitrate -= 410000;
			      }
			    }
		}

	    if (i2c_abuse_test_counter < 16)
	    {
	      RunOnceEvery(100,LED_TOGGLE(I2C_ABUSE_LED));
	      i2c_abuse_send_transaction( i2c_abuse_test_counter );
	    }
  }
}
void i2c_setbitrate(struct i2c_periph *periph, int bitrate)
{
  if (i2c_idle(periph))
  {
    if (periph == &i2c2)
    {
      I2C2_InitStruct.I2C_ClockSpeed = bitrate;
      I2C_Init(I2C2, i2c2.init_struct);
    }

#ifdef I2C_DEBUG_LED
        __disable_irq();

        LED2_ON();
        LED1_ON();
        LED2_OFF();
        LED1_OFF();
        LED2_ON();
        LED1_ON();
        LED2_OFF();
        LED1_OFF();

        __enable_irq();
#endif

   }
}
Example #3
0
void i2c_write(unsigned char data)
{
  // Send the Data to I2C Bus
  SSPBUF = data;
  if (SSPCON1bits.WCOL)         // Check for write collision
    return;

  while(SSPSTATbits.BF);        // Wait until write cycle is complete
  i2c_idle();                   // Ensure the I2C module is idle
}
Example #4
0
unsigned char i2c_read(void)
{
  // Ensure the I2C module is idle
  i2c_idle();

  // Enable Receive Mode
  SSPCON2bits.RCEN = 1;           // Enable master for 1 byte reception
  while(!SSPSTATbits.BF);         // Wait until buffer is full
  return(SSPBUF);
}
Example #5
0
void i2c_start(unsigned char stype)
{
  i2c_idle();                     // Ensure the I2C module is idle
  if (stype == I2C_START_CMD) {
    SSPCON2bits.SEN = 1;          // Start I2C Transmission
    while(SSPCON2bits.SEN);
  } else {
    SSPCON2bits.RSEN = 1;         // ReStart I2C Transmission
    while(SSPCON2bits.RSEN);
  }
}
Example #6
0
void baro_periodic(void)
{
  // check i2c_done
  if (!i2c_idle(&i2c2)) { return; }

  switch (baro_board.status) {
    case LBS_UNINITIALIZED:
      baro_board_send_reset();
      baro_board.status = LBS_RESETED;
      break;
    case LBS_RESETED:
      baro_board_send_config_abs();
      baro_board.status = LBS_INITIALIZING_ABS;
      break;
    case LBS_INITIALIZING_ABS:
      baro_board_set_current_register(BARO_ABS_ADDR, 0x00);
      baro_board.status = LBS_INITIALIZING_ABS_1;
      break;
    case LBS_INITIALIZING_ABS_1:
      baro_board_send_config_diff();
      baro_board.status = LBS_INITIALIZING_DIFF;
      break;
    case LBS_INITIALIZING_DIFF:
      baro_board_set_current_register(BARO_DIFF_ADDR, 0x00);
      baro_board.status = LBS_INITIALIZING_DIFF_1;
      //    baro_board.status = LBS_UNINITIALIZED;
      break;
    case LBS_INITIALIZING_DIFF_1:
      baro_board.running = true;
      /* Falls through. */
    case LBS_READ_DIFF:
      baro_board_read_from_current_register(BARO_ABS_ADDR);
      baro_board.status = LBS_READING_ABS;
      break;
    case LBS_READ_ABS:
      baro_board_read_from_current_register(BARO_DIFF_ADDR);
      baro_board.status = LBS_READING_DIFF;
      break;
    default:
      break;
  }

#ifdef BARO_LED
  if (baro_board.running == TRUE) {
    LED_ON(BARO_LED);
  } else {
    LED_TOGGLE(BARO_LED);
  }
#endif
}
Example #7
0
void baro_periodic(void) {
  
  // check i2c_done
  if (!i2c_idle(&i2c2)) return;

  switch (baro_board.status) {
  case LBS_UNINITIALIZED:
    baro_board_send_reset();
    baro_board.status = LBS_RESETED;

    break;
  case LBS_RESETED:
    baro_board_send_config_abs();
    baro_board.status = LBS_INITIALIZING_ABS;
    break;
  case LBS_INITIALIZING_ABS:
    baro_board_set_current_register(BARO_ABS_ADDR, 0x00);
    baro_board.status = LBS_INITIALIZING_ABS_1;
    break;
  case LBS_INITIALIZING_ABS_1:
    baro_board_send_config_diff();
    baro_board.status = LBS_INITIALIZING_DIFF;
    break;
  case LBS_INITIALIZING_DIFF:
    baro_board_set_current_register(BARO_DIFF_ADDR, 0x00);
    baro_board.status = LBS_INITIALIZING_DIFF_1;
    //    baro_board.status = LBS_UNINITIALIZED;
    break;
  case LBS_INITIALIZING_DIFF_1:
    baro.status = BS_RUNNING;
    
  case LBS_READ_DIFF:
    baro_board_read_from_current_register(BARO_ABS_ADDR);
    baro_board.status = LBS_READING_ABS;
    //LED_TOGGLE(6);
    break;
  case LBS_READ_ABS:
    baro_board_read_from_current_register(BARO_DIFF_ADDR);
    baro_board.status = LBS_READING_DIFF;
    LED_TOGGLE(6);
      					
    break;
  default:
    break;
  }

}
Example #8
0
void hmc5843_idle_task(void)
{
  if (hmc5843.i2c_trans.status == I2CTransFailed) {
    hmc5843.sent_tx = 0;
    hmc5843.sent_rx = 0;
  }

  if (hmc5843.i2c_trans.status == I2CTransRunning || hmc5843.i2c_trans.status == I2CTransPending) { return; }

  if (hmc5843.initialized && mag_eoc() && !hmc5843.sent_tx && !hmc5843.sent_rx) {
    if (HMC5843_I2C_DEV.status == I2CIdle && i2c_idle(&HMC5843_I2C_DEV)) {
      hmc5843.i2c_trans.type = I2CTransTx;
      hmc5843.i2c_trans.len_w = 1;
      hmc5843.i2c_trans.buf[0] = 0x3;
      i2c_submit(&HMC5843_I2C_DEV, &hmc5843.i2c_trans);
      hmc5843.sent_tx = 1;
      return;
    }
  }

  if (hmc5843.sent_tx) {
    hmc5843.i2c_trans.type = I2CTransRx;
    hmc5843.i2c_trans.len_r = 6;
    hmc5843.i2c_trans.len_w = 1;
    hmc5843.i2c_trans.buf[0] = 0x3;
    i2c_submit(&HMC5843_I2C_DEV, &hmc5843.i2c_trans);
    hmc5843.sent_rx = 1;
    hmc5843.sent_tx = 0;
    return;
  }

  if (hmc5843.sent_rx && hmc5843.i2c_trans.status == I2CTransSuccess) {
    hmc5843.sent_rx = 0;
    hmc5843.sent_tx = 0;
    hmc5843.timeout = 0;
    hmc5843.data_available = TRUE;
    memcpy(hmc5843.data.buf, (const void *) hmc5843.i2c_trans.buf, 6);
    for (int i = 0; i < 3; i++) {
      hmc5843.data.value[i] = bswap_16(hmc5843.data.value[i]);
    }
  }
}
Example #9
0
void hmc5843_idle_task(void)
{
    if (hmc5843.initialized && hmc5843.ready_for_read && (hmc5843.i2c_trans.status == I2CTransSuccess || hmc5843.i2c_trans.status == I2CTransFailed)) {
      if (i2c2.status == I2CIdle && i2c_idle(&i2c2)) {
        hmc5843.i2c_trans.type = I2CTransRx;
        hmc5843.i2c_trans.len_r = 7;
        i2c_submit(&i2c2, &hmc5843.i2c_trans);
        hmc5843.reading = TRUE;
        hmc5843.ready_for_read = FALSE;
      }
    }

    if (hmc5843.reading && hmc5843.i2c_trans.status == I2CTransSuccess) {
        hmc5843.timeout = 0;
        hmc5843.data_available = TRUE;
        hmc5843.reading = FALSE;
        memcpy(hmc5843.data.buf, (const void *) hmc5843.i2c_trans.buf, 6);
        for (int i = 0; i < 3; i++) {
            hmc5843.data.value[i] = bswap_16(hmc5843.data.value[i]);
        }
    }
}
Example #10
0
void baro_periodic(void) {
  // check that nothing is in progress
  if (baro_trans.status == I2CTransPending) return;
  if (baro_trans.status == I2CTransRunning) return;
  if (!i2c_idle(&i2c2)) return;

  switch (baro_board.status) {
  case LBS_UNINITIALIZED:
    baro_board_send_reset();
    baro_board.status = LBS_REQUEST;
    baro.status = BS_RUNNING;
    break;
  case LBS_REQUEST:
    bmp085_request_pressure();
    baro_board.status = LBS_READ;
    break;
  case LBS_READ:
    if (baro_eoc()) {
      bmp085_read_pressure();
      baro_board.status = LBS_READING;
    }
    break;
  case LBS_REQUEST_TEMP:
    bmp085_request_temp();
    baro_board.status = LBS_READ_TEMP;
    break;
  case LBS_READ_TEMP:
    if (baro_eoc()) {
      bmp085_read_temp();
      baro_board.status = LBS_READING_TEMP;
    }
    break;
  default:
    break;
  }

}
Example #11
0
void hmc5843_periodic(void)
{
  if (!hmc5843.initialized) {
    send_config();
    hmc5843.initialized = TRUE;
  } else if (hmc5843.timeout++ > HMC5843_TIMEOUT && HMC5843_I2C_DEV.status == I2CIdle && i2c_idle(&HMC5843_I2C_DEV)) {
#ifdef USE_HMC59843_ARCH_RESET
    hmc5843_arch_reset();
#endif
    hmc5843.i2c_trans.type = I2CTransTx;
    hmc5843.i2c_trans.len_w = 1;
    hmc5843.i2c_trans.buf[0] = 0x3;
    i2c_submit(&HMC5843_I2C_DEV, &hmc5843.i2c_trans);
    while (hmc5843.i2c_trans.status == I2CTransPending || hmc5843.i2c_trans.status == I2CTransRunning);

    hmc5843.i2c_trans.type = I2CTransRx;
    hmc5843.i2c_trans.len_r = 6;
    i2c_submit(&HMC5843_I2C_DEV, &hmc5843.i2c_trans);
    while (hmc5843.i2c_trans.status == I2CTransPending || hmc5843.i2c_trans.status == I2CTransRunning);
    hmc5843.timeout = 0;
  }

#ifdef HMC5843_NO_IRQ
  // < 50Hz
  fake_mag_eoc = 1;
#endif

}
Example #12
0
void i2c_setbitrate(struct i2c_periph *periph, int bitrate)
{
  // If NOT Busy
  if (i2c_idle(periph))
  {
    volatile int devider;
    volatile int risetime;

    uint32_t i2c = (uint32_t) periph->reg_addr;

    /*****************************************************
    Bitrate:

    -CR2 + CCR + TRISE registers
    -only change when PE=0

    e.g.

    10kHz:  36MHz + Standard 0x708 + 0x25
    70kHz:  36MHz + Standard 0x101 +
    400kHz: 36MHz + Fast 0x1E      + 0xb

    // 1) Program peripheral input clock CR2: to get correct timings
    // 2) Configure clock control registers
    // 3) Configure rise time register
    ******************************************************/

    if (bitrate < 3000)
      bitrate = 3000;

    // rcc_ppre1_frequency is normally configured to max: 36MHz on F1 and 42MHz on F4
    // in fast mode: 2counts low 1 count high -> / 3:
    // in standard mode: 1 count low, 1 count high -> /2:
    devider = (rcc_ppre1_frequency/2000) / (bitrate/1000);

    // never allow faster than 600kbps
    if (devider < 20)
      devider = 20;

    // no overflow either
    if (devider >=4095)
      devider = 4095;

    // risetime can be up to 1/6th of the period
    risetime = 1000000 / (bitrate/1000) / 6 / 28;

    if (risetime < 10)
      risetime = 10;

    // more will overflow the register: for more you should lower the FREQ
    if (risetime >=31)
      risetime = 31;

    // we do not expect an interrupt as the interface should have been idle, but just in case...
    __disable_irq(); // this code is in user space:

    // CCR can only be written when PE is disabled
    // p731 note 5
    i2c_peripheral_disable(i2c);

    // 1)
#ifdef STM32F1
    i2c_set_clock_frequency(i2c, I2C_CR2_FREQ_36MHZ);
#else // STM32F4
    i2c_set_clock_frequency(i2c, I2C_CR2_FREQ_42MHZ);
#endif
    // 2)
    //i2c_set_fast_mode(i2c);
    i2c_set_ccr(i2c, devider);
    // 3)
    i2c_set_trise(i2c, risetime);

    // Re-Enable
    i2c_peripheral_enable(i2c);

    __enable_irq();

#ifdef I2C_DEBUG_LED
    __disable_irq(); // this code is in user space:

    LED2_ON();
    LED1_ON();
    LED2_OFF();
    LED1_OFF();
    LED2_ON();
    LED1_ON();
    LED2_OFF();
    LED1_OFF();

    __enable_irq();
#endif

  }
}
Example #13
0
/*******************************************************************************
* PRIVATE FUNCTION: uc_i2c_write
*
* PARAMETERS:
* ~ uc_slave_address	- The I2C slave address.
* ~ uc_register_add	- The register address that we want to write.
* ~ uc_data			- The data that we want to write.
*
* RETURN:
* ~ void
*
* DESCRIPTIONS:
* This function will write a single byte of data using the I2C.
*
*******************************************************************************/
void uc_i2c_write(unsigned char uc_slave_address, unsigned char uc_register_add, unsigned char uc_data)
{
	// Clear the error flag before we start a new I2C operation.
	b_i2c_error_flag = 0;
	
	// Send start bit.	
	SSPCON2bits.SEN = 1;
	while (SSPCON2bits.SEN == 1);
	
	// Send slave address and indicate to write.
	SSPBUF = (uc_slave_address << 1) & 0xfe;
	
	// Wait for slave to acknowledge.
	//while (SSPSTATbits.R_W == 1);
	
	i2c_idle();	//wait for the message sending process complete
	
	// If slave does not acknowledge...
	if (SSPCON2bits.ACKSTAT == 1)
	{
		// Send stop bit.
		SSPCON2bits.PEN = 1;
		while (SSPCON2bits.PEN == 1);
		
		// Set the error flag and exit.
		b_i2c_error_flag = 1;
		return;
	}
	
	// Send the register address that we want to write.
	SSPBUF = uc_register_add;
	
	// Wait for slave to acknowledge.
	//while (SSPSTATbits.R_W == 1);
	
	i2c_idle();	//wait for the message sending process complete
	
	// If slave does not acknowledge...
	if (SSPCON2bits.ACKSTAT == 1) 
	{
		// Send stop bit.
		SSPCON2bits.PEN = 1;
		while (SSPCON2bits.PEN == 1);
		
		// Set the error flag and exit.
		b_i2c_error_flag = 1;
		return;
	}
	
	// Send the data.
	SSPBUF = uc_data;
	
	// Wait for slave to acknowledge.
	//while (SSPSTATbits.R_W == 1);
	
	i2c_idle();	//wait for the message sending process complete
	
	// If slave does not acknowledge...
	if (SSPCON2bits.ACKSTAT == 1) {
		// Send stop bit.
		SSPCON2bits.PEN = 1;
		while (SSPCON2bits.PEN == 1);
		
		// Set the error flag and exit.
		b_i2c_error_flag = 1;
		return;
	}
	
	// Send stop bit
	SSPCON2bits.PEN = 1;
	while (SSPCON2bits.PEN == 1);
	
	// Clear the error flag.
	b_i2c_error_flag = 0;
}
Example #14
0
void i2c_setbitrate(struct i2c_periph *periph, int bitrate)
{
  // If NOT Busy
  if (i2c_idle(periph))
  {
    volatile int devider;
    volatile int risetime;

    uint32_t i2c = (uint32_t) periph->reg_addr;

    /*****************************************************
    Bitrate:

    -CR2 + CCR + TRISE registers
    -only change when PE=0

    e.g.

    10kHz:  36MHz + Standard 0x708 + 0x25
    70kHz:  36MHz + Standard 0x101 +
    400kHz: 36MHz + Fast 0x1E      + 0xb

    // 1) Program peripheral input clock CR2: to get correct timings
    // 2) Configure clock control registers
    // 3) Configure rise time register
    ******************************************************/

    if (bitrate < 3000)
      bitrate = 3000;

    // 36MHz, fast scl: 2counts low 1 count high -> / 3:
    devider = 18000 / (bitrate/1000);

    // never allow faster than 600kbps
    if (devider < 20)
      devider = 20;

    // no overflow either
    if (devider >=4095)
      devider = 4095;

    // risetime can be up to 1/6th of the period
    risetime = 1000000 / (bitrate/1000) / 6 / 28;

    if (risetime < 10)
      risetime = 10;

    // more will overflow the register: for more you should lower the FREQ
    if (risetime >=31)
      risetime = 31;

    // we do not expect an interrupt as the interface should have been idle, but just in case...
    __disable_irq(); // this code is in user space:

    // CCR can only be written when PE is disabled
    // p731 note 5
    I2C_CR1(i2c) &= ~ I2C_CR1_PE;

    // 1)
    I2C_CR2(i2c) = 0x0324;
    // 2)
    //I2C_CCR(i2c) = 0x8000 + devider;
    I2C_CCR(i2c) = 0x0000 + devider;
    // 3)
    I2C_TRISE(i2c) = risetime;

    // Re-Enable
    I2C_CR1(i2c) |=   I2C_CR1_PE;

    __enable_irq();

#ifdef I2C_DEBUG_LED
    __disable_irq(); // this code is in user space:

    LED2_ON();
    LED1_ON();
    LED2_OFF();
    LED1_OFF();
    LED2_ON();
    LED1_ON();
    LED2_OFF();
    LED1_OFF();

    __enable_irq();
#endif

  }
}
void i2c_event(void)
{
  static uint32_t cnt = 0;
  //I2C_TypeDef *regs;
  cnt++;
  if (cnt > 10000) cnt = 0;

#ifndef I2C_DEBUG_LED
#ifdef USE_I2C1
  if (i2c1.status == I2CIdle)
  {
    if (i2c_idle(&i2c1))
    {
      __disable_irq();
      // More work to do
      if (i2c1.trans_extract_idx != i2c1.trans_insert_idx)
      {
        // Restart transaction doing the Rx part now
        PPRZ_I2C_SEND_START(&i2c1);
      }
      __enable_irq();
    }
  }
#endif
#endif

#ifdef USE_I2C2

#ifdef I2C_DEBUG_LED
  if (cnt == 0)
  {
        __disable_irq();

        LED2_ON();
        LED1_ON();
	LED1_OFF();
        LED1_ON();
	LED1_OFF();
        LED1_ON();
	LED1_OFF();
        LED1_ON();
	LED1_OFF();
        if (i2c2.status == I2CIdle)
        {
          LED1_ON();
   	  LED1_OFF();
        }
        else if (i2c2.status == I2CStartRequested)
        {
          LED1_ON();
   	  LED1_OFF();
          LED1_ON();
   	  LED1_OFF();

        }
	LED2_OFF();

        //regs = (I2C_TypeDef *) i2c2.reg_addr;
        //LED_SHOW_ACTIVE_BITS(regs);

        __enable_irq();
  }
#endif


  //if (i2c2.status == I2CIdle)
  {
    //if (i2c_idle(&i2c2))
    {
      //__disable_irq();
      // More work to do
      //if (i2c2.trans_extract_idx != i2c2.trans_insert_idx)
      {
        // Restart transaction doing the Rx part now
        //PPRZ_I2C_SEND_START(&i2c2);
      }
      //__enable_irq();
    }
  }
#endif
}
void main(void)
{
   const unsigned char *mas="\r\n---------------MASTER DEVICE-----------------\r\n";

   const unsigned char * arr1 = "\r\nTaking in the text \r\n";

   const unsigned char *arr2="\r\nEnter your choice \r\n 1.Slave 1(Address:0xAA\r\n2.Slave 2(Address:0xBB)\r\n3.Slave 3(Address:0xCC\r\n";

   const unsigned char *arr3= "You have entered:\r\n";

   const unsigned char *arr4= "\r\nUART Initialised\r\n";

   const unsigned char *arr5= "\r\nI2C initialised:\r\n";

   const unsigned char *msg1="\r\nSending to Slave 1 (Address 0xAA)\r\n";

   const unsigned char *msg2="\r\nSending to Slave 2 (Address 0xBB)\r\n";

   const unsigned char *msg3="\r\nSending to Slave 3 (Address 0xCC)\r\n";

   const unsigned char *msg4="\r\nAddress sent\r\n";

   const unsigned char *msg5="\r\nData sent\r\n";

    

   const unsigned char *err="\r\nNo message will be sent since no slave no entered\r\n";
     const unsigned char *fin="\r\nClosing Communication!\r\n";

   const unsigned char *msgm="\r\nYou have entered choice number:\r\n";

   unsigned char choice;

   OSCCONbits.IRCF = 0x07;  // Configure Internal OSC for 8MHz Clock

    while(!OSCCONbits.HTS);   // Wait Until Internal Osc is Stable

    INTCON=0;   // purpose of disabling the interrupts.

    UART_Init(baud_rate);

    UART_Write_Text(mas);

    UART_Write_Text(arr4);

    delay_ms(500);

    I2C_init();

    UART_Write_Text(arr5);
     //Initialisation done

    while(1)
    {
        UART_Write_Text(arr1);

        i2c_idle();

  //receive the characters until ENTER is pressed (ASCII for ENTER = 13)

         is=UART_Read_Text();

         UART_Write_Text(arr3);

         UART_Write_Text(is);

         UART_Write_Text(arr2);

         choice=UART_Read();

         UART_Write_Text(msgm);

         UART_Write(choice);

    switch(choice)
    {
        case 0x31:
        {
            UART_Write_Text(msg1);
            
            I2C_Start();

            if(I2C_address_send())//device address
           {   
           	delay_us(20);//clock settle and then send
                I2C_Write_Text(is);
           }
            
              else
                  break;
             I2C_Stop();
              break;
        }

        case 0x32:

          {
            UART_Write_Text(msg2);

            I2C_Start();

            if(I2C_address_send1())//device address
           {  
			 delay_us(20);//clock settle and then send
                 I2C_Write_Text(is);

             }

              else
                  break;
             I2C_Stop();
              break;
        }

       case 0x33:
           {
               UART_Write_Text(msg3);
               
               I2C_Start();
              
               if(I2C_address_send2())//device address
               {  
			 delay_us(20);//clock settle and then send
                 I2C_Write_Text(is);

               }
              else
                  break;
                I2C_Stop();

              break;
        }
        default:

            UART_Write_Text(err);
            break;
    }
    //Choice entered data sent respectively to slaves now stop
    //i2c_SendAcknowledge(I2C_LAST);
    PIR1bits.SSPIF = 0;

    
    UART_Write_Text(fin);

    }

}
Example #17
0
/*******************************************************************************
* PUBLIC FUNCTION: uc_i2c_read
*
* PARAMETERS:
* ~ uc_slave_address	- The I2C slave address.
* ~ uc_register			- The register that we want to read.
*
* RETURN:
* ~ The data that we read from the I2C.
*
* DESCRIPTIONS:
* This function will read a single byte of data using the I2C.
*
*******************************************************************************/
unsigned char uc_i2c_read(unsigned char uc_slave_address, unsigned char uc_register_add)
{
	// Buffer for the received byte.
	unsigned char uc_received_byte;
	unsigned long count = 10000;
	// Clear the error flag before we start a new I2C operation.
	b_i2c_error_flag = 0;
	
	// Send start bit.	
	SSPCON2bits.SEN = 1;
	while (SSPCON2bits.SEN == 1);
	
	// Send slave address and indicate to write.
	SSPBUF = (uc_slave_address << 1) & 0xfe;

	
	// Wait for slave to acknowledge.
	//while (SSPSTATbits.R_W == 1);	
	
	i2c_idle();	//wait for the message sending process complete
	
	// If slave does not acknowledge...
	if (SSPCON2bits.ACKSTAT == 1) {
		// Send stop bit.
		SSPCON2bits.PEN = 1;
		while (SSPCON2bits.PEN == 1);
		
		// Set the error flag and exit.
		b_i2c_error_flag = 1;
		return 0;
	}
	
	// Send the register address that we want to read and I2C will start transmitting out
	SSPBUF = uc_register_add;
	
	// Wait for slave to acknowledge.
	//while (SSPSTATbits.R_W == 1);
	
	i2c_idle();	//wait for the message sending process complete
	
	// If slave does not acknowledge...
	if (SSPCON2bits.ACKSTAT == 1) {
		// Send stop bit.
		SSPCON2bits.PEN = 1;
		while (SSPCON2bits.PEN == 1);
		
		// Set the error flag and exit.
		b_i2c_error_flag = 1;
		return 0;
	}	
	
	// Send repeated start bit.
	SSPCON2bits.RSEN = 1;
	while (SSPCON2bits.RSEN == 1);
	
	// Send slave address and indicate to read.
	SSPBUF = (uc_slave_address << 1) | 0x01;
	
	// Wait for slave to acknowledge.
	//while (SSPSTATbits.R_W == 1);
	
	i2c_idle();	//wait for the message sending process complete
	
	// If slave does not acknowledge...
	if (SSPCON2bits.ACKSTAT == 1) {
		// Send stop bit.
		SSPCON2bits.PEN = 1;
		while (SSPCON2bits.PEN == 1);
		
		// Set the error flag and exit.
		b_i2c_error_flag = 1;
		return 0;
	}
	
	// Enable receive.
	SSPCON2bits.RCEN = 1;
	
	// Wait until the data is received.
	while (SSPSTATbits.BF == 0) 
	{		
		// If timeout...
		if (--count == 0)
		{
			// Send stop bit.
			SSPCON2bits.PEN = 1;
			while (SSPCON2bits.PEN == 1);
			
			// Set the error flag and exit.
			b_i2c_error_flag = 1;
			return 0;
		}
	}
	
	// Read the received data.
	uc_received_byte = SSPBUF;
	
	// Send Not Acknowledge.
	SSPCON2bits.ACKDT = 1;
	SSPCON2bits.ACKEN = 1;
	while (SSPCON2bits.ACKEN == 1);
	
	// Send stop bit
	SSPCON2bits.PEN = 1;
	while (SSPCON2bits.PEN == 1);
	
	// Clear the error flag and return the received data.
	b_i2c_error_flag = 0;
	return uc_received_byte;
}