Ya, I think (in
wire.cpp):
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;
}
-Chris