diff --git a/examples/i2c_reply_datum/i2c_reply_datum.ino b/examples/i2c_reply_datum/i2c_reply_datum.ino new file mode 100644 index 0000000..8fe38e9 --- /dev/null +++ b/examples/i2c_reply_datum/i2c_reply_datum.ino @@ -0,0 +1,33 @@ +#include "I2CTransfer.h" + + +I2CTransfer myTransfer; + +struct __attribute__((packed)) STRUCT { + char z; + float y; +} testStruct; + +void I2C_RequestHandler(void) +{ + myTransfer.replyWithDatum(testStruct); +} + +void setup() +{ + Serial.begin(115200); + + Wire.begin(0x10); // Begin I2C as peripheral (slave) with address 0x10 + Wire.onRequest(I2C_RequestHandler); //Setup I2C_RequestHandler function as I2C request callback + + myTransfer.begin(Wire); + + testStruct.z = '$'; + testStruct.y = 4.5; +} + + +void loop() +{ + // Do nothing +} diff --git a/examples/i2c_request_datum/i2c_request_datum.ino b/examples/i2c_request_datum/i2c_request_datum.ino new file mode 100644 index 0000000..6b89dd7 --- /dev/null +++ b/examples/i2c_request_datum/i2c_request_datum.ino @@ -0,0 +1,47 @@ +#include "I2CTransfer.h" + + +I2CTransfer myTransfer; + +struct __attribute__((packed)) STRUCT { + char z; + float y; +} testStruct; + + +/////////////////////////////////////////////////////////////////// Callbacks +void hi() +{ + myTransfer.rxObj(testStruct); + Serial.print(testStruct.z); + Serial.println(testStruct.y); +} + +// supplied as a reference - persistent allocation required +const functionPtr callbackArr[] = { hi }; +/////////////////////////////////////////////////////////////////// + + +void setup() +{ + Serial.begin(115200); + Wire.begin(); // Begin I2C as controller (master) + + ///////////////////////////////////////////////////////////////// Config Parameters + configST myConfig; + myConfig.debug = true; + myConfig.callbacks = callbackArr; + myConfig.callbacksLen = sizeof(callbackArr) / sizeof(functionPtr); + ///////////////////////////////////////////////////////////////// + + myTransfer.begin(Wire, myConfig); +} + + +void loop() +{ + // Request datum from connected peripheral at address 0x10 + // Callback function hi() will be called on reception + myTransfer.requestDatum(sizeof(testStruct), 0x10); + delay(500); +} diff --git a/src/I2CTransfer.cpp b/src/I2CTransfer.cpp index 926edb6..03475e5 100644 --- a/src/I2CTransfer.cpp +++ b/src/I2CTransfer.cpp @@ -55,7 +55,8 @@ void I2CTransfer::begin(TwoWire& _port, const bool& _debug, Stream& _debugPort) to send as the payload in the next packet * const uint8_t &packetID - The packet 8-bit identifier * const uint8_t &targetAddress - I2C address to the device the packet - will be transmitted to + will be transmitted to. If targetAddress == 0xFF (invalid value in I2C), + data is transmitted as a reply to an I2C request. Return: ------- * uint8_t numBytesIncl - Number of payload bytes included in packet @@ -66,11 +67,15 @@ uint8_t I2CTransfer::sendData(const uint16_t& messageLen, const uint8_t& packetI numBytesIncl = packet.constructPacket(messageLen, packetID); - port->beginTransmission(targetAddress); + if (targetAddress < 0xFF) + port->beginTransmission(targetAddress); + port->write(packet.preamble, sizeof(packet.preamble)); port->write(packet.txBuff, numBytesIncl); port->write(packet.postamble, sizeof(packet.postamble)); - port->endTransmission(); + + if (targetAddress < 0xFF) + port->endTransmission(); return numBytesIncl; } diff --git a/src/I2CTransfer.h b/src/I2CTransfer.h index c5951f6..2adddc6 100644 --- a/src/I2CTransfer.h +++ b/src/I2CTransfer.h @@ -99,7 +99,54 @@ class I2CTransfer template uint8_t sendDatum(const T& val, const uint8_t& packetID = 0, const uint8_t& targetAddress = 0, const uint16_t& len = sizeof(T)) { - return sendData(packet.txObj(val, packetID, len), packetID, targetAddress); + return sendData(packet.txObj(val, 0, len), packetID, targetAddress); + } + + /* + uint8_t I2CTransfer::requestDatum(const uint16_t &len, const uint8_t &packetID=0, const uint8_t &targetAddress=0) + Description: + ------------ + * Requests "len" number of bytes from the I2C peripheral at specified address. + * Call rxObj() or setup a rx callback to retrieve the requested data. + Inputs: + ------- + * const uint16_t &len - Number of bytes to request + * const uint8_t &targetAddress - I2C address to the device the packet + will be transmitted to + Return: + ------- + * uint8_t - Number of payload bytes received + */ + uint8_t requestDatum(const uint16_t& len, const uint8_t& targetAddress = 0) + { + uint8_t bytesRead = port->requestFrom(targetAddress, len + PREAMBLE_SIZE + POSTAMBLE_SIZE); + processData(); + return bytesRead; + } + + /* + uint8_t I2CTransfer::replyWithDatum(const T &val, const uint8_t &packetID=0, const uint16_t &len=sizeof(T)) + Description: + ------------ + * Reply to an I2C request (requestDatum) with an arbitrary object + * Stuffs "len" number of bytes of an arbitrary object (byte, int, + float, double, struct, etc...) into the transmit buffer (txBuff) + starting at the index as specified by the argument "index" and + automatically transmits the bytes in an individual packet + Inputs: + ------- + * const T &val - Pointer to the object to be copied to the + transmit buffer (txBuff) + * const uint8_t &packetID - The packet 8-bit identifier + * const uint16_t &len - Number of bytes of the object "val" to transmit + Return: + ------- + * uint8_t - Number of payload bytes included in packet + */ + template + uint8_t replyWithDatum(const T& val, const uint8_t& packetID = 0, const uint16_t& len = sizeof(T)) + { + return sendDatum(val, packetID, 0xFF, len); //Send data with special I2C address 0xFF => don't initiate transmission }