I've been trying to understand how the AVR I2C and Wire library work. It appears to me that, if you send 100 bytes at 100 KHz, the processor will be sitting in the while() loop below doing not much of anything for 10-msec, while the ISR is repeated entered and exited automatically, etc. Yes, no, maybe?
For AVR in twi.c:
-----------------
uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait, uint8_t sendStop)
{
........
twi_state = TWI_MTX;
........
if (true == twi_inRepStart) {
twi_inRepStart = false;
........
}
else
// send start condition
TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE) | _BV(TWSTA); // enable INTs
// wait for write operation to complete
while(wait && (TWI_MTX == twi_state)){ <---[twi_state not cleared in ISR till all data sent]
continue;
}
..............
}
void twi_reply(uint8_t ack)
{
// transmit master read ready signal, with or without ack
if(ack){
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA);
}else{
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT);
}
}
ISR(TWI_vect)
{
....
// Master Transmitter
case TW_MT_SLA_ACK: // slave receiver acked address
case TW_MT_DATA_ACK: // slave receiver acked data
// if there is data to send, send it, otherwise stop
if(twi_masterBufferIndex < twi_masterBufferLength){
// copy data to output register and ack
TWDR = twi_masterBuffer[twi_masterBufferIndex++];
twi_reply(1); <---[setting TWINT here initiates data xfer]
}else{
if (twi_sendStop)
twi_stop();
else {
twi_inRepStart = true; // we're gonna send the START
// don't enable the interrupt. We'll generate the start, but we
// avoid handling the interrupt until we're in the next transaction,
// at the point where we would normally issue the start.
TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ;
twi_state = TWI_READY; <---- [getting to here ends the data xfer]
}
}
break;
....
}