Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow customization of transmit and receive buffer sizes for I2C 'Wire' object. #588

Closed
wants to merge 13 commits into from
Closed
1 change: 1 addition & 0 deletions libraries/Wire/examples/master_reader/master_reader.ino
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ void loop() {
char c = Wire.read(); // receive a byte as character
Serial.print(c); // print the character
}
Serial.println();

delay(500);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Wire Master Reader Custom Buffer

// Demonstrates use of the Wire library with customized buffers
// Reads data from an I2C/TWI slave device
// Refer to the "Wire Slave Sender Custom Buffer" example for use with this

// Created 31 Dec 2024

// This example code is in the public domain.


#include <Wire.h>
#include <TwoWireBuffers.h>
#include "Arduino.h"

// request 6 bytes from slave device #8
constexpr size_t REQUESTED_BYTE_COUNT = 6;

constexpr size_t RECEIVE_BUFFER_SIZE = REQUESTED_BYTE_COUNT;
constexpr size_t TRANSMIT_BUFFER_SIZE = 0; // There is no transmit in this sketch.

SET_Wire_BUFFERS(RECEIVE_BUFFER_SIZE, TRANSMIT_BUFFER_SIZE,
true /* master buffers needed */, false /* no slave buffers needed */ );

void setup() {
Wire.begin(); // join I2C bus (address optional for master)
Serial.begin(9600); // start serial for output

// This is just for curiosity and could be removed
printWireBuffersCapacity(Serial);
}

void loop() {
Wire.requestFrom(8, REQUESTED_BYTE_COUNT);

while (Wire.available()) { // slave may send less than requested
char c = Wire.read(); // receive a byte as character
Serial.print(c); // print the character
}
Serial.println();

delay(500);
}

void printWireBuffersCapacity(Stream& stream) {
const auto& buffers = GET_Wire_BUFFERS();

stream.print("Wire transmit buffer size is ");
stream.println(buffers.txWireBufferCapacity());

stream.print("Wire receive buffer size is ");
stream.println(buffers.rxWireBufferCapacity());

stream.print("twi_masterBuffer size is ");
stream.println(buffers.twi_masterBufferCapacity());

stream.print("twi_rxBuffer size is ");
stream.println(buffers.twi_rxBufferCapacity());

stream.print("twi_txBuffer size is ");
stream.println(buffers.twi_txBufferCapacity());
}
2 changes: 1 addition & 1 deletion libraries/Wire/examples/master_writer/master_writer.ino
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ void setup() {
Wire.begin(); // join I2C bus (address optional for master)
}

byte x = 0;
static byte x = 0;

