This is a fully backward compatible library with the Arduino Wire. It is improved, in order to control every steps of the I2C/TWI data communication.
With this library, the Arduino can behave as a Slave with the same timings of any dedicated I2C slave device, deciding what to send at any single Master request. In this way, differently from the official Wire, you can decide what byte to send during the Master request, and not only before it.
In this way, the slave using the HardWire can behave like any hard-wired I2C slave device (i.e. all-in-one chips like EEPROMs, RTCs and so on).
Everything is on GitHub so that proposals, feedbacks and critics can be easily provided.
This library can be downloaded from the GitHub links. It can be added in you Arduino project by copying the HardWire folder to the library folder ofthe Arduino IDE and then selecting it to add in your sketch. For a more detailed documentation, follow the GitHub links posted in the project's page.
Practical deep examples are under development, but basically you can follow the official Wire guide.
Here will be described only the differences between the original
Wire and the HardWire, everything else is compliant with the guide linked above to the Wire.
Wire.onReceive(handler) -> handler takes the number of bytes received, here the data buffer can be read, since the master has terminated the communication (official from Wire)
Wire.onRequest(handler) -> handler takes no parameters, but when called the slave prepares data to be sent using the standard Wire methods available, like read() and write() and whatever (official from Wire)
Wire.onReceiveData(handler) -> handler takes last received byte for the slave runtime computation, but will also fill the data buffer with that byte, as the official Wire does transparently (not present in Wire, new in the WireHard)
Wire.onReceiveDataNack(handler) -> handler takes no parameters but is used to notify the slave, since this received byte shall not be used (not present in Wire, new in the WireHard)
Wire.onReceiveAdx(handler) -> handler takes no parameters, but the slave is notified to prepare itself to receive data in the next bus transaction, the official Wire does it transparently (not present in Wire, new in the WireHard)
Wire.onRequestData(handler) -> handler returns a byte to be sent to master. This byte can be generated from the slave in the handler at runtime without using the shared buffer. The official Wire does it transparently, retrieving the data from the buffer (not present in Wire, new in the WireHard)
Wire.onRequestDataNack(handler) -> handler takes no parameters. Used when the master still requires data which is not available from the shared buffer. It is done transparently in the official Wire (not present in Wire, new in the WireHard)
All the functions marked as new in the WireHard are the core
difference between the official Wire library. The normal Wire handle
them automatically, always reading or writing in the shared buffer,
transparently to the user.
Initialization
Again, follow the official Wire guide. But this version supports a HARD_WIRE_MODE that shall be notified in the init. If mode is omitted, it is initialized following the normal Wire initialization
and the additional handlers are still supported, but is not mandatory
to use them. Actually, is never a mandatory to use the additional
handlers.
Wire.begin(slaveAddress, HARD_WIRE_MODE)->
will be supported all the additional handlers, with an undefined
(vitually infinite) number of read/write cycles, as any I2C slave device
would do.
Wire.begin(slaveAddress, NORMAL_MODE)->
will be supported all the additional handlers, but when the shared
buffer is full, it needs to be flushed or read before accepting any new
incoming byte:
this behavior is the same as the Wire library.