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. #589

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// 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 <WireBuffer.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
printWireBufferSize(Serial);
}

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

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

void printWireBufferSize(Stream& stream) {
stream.print("Wire receive buffer size is ");
stream.println(WireBuffer::RX_BUFFER_SIZE);
stream.print("Wire transmit buffer size is ");
stream.println(WireBuffer::TX_BUFFER_SIZE);
stream.print("twi_masterBuffer size is ");
stream.println(twiBuffer::TWI_MASTER_BUFFER_SIZE);
stream.print("twi_rxBuffer size is ");
stream.println(twiBuffer::TWI_RX_BUFFER_SIZE);
stream.print("twi_txBuffer size is ");
stream.println(twiBuffer::TWI_TX_BUFFER_SIZE);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// 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 <WireBuffer.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
printWireBufferSize(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 printWireBufferSize(Stream& stream) {
stream.print("Wire receive buffer size is ");
stream.println(WireBuffer::RX_BUFFER_SIZE);
stream.print("Wire transmit buffer size is ");
stream.println(WireBuffer::TX_BUFFER_SIZE);
stream.print("twi_masterBuffer size is ");
stream.println(twiBuffer::TWI_MASTER_BUFFER_SIZE);
stream.print("twi_rxBuffer size is ");
stream.println(twiBuffer::TWI_RX_BUFFER_SIZE);
stream.print("twi_txBuffer size is ");
stream.println(twiBuffer::TWI_TX_BUFFER_SIZE);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// 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 <WireBuffer.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
printWireBufferSize(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 printWireBufferSize(Stream& stream) {
stream.print("Wire receive buffer size is ");
stream.println(WireBuffer::RX_BUFFER_SIZE);
stream.print("Wire transmit buffer size is ");
stream.println(WireBuffer::TX_BUFFER_SIZE);
stream.print("twi_masterBuffer size is ");
stream.println(twiBuffer::TWI_MASTER_BUFFER_SIZE);
stream.print("twi_rxBuffer size is ");
stream.println(twiBuffer::TWI_RX_BUFFER_SIZE);
stream.print("twi_txBuffer size is ");
stream.println(twiBuffer::TWI_TX_BUFFER_SIZE);
delay(250); // Give time to free up Serial output buffer.
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// 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 <WireBuffer.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);
printWireBufferSize(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 printWireBufferSize(Stream& stream) {
stream.print("Wire receive buffer size is ");
stream.println(WireBuffer::RX_BUFFER_SIZE);
stream.print("Wire transmit buffer size is ");
stream.println(WireBuffer::TX_BUFFER_SIZE);
stream.print("twi_masterBuffer size is ");
stream.println(twiBuffer::TWI_MASTER_BUFFER_SIZE);
stream.print("twi_rxBuffer size is ");
stream.println(twiBuffer::TWI_RX_BUFFER_SIZE);
stream.print("twi_txBuffer size is ");
stream.println(twiBuffer::TWI_TX_BUFFER_SIZE);
}
49 changes: 12 additions & 37 deletions libraries/Wire/src/Wire.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
TwoWire.cpp - TWI/I2C library for Wiring & Arduino
Wire.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
Expand All @@ -21,30 +21,29 @@
Modified 2020 by Greyson Christoforo ([email protected]) to implement timeouts
*/

extern "C" {
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "utility/twi.h"
}
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "utility/twi.h"

#include "WireBuffer.h"
#include "Wire.h"

// Initialize Class Variables //////////////////////////////////////////////////

uint8_t TwoWire::rxBuffer[BUFFER_LENGTH];
uint8_t TwoWire::rxBufferIndex = 0;
uint8_t TwoWire::rxBufferLength = 0;

uint8_t TwoWire::txAddress = 0;
uint8_t TwoWire::txBuffer[BUFFER_LENGTH];
uint8_t TwoWire::txBufferIndex = 0;
uint8_t TwoWire::txBufferLength = 0;

uint8_t TwoWire::transmitting = 0;
void (*TwoWire::user_onRequest)(void);
void (*TwoWire::user_onReceive)(int);

using namespace WireBuffer;

// Constructors ////////////////////////////////////////////////////////////////

TwoWire::TwoWire()
Expand Down Expand Up @@ -154,8 +153,8 @@ uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddres
}

// clamp to buffer length
if(quantity > BUFFER_LENGTH){
quantity = BUFFER_LENGTH;
if(quantity > RX_BUFFER_SIZE){
quantity = RX_BUFFER_SIZE;
}
// perform blocking read into buffer
uint8_t read = twi_readFrom(address, rxBuffer, quantity, sendStop);
Expand All @@ -166,25 +165,6 @@ uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddres
return read;
}

uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop) {
return requestFrom((uint8_t)address, (uint8_t)quantity, (uint32_t)0, (uint8_t)0, (uint8_t)sendStop);
}

uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity)
{
return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
}

uint8_t TwoWire::requestFrom(int address, int quantity)
{
return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
}

uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop)
{
return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)sendStop);
}

void TwoWire::beginTransmission(uint8_t address)
{
// indicate that we are transmitting
Expand All @@ -196,11 +176,6 @@ void TwoWire::beginTransmission(uint8_t address)
txBufferLength = 0;
}

void TwoWire::beginTransmission(int address)
{
beginTransmission((uint8_t)address);
}

//
// Originally, 'endTransmission' was an f(void) function.
// It has been modified to take one parameter indicating
Expand Down Expand Up @@ -242,7 +217,7 @@ size_t TwoWire::write(uint8_t data)
if(transmitting){
// in master transmitter mode
// don't bother if buffer is full
if(txBufferLength >= BUFFER_LENGTH){
if(txBufferLength >= TX_BUFFER_SIZE){
setWriteError();
return 0;
}
Expand Down Expand Up @@ -336,7 +311,7 @@ void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes)
// copy twi rx buffer into local read buffer
// this enables new reads to happen in parallel
for(uint8_t i = 0; i < numBytes; ++i){
rxBuffer[i] = inBytes[i];
rxBuffer[i] = inBytes[i];
}
// set rx iterator vars
rxBufferIndex = 0;
Expand Down
Loading
Loading