I am writing a new library for the AVR Two Wire Interface. The Wire library is not very RTOS friendly.
The library is for master mode. I plan to write a separate slave mode library later.
This new library is designed to be used with various RTOSs and the calling thread will sleep while the I2C transfer occurs.
Is this API adequate for slave devices that may be used with Arduino?
The class API has three functions (detailed documentation follows later):
Public Member Functions
void begin (bool speed=I2C_400KHZ, bool pullups=I2C_NO_PULLUPS);
bool transfer (uint8_t addrRW, void *buf, size_t nbytes, uint8_t option=I2C_STOP);
bool transferContinue (void *buf, size_t nbytes, uint8_t option=I2C_STOP);
Here is an example for a DS1307 RTC chip that reads the DS1307 registers and prints the data and time.
#include <NilTwi.h>
// Two Wire Interface instance.
NilTwiMaster twi;
// DS1307 I2C address in high bits, R/W in low bit.
const uint8_t DS1307ADDR = 0XD0;
// DS1307 address and read bit.
const uint8_t RTC_READ = DS1307ADDR | I2C_READ;
// DS1307 address and write bit
const uint8_t RTC_WRITE = DS1307ADDR | I2C_WRITE;
//------------------------------------------------------------------------------
void setup() {
Serial.begin(9600);
// Use standard 100 kHz speed and no internal pullups.
twi.begin(I2C_100KHZ);
}
//------------------------------------------------------------------------------
void loop() {
uint8_t add = 0; // DS1307 time/date register address.
uint8_t buf[7]; // Buffer for DS1307 register values.
// Write DS1307 register address.
// Demo of option argument, repeat start is not required here.
twi.transfer(RTC_WRITE, &add, 1, I2C_REP_START);
// Read DS1307 time/date registers.
twi.transfer(RTC_READ, buf, 7);
// Print YYYY-MM-DD hh:mm:ss
Serial.print("20");
for (int i = 6; i >= 0; i--){
// Skip day of week.
if (i == 3) continue;
// Always print two digits
if (buf[i] < 10) Serial.print('0');
// Ds1307 is BCD.
Serial.print(buf[i], HEX);
// Print field separator.
if (i == 6 || i == 5) Serial.print('-');
if (i == 4) Serial.print(' ');
if (i == 2 || i == 1) Serial.print(':');
}
Serial.println();
delay(1000);
}
Here is more detailed documentation for the class members.
void TwiMaster::begin(bool speed = I2C_400KHZ, bool pullups = I2C_NO_PULLUPS)
Initialize the AVR 2-wire Serial Interface.
Parameters:
[in] speed I2C bus speed, one of:I2C_400KHZ
I2C_100KHZ[in] pullups State of internal AVR pullups, one of:
I2C_NO_PULLUPS
I2C_PULLUPSbool TwiMaster::transfer(uint8_t addrRW, void* buf,
size_t nbytes, uint8_t option = I2C_STOP)Start an I2C transfer with possible continuation.
Parameters:
[in] addrRW I2C slave address plus R/W bit.
[in,out] buf Source or destination data address for transfer.
[in] nbytes Number of bytes to transfer (may be zero).
[in] option Option for ending the transfer, one of:I2C_STOP end the transfer with an I2C stop condition.
I2C_REP_START end the transfer with an I2C repeat start condition.
I2C_CONTINUE allow additional transferContinue() calls.Returns:
true for success else false.bool TwiMaster::transferContinue(void* buf, size_t nbytes,
uint8_t option = I2C_STOP)Continue an I2C transfer.
Parameters:
[in,out] buf Source or destination data address for transfer.
[in] nbytes Number of bytes to transfer (may be zero).
[in] option Option for ending the transfer, one of:I2C_STOP end the transfer with an I2C stop condition.
I2C_REP_START end the transfer with an I2C repeat start condition.
I2C_CONTINUE allow additional transferContinue() calls.Returns:
true for success else false.