void loop() {
Wire.beginTransmission(8); // transmit to device #8
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Wire Master Writer Custom Buffer

// Demonstrates use of the Wire library with customized buffers
// Writes data to an I2C/TWI slave device
// Refer to the "Wire Slave Receiver Custom Buffer" example for use with this

// Created 31 Dec 2024

// This example code is in the public domain.


#include <Wire.h>
#include <TwoWireBuffers.h>
#include "Arduino.h"

// The following text will not fit into the default buffer of 32 bytes.
static const char text[] = "You really won't believe it, but x is ";

constexpr size_t RECEIVE_BUFFER_SIZE = 0; // There is no receive in this sketch.
constexpr size_t TRANSMIT_BUFFER_SIZE = 42; // Enhance the buffer to 42 characters.

SET_Wire_BUFFERS(RECEIVE_BUFFER_SIZE, TRANSMIT_BUFFER_SIZE,
true /* master buffers needed */, false /* no slave buffers needed */ );

void setup() {
Wire.begin(); // join I2C bus (address optional for master)

// This is just for curiosity and could be removed
Serial.begin(9600); // start serial for output
printWireBuffersCapacity(Serial);
}

static byte x = 0;

void loop() {
Wire.beginTransmission(8); // transmit to device #8
Wire.write(text); // sends multiple bytes
Wire.write(x); // sends one byte
Wire.endTransmission(); // stop transmitting

x++;
delay(500);
}

void printWireBuffersCapacity(Stream& stream) {
const auto& buffers = GET_Wire_BUFFERS();

stream.print("Wire transmit buffer size is ");
stream.println(buffers.txWireBufferCapacity());

stream.print("Wire receive buffer size is ");
stream.println(buffers.rxWireBufferCapacity());

stream.print("twi_masterBuffer size is ");
stream.println(buffers.twi_masterBufferCapacity());

stream.print("twi_rxBuffer size is ");
stream.println(buffers.twi_rxBufferCapacity());

stream.print("twi_txBuffer size is ");
stream.println(buffers.twi_txBufferCapacity());
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Wire Slave Receiver Custom Buffer

// Demonstrates use of the Wire library with customized buffers
// Receives data as an I2C/TWI slave device
// Refer to the "Wire Master Writer Custom Buffer" example for use with this

// Created 31 Dec 2024

// This example code is in the public domain.


#include <Wire.h>
#include <TwoWireBuffers.h>
#include "Arduino.h"

constexpr size_t RECEIVE_BUFFER_SIZE = 42; // Be able receive up to 42 characters in one message.
constexpr size_t TRANSMIT_BUFFER_SIZE = 0; // There is no transmit in this sketch.

SET_Wire_BUFFERS(RECEIVE_BUFFER_SIZE, TRANSMIT_BUFFER_SIZE,
false /* no master buffers needed */, true /* slave buffers needed */ );

void setup() {
Wire.begin(8); // join I2C bus with address #8
Wire.onReceive(receiveEvent); // register event
Serial.begin(9600); // start serial for output

// This is just for curiosity and could be removed
printWireBuffersCapacity(Serial);
}

void loop() {
delay(100);
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
//
// Hint: This function is called within an interrupt context.
// That means, that there must be enough space in the Serial output
// buffer for the characters to be printed. Otherwise the
// Serial.print() call will lock up.
void receiveEvent(int howMany) {
while (1 < Wire.available()) { // loop through all but the last
const char c = Wire.read(); // receive byte as a character
Serial.print(c); // print the character
}
const int x = Wire.read(); // receive byte as an integer
Serial.println(x); // print the integer
}

void printWireBuffersCapacity(Stream& stream) {
const auto& buffers = GET_Wire_BUFFERS();

stream.print("Wire transmit buffer size is ");
stream.println(buffers.txWireBufferCapacity());

stream.print("Wire receive buffer size is ");
stream.println(buffers.rxWireBufferCapacity());

stream.print("twi_masterBuffer size is ");
stream.println(buffers.twi_masterBufferCapacity());

stream.print("twi_rxBuffer size is ");
stream.println(buffers.twi_rxBufferCapacity());

stream.print("twi_txBuffer size is ");
stream.println(buffers.twi_txBufferCapacity());
delay(250); // Give time to free up Serial output buffer.
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Wire Slave Sender Custom Buffer

// Demonstrates use of the Wire library with customized buffers
// Sends data as an I2C/TWI slave device
// Refer to the "Wire Master Reader Custom Buffer" example for use with this

// Created 31 Dec 2024

// This example code is in the public domain.


#include <Wire.h>
#include <TwoWireBuffers.h>
#include "Arduino.h"

static const char text[] = "hello "; // respond with message of 6 bytes

constexpr size_t RECEIVE_BUFFER_SIZE = 0; // There is no receive in this sketch.
constexpr size_t TRANSMIT_BUFFER_SIZE = sizeof(text)-1; // Don't need a byte for the \0

SET_Wire_BUFFERS(RECEIVE_BUFFER_SIZE, TRANSMIT_BUFFER_SIZE,
false /* no master buffers needed */, true /* slave buffers needed */ );

void setup() {
Wire.begin(8); // join I2C bus with address #8
Wire.onRequest(requestEvent); // register event

// This is just for curiosity and could be removed
Serial.begin(9600);
printWireBuffersCapacity(Serial);
}

void loop() {
delay(100);
}

// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent() {
Wire.write(text);
// as expected by master
}

void printWireBuffersCapacity(Stream& stream) {
const auto& buffers = GET_Wire_BUFFERS();

stream.print("Wire transmit buffer size is ");
stream.println(buffers.txWireBufferCapacity());

stream.print("Wire receive buffer size is ");
stream.println(buffers.rxWireBufferCapacity());

stream.print("twi_masterBuffer size is ");
stream.println(buffers.twi_masterBufferCapacity());

stream.print("twi_rxBuffer size is ");
stream.println(buffers.twi_rxBufferCapacity());

stream.print("twi_txBuffer size is ");
stream.println(buffers.twi_txBufferCapacity());
}
29 changes: 29 additions & 0 deletions libraries/Wire/src/TwoWireBuffers.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
TwoWireBuffers.cpp - TWI/I2C library for Wiring & Arduino
Copyright (c) 2006 Nicholas Zambetti. All right reserved.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "TwoWireBuffers.h"

constexpr size_t RX_BUFFER_DEFAULT_LENGTH = 32;
constexpr size_t TX_BUFFER_DEFAULT_LENGTH = 32;

// Default buffers for the one and only Wire object
template<> __attribute__((weak)) TwoWireBuffers::Interface& WireBuffers<0>::instance() { \
static TwoWireBuffers::Impl<RX_BUFFER_DEFAULT_LENGTH, TX_BUFFER_DEFAULT_LENGTH, true, true> buffers; \
return buffers; \
}
Loading
Loading