Let me try to handle some of your comments.
1 .. length to long for buffer
This can't happen since I don't copy the data to/from an internal buffer. I just setup the address and count in static variables and the ISR moves data directly to/from the user's buffer.
- 2 .. address send, NACK received
- 3 .. data send, NACK received
- 4 .. other twi error (lost bus arbitration, bus error, ..)
The ISR saves the TWI state on entrance so the you can get the initial and current state of the bus. Here are the possible codes:
// General TWI Master state codes
#define TWI_START 0x08 // START has been transmitted
#define TWI_REP_START 0x10 // Repeated START has been transmitted
#define TWI_ARB_LOST 0x38 // Arbitration lost// TWI Master Transmitter state codes
#define TWI_MTX_ADR_ACK 0x18 // SLA+W has been transmitted and ACK received
#define TWI_MTX_ADR_NACK 0x20 // SLA+W has been transmitted and NACK received
#define TWI_MTX_DATA_ACK 0x28 // Data byte has been transmitted and ACK received
#define TWI_MTX_DATA_NACK 0x30 // Data byte has been transmitted and NACK received// TWI Master Receiver state codes
#define TWI_MRX_ADR_ACK 0x40 // SLA+R has been transmitted and ACK received
#define TWI_MRX_ADR_NACK 0x48 // SLA+R has been transmitted and NACK received
#define TWI_MRX_DATA_ACK 0x50 // Data byte has been received and ACK transmitted
#define TWI_MRX_DATA_NACK 0x58 // Data byte has been received and NACK transmitted// TWI Miscellaneous state codes
#define TWI_NO_STATE 0xF8 // No relevant state information available; TWINT = “0”
#define TWI_BUS_ERROR 0x00 // Bus error due to an illegal START or STOP condition
For example if you call transferContinue() and it fails you can check the bus state.
idea:
to solve address issues it might be useful to have a I2C scanner equivalent in the core of the new lib? (master only?)
I am not sure exactly what you mean but the main reason that transfer() will allows zero length is to probe the bus.
On my DS1307 test setup this sketch:
#include <NilTwi.h>
// Two Wire Interface instance.
NilTwiMaster twi;
void setup() {
Serial.begin(9600);
twi.begin();
uint8_t add = 0;
// try read
do {
if (twi.transfer(add | I2C_READ, 0, 0)) {
Serial.print("Add read: 0X");
Serial.println(add, HEX);
}
add += 2;
}
while (add);
// try write
add = 0;
do {
if (twi.transfer(add | I2C_WRITE, 0, 0)) {
Serial.print("Add write: 0X");
Serial.println(add, HEX);
}
add += 2;
}
while (add);
Serial.println("Done");
}
void loop() {
}
Prints this:
Add read: 0XD0
Add write: 0XD0
Done
Some getter functions? have no direct use for them, but makes it complete
bool getPullUps();
int getSPeed();
Unfortunately I set the pull-ups and baud rate in begin() but don't save it. I guess I could.
Question pops up?
How would the new lib communicate with an I2C EEPROM? (esp eeprom address handling, page boundaries ...)
The user has total control of the transfer size. I don't have internal buffers.
You could send all day without a stop or repeat start by calling transferContinue(). There might be a time gap.
I didn't demo transferContinue() in my example. Here is a DS1307 write function:
bool rtcWrite(uint8_t regAdd, uint8_t* buf, uint8_t count) {
// Set place to write in DS1307 and don't end transfer.
if (!twi.transfer(RTC_WRITE, ®Add, 1, I2C_CONTINUE)) return false;
// Write DS1307 registers or memory. Default is to end with a stop condition.
return twi.transferContinue(buf, count);
}