I've noticed that the return byte from endTransmission always returns a non-zero value, even when the transmission appears to function properly.
Can anyone else confirm this?
//Service note: Wire.endTransmission(false) does not work as advertised. A STOP is always generated.
Wire.endTransmission();
//result = Wire.endTransmission();
// result always returns non-zero, even though everything seems to work. Strange.
//if (result != 0) {
// DBG_PRINT("xmitt result: ");
// DBG_PRINTLN(result);
//}
It looks like endTransmission returns the number of bytes sent from the transmit buffer, not an indication of success, as Wire - Arduino Reference suggests.
from \arduino-1.5.1r2\hardware\arduino\sam\system\libsam\source\twi.c :
uses the old? wire.endtransmission function to determine if there was success or an error and to hold/release the bus, but i have no idea how to change this.
Does anyone have a working I2C for arduino 1.51r2 and could send me the source files,please?
static inline bool TWI_WaitTransferComplete(Twi *_twi, uint32_t _timeout) {
while (!TWI_TransferComplete(_twi)) {
if (TWI_FailedAcknowledge(_twi))
return false;
if (--_timeout == 0)
return false;
}
return true;
}
might be broken too.
Please correct me... I think the act of reading the status register during TWI_TransferComplete() will reset the NACK flag in TWI_SR.
If that's really the case, then TWI_FailedAcknowledge() will never trip.
I've spun my own where I load TWI_SR into a holder to allow me to check for NACK and TXCOMP (both flags are set simultaneously by the MCU).
So, the upshot is that for 1.5.1r2 on the Due, you should stay well-away from endTransmission(), and code your own.
It seems the entire 'wire' is a bit hosed.
My current scheme:
//Service note: Wire.endTransmission(false) does not work as advertised. A STOP is always generated.
// not only that, but NACK's are ignored too.
//
//The Problem: A NACK (slave not found) error is only available after a STOP bit has been issued.
// Cannot detect a bad address until we complete the whole process.
//Worse: The NACK flag is reset everytime any part of the Status register is read by code.
TWI_StartWrite(WIRE_INTERFACE, i2c_addr, 0, 0, i2c_register);
Embiic_WaitByteSent();
i=0;
while (i < numOfBytes) {
TWI_WriteByte(WIRE_INTERFACE, params[i++]);
if (i < (numOfBytes - 1)) { //cannot check the i2c status register on the last transmit, need to
Embiic_WaitByteSent(); // preserve any flagged NACK's
}
}
TWI_Stop(WIRE_INTERFACE);
if (!Embiic_CheckTXCOMP()) { //look for TX Completion, and check the NACK flag.
Error_Code = 2110;
}
boolean Embiic_CheckTXCOMP() {
unsigned long start, now;
uint32_t sr, tw_nack, tw_txcomp;
tw_txcomp = 0;
start = micros();
while (tw_txcomp == 0) {
sr = WIRE_INTERFACE->TWI_SR;
now = micros();
if (now < start) { // handle overflow, at at the expense of a longer timeout
start = now;
now++;
} else {
now = now - start;
}
if (now > I2C_ACK_TIMEOUTuS){
DBG_PRINTLN("Embiic_CheckTXCOMP: Timeout.");
return false;
}
tw_nack = ((sr & TWI_SR_NACK) & TWI_SR_NACK);
if (tw_nack != 0) {
DBG_PRINTLN("Embiic_CheckTXCOMP: NACK. Natch.");
return false;
}
tw_txcomp = ((sr & TWI_SR_TXCOMP) & TWI_SR_TXCOMP);
}
return true;
}
I'm fiddling with the Wire.cpp code myself now, based on Chris' notes. One thing that stands out on top of everything else (and which doesn't appear to be specifically mentioned in these threads) is that sendStop is being ignored entirely right now... endTransmission() is effectively identical to endTransmission(sendStop) for all values of sendStop when it comes to the Due "sam" library.
That thread didn't match the particular search I did so it was missed (though I'd stumbled upon it before).
I'm looking at how to fix Wire.cpp itself (at least getting it back to the original functionality for the Due). If I learn anything useful I'll share it.