In seeking some more details on the inner workings of the Wire library for the Arduino, I chanced across this rather informative link on the Arduino Playground website:
Arduino playground – WireLibraryDetailedReference
Of particular interest to me was the description how requestFrom worked. It doesn’t just issue the request: it calls the low level twi_readFrom() command to read the bytes requested from the I2C device. Thus, in the case that troubled me before, the bytes are guaranteed to be there.
Or are they? What if you ask for too many? The documentation says the I2C slave will NACK the read request. Well, what happens there? Let’s see what the code looks like…
[sourcecode lang=”cpp”]
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity)
{
// clamp to buffer length
if(quantity > BUFFER_LENGTH){
quantity = BUFFER_LENGTH;
}
// perform blocking read into buffer
uint8_t read = twi_readFrom(address, rxBuffer, quantity);
// set rx buffer iterator vars
rxBufferIndex = 0;
rxBufferLength = read;
return read;
}
[/sourcecode]
The twi_readFrom() call is from the underlying avr_libc library, which seems every bit as inscrutable. I haven’t dug deep enough to know for sure, but I suppose it is possible for twi_readFrom to return a value less than the number requested, or even zero in case of a NACK. In that case, the code that I was complaining about would still “work”, although it would call Wire.available() repeatedly (length times) to no avail, and leave the buffer empty.
It’s also good to note that the routine silently trims requests to match an internal buffer length. In theory, the AT24C1024 can write 256 bytes at a time, but the internal buffer lengths are set to 32.