/**
 * @brief  Writes one byte to the LSM303DLHC.
 * @param  DeviceAddr : specifies the slave address to be programmed.
 * @param  RegAddr : specifies the LSM303DLHC register to be written.
 * @param  pBuffer : pointer to the buffer  containing the data to be written to the LSM303DLH.
 * @retval LSM303DLHC Status
 */
uint16_t LSM303DLHC_Write(uint8_t DeviceAddr, uint8_t RegAddr, uint8_t* pBuffer) {
	/* Test on BUSY Flag */
	LSM303DLHC_Timeout = LSM303DLHC_LONG_TIMEOUT;
	while (I2C_GetFlagStatus(LSM303DLHC_I2C, I2C_ISR_BUSY ) != RESET) {
		if ((LSM303DLHC_Timeout--) == 0)
			return LSM303DLHC_TIMEOUT_UserCallback();
	}

	/* Configure slave address, nbytes, reload, end mode and start or stop generation */
	I2C_TransferHandling(LSM303DLHC_I2C, DeviceAddr, 1, I2C_Reload_Mode,
			I2C_Generate_Start_Write);

	/* Wait until TXIS flag is set */
	LSM303DLHC_Timeout = LSM303DLHC_LONG_TIMEOUT;
	while (I2C_GetFlagStatus(LSM303DLHC_I2C, I2C_ISR_TXIS ) == RESET) {
		if ((LSM303DLHC_Timeout--) == 0)
			return LSM303DLHC_TIMEOUT_UserCallback();
	}

	/* Send Register address */
	I2C_SendData(LSM303DLHC_I2C, (uint8_t) RegAddr);

	/* Wait until TCR flag is set */
	LSM303DLHC_Timeout = LSM303DLHC_LONG_TIMEOUT;
	while (I2C_GetFlagStatus(LSM303DLHC_I2C, I2C_ISR_TCR ) == RESET) {
		if ((LSM303DLHC_Timeout--) == 0)
			return LSM303DLHC_TIMEOUT_UserCallback();
	}

	/* Configure slave address, nbytes, reload, end mode and start or stop generation */
	I2C_TransferHandling(LSM303DLHC_I2C, DeviceAddr, 1, I2C_AutoEnd_Mode,
			I2C_No_StartStop);

	/* Wait until TXIS flag is set */
	LSM303DLHC_Timeout = LSM303DLHC_LONG_TIMEOUT;
	while (I2C_GetFlagStatus(LSM303DLHC_I2C, I2C_ISR_TXIS ) == RESET) {
		if ((LSM303DLHC_Timeout--) == 0)
			return LSM303DLHC_TIMEOUT_UserCallback();
	}

	/* Write data to TXDR */
	I2C_SendData(LSM303DLHC_I2C, *pBuffer);

	/* Wait until STOPF flag is set */
	LSM303DLHC_Timeout = LSM303DLHC_LONG_TIMEOUT;
	while (I2C_GetFlagStatus(LSM303DLHC_I2C, I2C_ISR_STOPF ) == RESET) {
		if ((LSM303DLHC_Timeout--) == 0)
			return LSM303DLHC_TIMEOUT_UserCallback();
	}

	/* Clear STOPF flag */
	I2C_ClearFlag(LSM303DLHC_I2C, I2C_ICR_STOPCF );

	return LSM303DLHC_OK ;
}
/**
  * @brief  Reads a block of data from the LSM303DLHC.
  * @param  DeviceAddr : specifies the slave address to be programmed(ACC_I2C_ADDRESS or MAG_I2C_ADDRESS).
  * @param  RegAddr : specifies the LSM303DLHC internal address register to read from.
  * @param  pBuffer : pointer to the buffer that receives the data read from the LSM303DLH.
  * @param  NumByteToRead : number of bytes to read from the LSM303DLH ( NumByteToRead >1  only for the Mgnetometer readinf).
  * @retval LSM303DLHC register value
  */
uint16_t LSM303DLHC_Read(uint8_t DeviceAddr, uint8_t RegAddr, uint8_t* pBuffer, uint16_t NumByteToRead)
{    
  /* Test on BUSY Flag */
  LSM303DLHC_Timeout = LSM303DLHC_LONG_TIMEOUT;
  while(I2C_GetFlagStatus(LSM303DLHC_I2C, I2C_ISR_BUSY) != RESET)
  {
    if((LSM303DLHC_Timeout--) == 0) return LSM303DLHC_TIMEOUT_UserCallback();
  }
  
  /* Configure slave address, nbytes, reload, end mode and start or stop generation */
  I2C_TransferHandling(LSM303DLHC_I2C, DeviceAddr, 1, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
  
  /* Wait until TXIS flag is set */
  LSM303DLHC_Timeout = LSM303DLHC_LONG_TIMEOUT;
  while(I2C_GetFlagStatus(LSM303DLHC_I2C, I2C_ISR_TXIS) == RESET)
  {
    if((LSM303DLHC_Timeout--) == 0) return LSM303DLHC_TIMEOUT_UserCallback();
  }
  
  if(NumByteToRead>1)
      RegAddr |= 0x80;

  
  /* Send Register address */
  I2C_SendData(LSM303DLHC_I2C, (uint8_t)RegAddr);
  
  /* Wait until TC flag is set */
  LSM303DLHC_Timeout = LSM303DLHC_LONG_TIMEOUT;
  while(I2C_GetFlagStatus(LSM303DLHC_I2C, I2C_ISR_TC) == RESET)
  {
    if((LSM303DLHC_Timeout--) == 0) return LSM303DLHC_TIMEOUT_UserCallback();
  }  
  
  /* Configure slave address, nbytes, reload, end mode and start or stop generation */
  I2C_TransferHandling(LSM303DLHC_I2C, DeviceAddr, NumByteToRead, I2C_AutoEnd_Mode, I2C_Generate_Start_Read);
  
  /* Wait until all data are received */
  while (NumByteToRead)
  {   
    /* Wait until RXNE flag is set */
    LSM303DLHC_Timeout = LSM303DLHC_LONG_TIMEOUT;
    while(I2C_GetFlagStatus(LSM303DLHC_I2C, I2C_ISR_RXNE) == RESET)    
    {
      if((LSM303DLHC_Timeout--) == 0) return LSM303DLHC_TIMEOUT_UserCallback();
    }
    
    /* Read data from RXDR */
    *pBuffer = I2C_ReceiveData(LSM303DLHC_I2C);
    /* Point to the next location where the byte read will be saved */
    pBuffer++;
    
    /* Decrement the read bytes counter */
    NumByteToRead--;
  } 
  
  /* Wait until STOPF flag is set */
  LSM303DLHC_Timeout = LSM303DLHC_LONG_TIMEOUT;
  while(I2C_GetFlagStatus(LSM303DLHC_I2C, I2C_ISR_STOPF) == RESET)   
  {
    if((LSM303DLHC_Timeout--) == 0) return LSM303DLHC_TIMEOUT_UserCallback();
  }
  
  /* Clear STOPF flag */
  I2C_ClearFlag(LSM303DLHC_I2C, I2C_ICR_STOPCF);
  
  /* If all operations OK */
  return LSM303DLHC_OK;  
}