TWI as Slave Write Issue

I'm not sure what the main intention of using write during a twi request in the onReuqest function is, but if I do several writes, only the data of the last write is send to the master.

Example:

char buf[4];
...
void requestEvent()
{
  Wire.write(0xFE);  // skipped
  Wire.write(0x32);  // skipped
  Wire.write(buf, sizeof(buf));  // only this will be send
}

If you look in the source code of the wire/twi library you find that write calls twi_transmit(data, size).
A close up view at this function shows the problem:

uint8_t twi_transmit(const uint8_t* data, uint8_t length)
{
  uint8_t i;

  // ensure data will fit into buffer
  if(TWI_BUFFER_LENGTH < length){
    return 1;
  }
  
  // ensure we are currently a slave transmitter
  if(TWI_STX != twi_state){
    return 2;
  }
  
  // set length and copy data into tx buffer
  twi_txBufferLength = length;
  for(i = 0; i < length; ++i){
    twi_txBuffer[i] = data[i];
  }
  
  return 0;
}

-> The function overwrites every call the transmit buffer (standard length 32Bytes).
Maybe it will be better to change the function to append data to the buffer which submitted by write.
I think there shouldn't be any errors, because the TransmitIndex and TransmitLen is reseted before the event call.

I change the function to the following and it seems to work fine:

uint8_t twi_transmit(const uint8_t* data, uint8_t length)
{
  uint8_t i, t;

  // ensure data will fit into buffer
  if(TWI_BUFFER_LENGTH < twi_txBufferLength+length){
    return 1;
  }
  
  // ensure we are currently a slave transmitter
  if(TWI_STX != twi_state){
    return 2;
  }
  
  // set length and copy data into tx buffer
  t = twi_txBufferLength;
  twi_txBufferLength += length;
  for(i = 0; i < length; ++i){
    twi_txBuffer[t+i] = data[i];
  }
  
  return 0;
}

Did I missed something?
What do you think?

In the onRequest handler, only one Wire.write may be used.
I don't know if that is written somewhere, but its a fact.
You have to build an array with data in the onRequest handler.

It would be great if your changes are okay.
The Wire.write can be used anywhere in any situation. I don't know if it can be changed while maintaining the compatibility.

I have a problem with Master-receiver myself, http://forum.arduino.cc/index.php?topic=172296.0

I opened an issue on Github for this, I2C/Wire library: Allow multiple Wire.write in Slave onRequest handler. · Issue #1475 · arduino/Arduino · GitHub

Erdin:
In the onRequest handler, only one Wire.write may be used.
I don't know if that is written somewhere, but its a fact.
You have to build an array with data in the onRequest handler.

It would be great if your changes are okay.
The Wire.write can be used anywhere in any situation. I don't know if it can be changed while maintaining the compatibility.

I have a problem with Master-receiver myself, http://forum.arduino.cc/index.php?topic=172296.0

Got Caught with this. I can find no excuse for why this behavior is not documented or repaired.

The repair is simple, and I cannot find any incompatibilities with existing code.

Does anyone have justifications for not repairing it?

Chuck.


Check out my Kickstarter Project Memory Panes an expansion RAM Shield for Mega2560's. It adds 1MB of RAM for those projects where 8KB is not enough.