Beispiel #1
0
//
// Send a START Condition
//
// The SDA and SCL should already be high.
// 
// The SDA and SCL will both be low after this function.
// When writing the address, the Master makes them high.
// 
// Return value:
//   true  : software i2c bus is okay.
//   false : failed, some kind of hardware bus error.
//
boolean SoftwareWire::i2c_start(void)
{
  i2c_sda_hi();              // can perhaps be removed some day ? if the rest of the code is okay
  i2c_scl_hi();              // can perhaps be removed some day ? if the rest of the code is okay

  if (_i2cdelay != 0)
    delayMicroseconds(_i2cdelay);
    
  // Both the sda and scl should be high.
  // If not, there might be a hardware problem with the i2c bus signal lines.
  // This check was added to prevent that a shortcut of sda would be seen as a valid ACK
  // from a i2c Slave.
  uint8_t sda_status = i2c_sda_read();
  uint8_t scl_status = i2c_scl_read();
  if(sda_status == 0 || scl_status == 0)
  {
    return(false);
  }
  else
  {
    i2c_sda_lo();
    
    if (_i2cdelay != 0)
      delayMicroseconds(_i2cdelay);
  
    i2c_scl_lo();
    
    if (_i2cdelay != 0)
      delayMicroseconds(_i2cdelay);
  }
  return(true);
}
Beispiel #2
0
uint8_t SoftwareWire::i2c_readbit(void)
{
  i2c_sda_hi();            // 'hi' is the same as releasing the line
  i2c_scl_hi();

  // Check if clock stretching by the Slave should be detected.
  if( _stretch)
  {
    // Wait until the clock is high, the Slave could keep it low for clock stretching.
    unsigned long prevMillis = millis();
    while( i2c_scl_read() == 0)
    {
      if( millis() - prevMillis >= _timeout)
        break;
    };
  }

  // After the clock stretching, this delay has still be done before reading sda.
  if (_i2cdelay != 0)
    delayMicroseconds(_i2cdelay);
  
  uint8_t c = i2c_sda_read();
  
  i2c_scl_lo();

  if (_i2cdelay != 0)
    delayMicroseconds(_i2cdelay);

  return(c);
}
Beispiel #3
0
uint8_t SoftI2CMaster::i2c_readbit(void)
{
    i2c_sda_hi();
    i2c_scl_hi();
    _delay_us(i2cbitdelay);

    uint8_t port = digitalPinToPort(_sdaPin);
    volatile uint8_t* pinReg = portInputRegister(port);
    uint8_t c = *pinReg;  // I2C_PIN;

    i2c_scl_lo();
    _delay_us(i2cbitdelay);

    return ( c & _sdaBitMask) ? 1 : 0;
}
Beispiel #4
0
// Send a START Condition
//
void SoftI2CMaster::i2c_start(void)
{
    // set both to high at the same time
    //I2C_DDR &=~ (_BV( I2C_SDA ) | _BV( I2C_SCL ));
    //*_sclDirReg &=~ (_sdaBitMask | _sclBitMask);
    i2c_sda_hi();
    i2c_scl_hi();

    _delay_us(i2cbitdelay);
   
    i2c_sda_lo();
    _delay_us(i2cbitdelay);

    i2c_scl_lo();
    _delay_us(i2cbitdelay);
}
Beispiel #5
0
void SoftI2CMaster::i2c_writebit( uint8_t c )
{
    if ( c > 0 ) {
        i2c_sda_hi();
    } else {
        i2c_sda_lo();
    }

    i2c_scl_hi();
    _delay_us(i2cbitdelay);

    i2c_scl_lo();
    _delay_us(i2cbitdelay);

    if ( c > 0 ) {
        i2c_sda_lo();
    }
    _delay_us(i2cbitdelay);
}
Beispiel #6
0
void SoftI2CMaster::i2c_repstart(void)
{
    // set both to high at the same time (releases drive on both lines)
    //I2C_DDR &=~ (_BV( I2C_SDA ) | _BV( I2C_SCL ));
    //*_sclDirReg &=~ (_sdaBitMask | _sclBitMask);
    i2c_sda_hi();
    i2c_scl_hi();

    i2c_scl_lo();                           // force SCL low
    _delay_us(i2cbitdelay);

    i2c_sda_release();                      // release SDA
    _delay_us(i2cbitdelay);

    i2c_scl_release();                      // release SCL
    _delay_us(i2cbitdelay);

    i2c_sda_lo();                           // force SDA low
    _delay_us(i2cbitdelay);
}
Beispiel #7
0
//
// The i2c_writebit and i2c_readbit could be make "inline", but that
// didn't increase the speed, and the code size increases.
//
// The sda is low after the start condition.
// Therefor the sda is low for the first bit.
//
void SoftwareWire::i2c_writebit(uint8_t c)
{
  if(c==0)
  {
    i2c_sda_lo();
  }
  else
  {
    i2c_sda_hi();
  }
  
  if (_i2cdelay != 0)               // This delay is not needed, but it makes it safer
    delayMicroseconds(_i2cdelay);   // This delay is not needed, but it makes it safer
  
  i2c_scl_hi();                     // clock high: the Slave will read the sda signal
  
  // Check if clock stretching by the Slave should be detected.
  if( _stretch)
  {
    // If the Slave was strechting the clock pulse, the clock would not go high immediately.
    // For example if the Slave is an Arduino, that has other interrupts running (for example Serial data).
    unsigned long prevMillis = millis();
    while( i2c_scl_read() == 0)
    {
      if( millis() - prevMillis >= _timeout)
        break;
    };
  }

  // After the clock stretching, the clock must be high for the normal duration.
  // That is why this delay has still to be done.
  if (_i2cdelay != 0)
    delayMicroseconds(_i2cdelay);

  i2c_scl_lo();
  
  if (_i2cdelay != 0)
    delayMicroseconds(_i2cdelay);
}
Beispiel #8
0
//
// Repeated START instead of a STOP
// 
// TODO: check if the repeated start actually works.
//
void SoftwareWire::i2c_repstart(void)
{
  i2c_sda_hi();
//  i2c_scl_hi();               // ??????

  i2c_scl_lo();                         // force SCL low
  
  if (_i2cdelay != 0)
    delayMicroseconds(_i2cdelay);

  i2c_sda_hi();                        // release SDA
  
  if (_i2cdelay != 0)
    delayMicroseconds(_i2cdelay);

  i2c_scl_hi();                        // release SCL
  
  // Check if clock stretching by the Slave should be detected.
  if( _stretch)
  {
    // If the Slave was strechting the clock pulse, the clock would not go high immediately.
    // For example if the Slave is an Arduino, that has other interrupts running (for example Serial data).
    unsigned long prevMillis = millis();
    while( i2c_scl_read() == 0)
    {
      if( millis() - prevMillis >= _timeout)
        break;
    };
  }
  
  if (_i2cdelay != 0)
    delayMicroseconds(_i2cdelay);

  i2c_sda_lo();                        // force SDA low
  
  if (_i2cdelay != 0)
    delayMicroseconds(_i2cdelay);
}