Short answer,yes. The demo is a trivial counter example and the slave always returns the value of the counter, then increments the local value.
To send more complex data (multi-byte length) the master requesting the data must know how to request and interpret the data. For example to receive text, is the text encoded or plain ASCII, is it fixed or variable length?
A simple implementation for handling a variable length string could be as follows on the slave side:
- Master initiates I2C transaction by writing a byte value to slave that should be interpreted as selecting a status string.
- The slave receives this byte and stores it to know what should be returned when the master issues a read request.
- The master initiates a read request.
- The slave returns the first byte of the string and increments an internal index to the string. End return value with ACK.
- The master receives the byte. If the slave ended with ACK, read another byte.If the slave ended with NACK, end transaction.
- When the slave sends the last byte of the string, end the transaction by sending a NACK.
Untested code for illustration of the slave side implementation:
const
SLAVE_STATUS_STRING = 1;
var
state: byte; // what to return when returning data
status: shortstring;
index: byte;
procedure DataReceivedHandler(data: byte; ACK: boolean);
begin
state := data;
// If addressing status, reset index to start of string
if state = SLAVE_STATUS_STRING then
index := 1;
end;
procedure DataRequestHandler(out data: byte; out ACK: boolean);
begin
case status of
SLAVE_STATUS_STRING:
begin
data := status[index];
inc(index);
ACK := index < length(status);
end;
end;
end;