'TWI/I2C Wire Library' Clarification Question

In the wire library, when using an Arduino as a slave, we use the Wire.onReceive(receiveEvent) and Wire.onRequest(requestEvent) methods to define the methods to use when data is received and requested. Simple enough; this I understand.

The receiveEvent(int howMany) method that I define has one parameter, an int, that presumably tells me how many bytes are being requested. This is all well and good - somebody stop me if I'm wrong or misunderstanding something.

Now, finally, the question:

The requestEvent() method that I define has NO parameters. Therefore the Arduino has no way of knowing what is actually being requested, only that a request has been made. This seems too ridiculous to be true - I've GOT to be missing something here.

Let's say I want to store some data on the Arduino's internal EEPROM and send that data to a master device. I have no way of determining what address the master is trying to read, do I? I've gotta be getting this wrong - right?

The requestEvent() method that I define has NO parameters. Therefore the Arduino has no way of knowing what is actually being requested, only that a request has been made. This seems too ridiculous to be true - I've GOT to be missing something here.

Let's say I want to store some data on the Arduino's internal EEPROM and send that data to a master device. I have no way of determining what address the master is trying to read, do I? I've gotta be getting this wrong - right?

No takers on this one? Come on, someone help me out here.

How do I get my Arduino to act as a slave EEPROM?

How can I tell which memory address the master is requesting??

From my limited playing-around (emulating a Wiimote nunchuk accessory) the way you deal with this is at some level above I2C. For example when the Wiimote wants to read some data from the nunchuk, it writes data indicating the address it wants to read from (ie, you get a receiveEvent), and then it requests the data (ie, you get a requestEvent).

However what is more confusing to me is that you don't even get told the number of bytes being requested. From what I'm seeing in my interactions with the Wiimote, there is no way of avoiding this information, since the client (the Wii, or whatever) can request any number of bytes it likes from the device.

EDIT: "above I2C", not "about I2C".

I see your point, and I don't understand it either. Either I'm missing something that should be obvious but isn't, or they didn't have this kind of functionality in mind when they wrote the Wire library.

I did a little more digging and it seems that as an I2C slave you basically keep sending data until the master tells you to stop. Doesn't look like you can get Wire to tell you how much it sent though. But maybe I'm missing something obvious too...

Let the master send you something first - like how many bytes to send. Then you send that number of bytes.

You may need a higher layer protocol to make things work out; e.g., master sends 0x01, which is the opcode I arbitrarily assign to mean "transmit 1 byte containing the number of bytes you have ready to send", so the slave sends back 1 byte in response. Based on that info, master sends opcode 0x02, which means "send me all the data in your buffer". Based on previous transfer, master knows how many bytes to expect. The can be more complex, with some "opcodes" containing data in unused bits, or variable number of bytes, etc.

-j

That would be good if I controlled the protocol but for my project I don't (the master is a Wii remote, and when it wants data it just sends one byte indicating the address to start from). But I think I can work around it for my stuff by always sending 16 bytes, which I think is the maximum, and letting the Wire library work out the details :wink:

I don't have control over the protocol either - I am just emulating a Microchip 24LC00 EEPROM.

Hi,

I don't have control over the protocol either - I am just emulating a Microchip 24LC00 EEPROM.

You have complete control over the protocol, just do exactly what the 24LC00 would do!
See for instance the Read-Operations from the datasheet
8.1 Current address read
When this is initated by the master, your slave's will only see that its onRequest()-function is called. You return the byte from the current address-counter. End of operation.

8.2 Random Read
The master starts this by initiating a write. Your slave's onReceive() will be called, and you have to remember the address that came with the write. The next thing you'll see is onRequest() again, now you return the data found at the address you received with the write call.

and so on...

BTW:
Why would I want a 25 Euro Arduino mimic an EEPROM that sells for 50 Cent, or is this just a proof of concept thing?

Eberhard

It's educational! If I can't emulate an EEPROM it doesn't say much about my understanding of the subject - and I have a microprocessor that interrogates a 24LC00 to store/retrieve data, so it makes a great test subject.