Beispiel #1
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 #2
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 #3
0
// Perform one step of the I2C FSM
static void i2c_step(void)
{
	switch(g_i2c_state)
	{
		// Idle states
		case I2C_IDLE: // Idle bus with SCL and SDA high
			break;
		case I2C_READY: // Bus ready for activity with SCL and SDA low
			break;

		// Start states
		case I2C_START:
			i2c_init(); // Sets SDA and SCL to 1
			g_i2c_state = I2C_START_2;
			break;
		case I2C_START_2:
			i2c_sda(0); // SDA falling while SCL 1 => Start bit
			g_i2c_state = I2C_START_3;
			break;
		case I2C_START_3:
			i2c_scl(0); // Now SDA and SCL are both 0, ready for bus activity
			g_i2c_state = I2C_READY;
			break;
		
		// Write states
		case I2C_WRITE:
			i2c_sda(g_i2c_to_write & (1 << g_i2c_bit)); // SDA reflects data bit
			g_i2c_state = I2C_WRITE_2;
			break;
		case I2C_WRITE_2:
			i2c_scl(1); // Toggle SCL high
			g_i2c_state = I2C_WRITE_3;
			break;
		case I2C_WRITE_3:
			i2c_scl(0); // Toggle SCL low
			if(g_i2c_bit == 0)
				g_i2c_state = I2C_WRITE_ACK_1;
			else
			{
				g_i2c_bit--;
				g_i2c_state = I2C_WRITE;
			}
			break;
		case I2C_WRITE_ACK_1:
			i2c_sda(1); // Release SDA to allow the slave to ACK or NACK
			g_i2c_state = I2C_WRITE_ACK_2;
			break;
		case I2C_WRITE_ACK_2:
			i2c_scl(1); // Toggle SCL high
			g_i2c_state = I2C_WRITE_ACK_3;
			break;
		case I2C_WRITE_ACK_3:
			if(i2c_sda_read()) // Read the acknowledgement bit
				g_i2c_state = I2C_WRITE_GOT_NACK;
			else
				g_i2c_state = I2C_WRITE_GOT_ACK;
			i2c_scl(0); // Toggle SCL low
			break;
		case I2C_WRITE_GOT_ACK:
			break;
		case I2C_WRITE_GOT_NACK:
			break;
		
		// Read states
		case I2C_READ:
			i2c_sda(1); // Release SDA to allow the slave to transmit data
			g_i2c_state = I2C_READ_2;
			break;
		case I2C_READ_2:
			i2c_scl(1); // Toggle SCL high
			g_i2c_state = I2C_READ_3;
			break;
		case I2C_READ_3:
			if(i2c_sda_read())
				g_i2c_read |= (1 << g_i2c_bit);
			i2c_scl(0); // Toggle SCL low
			if(g_i2c_bit == 0)
				g_i2c_state = I2C_READ_4;
			else
			{
				g_i2c_bit--;
				g_i2c_state = I2C_READ_2;
			}
			break;
		case I2C_READ_4:
			i2c_sda(0); // Reassert control over SDA again and pull it low for an ACK
			g_i2c_state = I2C_READ_ACK_1;
			break;
		case I2C_READ_ACK_1:
			i2c_scl(1); // Toggle SCL high
			g_i2c_state = I2C_READ_ACK_2;
			break;
		case I2C_READ_ACK_2:
			i2c_scl(0); // Toggle SCL low
			g_i2c_state = I2C_READ_ENDED;
			break;
		case I2C_READ_ENDED:
			break;
		
		// Stop states
		case I2C_STOP:
			i2c_sda(0);
			g_i2c_state = I2C_STOP_2;
			break;
		case I2C_STOP_2:
			i2c_scl(1);
			g_i2c_state = I2C_STOP_3;
			break;
		case I2C_STOP_3:
			i2c_sda(1);
			g_i2c_state = I2C_IDLE;
			break;
		
		// Default state
		default:
			break;
	}
}
Beispiel #4
0
//
// printStatus
// -----------
// Print information to the Serial port
// Used during developing and debugging.
// Call it with the Serial port as parameter:
//   myWire.printStatus(Serial);
// This function is not compatible with the Wire library.
// When this function is not called, it does not use any memory.
//
void SoftwareWire::printStatus( HardwareSerial& Ser)
{
  Ser.println(F("-------------------"));
  Ser.println(F("SoftwareWire Status"));
  Ser.println(F("-------------------"));
  Ser.print(F("  F_CPU = "));
  Ser.println(F_CPU);
  Ser.print(F("  sizeof(SoftwareWire) = "));
  Ser.println(sizeof(SoftwareWire));
  Ser.print(F("  _transmission status = "));
  Ser.println(_transmission);
  Ser.print(F("  _i2cdelay = "));
  Ser.print(_i2cdelay);
  if( _i2cdelay == 0)
    Ser.print(F(" (free running)"));
  Ser.println();
  Ser.print(F("  _pullups = "));
  Ser.print(_pullups);
  if( _pullups)
    Ser.print(F(" (enabled)"));
  Ser.println();
  Ser.print(F("  _timeout = "));
  Ser.print(_timeout);
  Ser.println(F(" ms"));

  Ser.print(F("  SOFTWAREWIRE_BUFSIZE = "));
  Ser.println(SOFTWAREWIRE_BUFSIZE);
  Ser.print(F("  rxBufPut = "));
  Ser.println(rxBufPut);
  Ser.print(F("  rxBufGet = "));
  Ser.println(rxBufGet);
  Ser.print(F("  available() = "));
  Ser.println(available());
  Ser.print(F("  rxBuf (hex) = "));
  for(int ii=0; ii<SOFTWAREWIRE_BUFSIZE; ii++)
  {
    if(rxBuf[ii] < 16)
      Ser.print(F("0"));
    Ser.print(rxBuf[ii],HEX);
    Ser.print(F(" "));
  }
  Ser.println();
  
  Ser.print(F("  _sdaPin = "));
  Ser.println(_sdaPin);
  Ser.print(F("  _sclPin = "));
  Ser.println(_sclPin);
  Ser.print(F("  _sdaBitMast = 0x"));
  Ser.println(_sdaBitMask, HEX);
  Ser.print(F("  _sclBitMast = 0x"));
  Ser.println(_sclBitMask, HEX);
  Ser.print(F("  _sdaPortReg = "));  
  Ser.println( (uint16_t) _sdaPortReg, HEX);
  Ser.print(F("  _sclPortReg = "));  
  Ser.println( (uint16_t) _sclPortReg, HEX);
  Ser.print(F("  _sdaDirReg = "));  
  Ser.println( (uint16_t) _sdaDirReg, HEX);
  Ser.print(F("  _sclDirReg = "));  
  Ser.println( (uint16_t) _sclDirReg, HEX);
  Ser.print(F("  _sdaPinReg = "));  
  Ser.println( (uint16_t) _sdaPinReg, HEX);
  Ser.print(F("  _sclPinReg = "));  
  Ser.println( (uint16_t) _sclPinReg, HEX);
  
  Ser.print(F("  line state sda = "));
  Ser.println(i2c_sda_read());
  Ser.print(F("  line state scl = "));
  Ser.println(i2c_scl_read());
  
#ifdef ENABLE_I2C_SCANNER
  // i2c_scanner
  // Taken from : http://playground.arduino.cc/Main/I2cScanner
  // At April 2015, it was version 5
  Ser.println("\n  I2C Scanner");
  byte error, address;
  int nDevices;

  Ser.println("  Scanning...");

  nDevices = 0;
  for(address=1; address<127; address++ ) 
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    beginTransmission(address);
    error = endTransmission();

    if (error == 0)
    {
      Ser.print("  I2C device found at address 0x");
      if (address<16) 
        Ser.print("0");
      Ser.print(address,HEX);
      Ser.println("  !");

      nDevices++;
    }
    else if (error==4) 
    {
      Ser.print("  Unknow error at address 0x");
      if (address<16) 
        Ser.print("0");
      Ser.println(address,HEX);
    }    
  }
  if (nDevices == 0)
    Ser.println("  No I2C devices found\n");
  else
    Ser.println("  done\n");
#endif    
}