Skip to content

Commit 56ef4a4

Browse files
committed
Make Wire and twi buffers weak and allow to override by macro
SET_Wire_Buffers().
1 parent 59355fe commit 56ef4a4

File tree

12 files changed

+448
-26
lines changed

12 files changed

+448
-26
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Wire Master Reader Custom Buffer
2+
3+
// Demonstrates use of the Wire library with customized buffers
4+
// Reads data from an I2C/TWI slave device
5+
// Refer to the "Wire Slave Sender Custom Buffer" example for use with this
6+
7+
// Created 31 Dec 2024
8+
9+
// This example code is in the public domain.
10+
11+
12+
#include <Wire.h>
13+
#include <WireBuffer.h>
14+
#include "Arduino.h"
15+
16+
// request 6 bytes from slave device #8
17+
constexpr size_t REQUESTED_BYTE_COUNT = 6;
18+
19+
constexpr size_t RECEIVE_BUFFER_SIZE = REQUESTED_BYTE_COUNT;
20+
constexpr size_t TRANSMIT_BUFFER_SIZE = 0; // There is no transmit in this sketch.
21+
22+
SET_Wire_BUFFERS(RECEIVE_BUFFER_SIZE, TRANSMIT_BUFFER_SIZE,
23+
true /* master buffers needed */, false /* no slave buffers needed */ );
24+
25+
void setup() {
26+
Wire.begin(); // join I2C bus (address optional for master)
27+
Serial.begin(9600); // start serial for output
28+
29+
// This is just for curiosity and could be removed
30+
printWireBufferSize(Serial);
31+
}
32+
33+
void loop() {
34+
Wire.requestFrom(8, REQUESTED_BYTE_COUNT);
35+
36+
size_t count = 0;
37+
while (Wire.available()) { // slave may send less than requested
38+
++count;
39+
char c = Wire.read(); // receive a byte as character
40+
Serial.print(c); // print the character
41+
}
42+
if(count) {
43+
Serial.println();
44+
}
45+
delay(500);
46+
}
47+
48+
void printWireBufferSize(Stream& stream) {
49+
stream.print("Wire receive buffer size is ");
50+
stream.println(WireBuffer::RX_BUFFER_SIZE);
51+
stream.print("Wire transmit buffer size is ");
52+
stream.println(WireBuffer::TX_BUFFER_SIZE);
53+
stream.print("twi_masterBuffer size is ");
54+
stream.println(twiBuffer::TWI_MASTER_BUFFER_SIZE);
55+
stream.print("twi_rxBuffer size is ");
56+
stream.println(twiBuffer::TWI_RX_BUFFER_SIZE);
57+
stream.print("twi_txBuffer size is ");
58+
stream.println(twiBuffer::TWI_TX_BUFFER_SIZE);
59+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Wire Master Writer Custom Buffer
2+
3+
// Demonstrates use of the Wire library with customized buffers
4+
// Writes data to an I2C/TWI slave device
5+
// Refer to the "Wire Slave Receiver Custom Buffer" example for use with this
6+
7+
// Created 31 Dec 2024
8+
9+
// This example code is in the public domain.
10+
11+
12+
#include <Wire.h>
13+
#include <WireBuffer.h>
14+
#include "Arduino.h"
15+
16+
// The following text will not fit into the default buffer of 32 bytes.
17+
static const char text[] = "You really won't believe it, but x is ";
18+
19+
constexpr size_t RECEIVE_BUFFER_SIZE = 0; // There is no receive in this sketch.
20+
constexpr size_t TRANSMIT_BUFFER_SIZE = 42; // Enhance the buffer to 42 characters.
21+
22+
SET_Wire_BUFFERS(RECEIVE_BUFFER_SIZE, TRANSMIT_BUFFER_SIZE,
23+
true /* master buffers needed */, false /* no slave buffers needed */ );
24+
25+
void setup() {
26+
Wire.begin(); // join I2C bus (address optional for master)
27+
28+
// This is just for curiosity and could be removed
29+
Serial.begin(9600); // start serial for output
30+
printWireBufferSize(Serial);
31+
}
32+
33+
static byte x = 0;
34+
35+
void loop() {
36+
Wire.beginTransmission(8); // transmit to device #8
37+
Wire.write(text); // sends multiple bytes
38+
Wire.write(x); // sends one byte
39+
Wire.endTransmission(); // stop transmitting
40+
41+
x++;
42+
delay(500);
43+
}
44+
45+
void printWireBufferSize(Stream& stream) {
46+
stream.print("Wire receive buffer size is ");
47+
stream.println(WireBuffer::RX_BUFFER_SIZE);
48+
stream.print("Wire transmit buffer size is ");
49+
stream.println(WireBuffer::TX_BUFFER_SIZE);
50+
stream.print("twi_masterBuffer size is ");
51+
stream.println(twiBuffer::TWI_MASTER_BUFFER_SIZE);
52+
stream.print("twi_rxBuffer size is ");
53+
stream.println(twiBuffer::TWI_RX_BUFFER_SIZE);
54+
stream.print("twi_txBuffer size is ");
55+
stream.println(twiBuffer::TWI_TX_BUFFER_SIZE);
56+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Wire Slave Receiver Custom Buffer
2+
3+
// Demonstrates use of the Wire library with customized buffers
4+
// Receives data as an I2C/TWI slave device
5+
// Refer to the "Wire Master Writer Custom Buffer" example for use with this
6+
7+
// Created 31 Dec 2024
8+
9+
// This example code is in the public domain.
10+
11+
12+
#include <Wire.h>
13+
#include <WireBuffer.h>
14+
#include "Arduino.h"
15+
16+
constexpr size_t RECEIVE_BUFFER_SIZE = 42; // Be able receive up to 42 characters in one message.
17+
constexpr size_t TRANSMIT_BUFFER_SIZE = 0; // There is no transmit in this sketch.
18+
19+
SET_Wire_BUFFERS(RECEIVE_BUFFER_SIZE, TRANSMIT_BUFFER_SIZE,
20+
false /* no master buffers needed */, true /* slave buffers needed */ );
21+
22+
void setup() {
23+
Wire.begin(8); // join I2C bus with address #8
24+
Wire.onReceive(receiveEvent); // register event
25+
Serial.begin(9600); // start serial for output
26+
27+
// This is just for curiosity and could be removed
28+
printWireBufferSize(Serial);
29+
}
30+
31+
void loop() {
32+
delay(100);
33+
}
34+
35+
// function that executes whenever data is received from master
36+
// this function is registered as an event, see setup()
37+
//
38+
// Hint: This function is called within an interrupt context.
39+
// That means, that there must be enough space in the Serial output
40+
// buffer for the characters to be printed. Otherwise the
41+
// Serial.print() call will lock up.
42+
void receiveEvent(int howMany) {
43+
while (1 < Wire.available()) { // loop through all but the last
44+
const char c = Wire.read(); // receive byte as a character
45+
Serial.print(c); // print the character
46+
}
47+
const int x = Wire.read(); // receive byte as an integer
48+
Serial.println(x); // print the integer
49+
}
50+
51+
void printWireBufferSize(Stream& stream) {
52+
stream.print("Wire receive buffer size is ");
53+
stream.println(WireBuffer::RX_BUFFER_SIZE);
54+
stream.print("Wire transmit buffer size is ");
55+
stream.println(WireBuffer::TX_BUFFER_SIZE);
56+
stream.print("twi_masterBuffer size is ");
57+
stream.println(twiBuffer::TWI_MASTER_BUFFER_SIZE);
58+
stream.print("twi_rxBuffer size is ");
59+
stream.println(twiBuffer::TWI_RX_BUFFER_SIZE);
60+
stream.print("twi_txBuffer size is ");
61+
stream.println(twiBuffer::TWI_TX_BUFFER_SIZE);
62+
delay(250); // Give time to free up Serial output buffer.
63+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Wire Slave Sender Custom Buffer
2+
3+
// Demonstrates use of the Wire library with customized buffers
4+
// Sends data as an I2C/TWI slave device
5+
// Refer to the "Wire Master Reader Custom Buffer" example for use with this
6+
7+
// Created 31 Dec 2024
8+
9+
// This example code is in the public domain.
10+
11+
12+
#include <Wire.h>
13+
#include <WireBuffer.h>
14+
#include "Arduino.h"
15+
16+
static const char text[] = "hello "; // respond with message of 6 bytes
17+
18+
constexpr size_t RECEIVE_BUFFER_SIZE = 0; // There is no receive in this sketch.
19+
constexpr size_t TRANSMIT_BUFFER_SIZE = sizeof(text)-1; // Don't need a byte for the \0
20+
21+
SET_Wire_BUFFERS(RECEIVE_BUFFER_SIZE, TRANSMIT_BUFFER_SIZE,
22+
false /* no master buffers needed */, true /* slave buffers needed */ );
23+
24+
void setup() {
25+
Wire.begin(8); // join I2C bus with address #8
26+
Wire.onRequest(requestEvent); // register event
27+
28+
// This is just for curiosity and could be removed
29+
Serial.begin(9600);
30+
printWireBufferSize(Serial);
31+
}
32+
33+
void loop() {
34+
delay(100);
35+
}
36+
37+
// function that executes whenever data is requested by master
38+
// this function is registered as an event, see setup()
39+
void requestEvent() {
40+
Wire.write(text);
41+
// as expected by master
42+
}
43+
44+
void printWireBufferSize(Stream& stream) {
45+
stream.print("Wire receive buffer size is ");
46+
stream.println(WireBuffer::RX_BUFFER_SIZE);
47+
stream.print("Wire transmit buffer size is ");
48+
stream.println(WireBuffer::TX_BUFFER_SIZE);
49+
stream.print("twi_masterBuffer size is ");
50+
stream.println(twiBuffer::TWI_MASTER_BUFFER_SIZE);
51+
stream.print("twi_rxBuffer size is ");
52+
stream.println(twiBuffer::TWI_RX_BUFFER_SIZE);
53+
stream.print("twi_txBuffer size is ");
54+
stream.println(twiBuffer::TWI_TX_BUFFER_SIZE);
55+
}

Diff for: libraries/Wire/src/Wire.cpp

+8-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
TwoWire.cpp - TWI/I2C library for Wiring & Arduino
2+
Wire.cpp - TWI/I2C library for Wiring & Arduino
33
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
44
55
This library is free software; you can redistribute it and/or
@@ -26,23 +26,24 @@
2626
#include <inttypes.h>
2727
#include "utility/twi.h"
2828

29+
#include "WireBuffer.h"
2930
#include "Wire.h"
3031

3132
// Initialize Class Variables //////////////////////////////////////////////////
3233

33-
uint8_t TwoWire::rxBuffer[BUFFER_LENGTH];
3434
uint8_t TwoWire::rxBufferIndex = 0;
3535
uint8_t TwoWire::rxBufferLength = 0;
3636

3737
uint8_t TwoWire::txAddress = 0;
38-
uint8_t TwoWire::txBuffer[BUFFER_LENGTH];
3938
uint8_t TwoWire::txBufferIndex = 0;
4039
uint8_t TwoWire::txBufferLength = 0;
4140

4241
uint8_t TwoWire::transmitting = 0;
4342
void (*TwoWire::user_onRequest)(void);
4443
void (*TwoWire::user_onReceive)(int);
4544

45+
using namespace WireBuffer;
46+
4647
// Constructors ////////////////////////////////////////////////////////////////
4748

4849
TwoWire::TwoWire()
@@ -152,8 +153,8 @@ uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddres
152153
}
153154

154155
// clamp to buffer length
155-
if(quantity > BUFFER_LENGTH){
156-
quantity = BUFFER_LENGTH;
156+
if(quantity > RX_BUFFER_SIZE){
157+
quantity = RX_BUFFER_SIZE;
157158
}
158159
// perform blocking read into buffer
159160
uint8_t read = twi_readFrom(address, rxBuffer, quantity, sendStop);
@@ -240,7 +241,7 @@ size_t TwoWire::write(uint8_t data)
240241
if(transmitting){
241242
// in master transmitter mode
242243
// don't bother if buffer is full
243-
if(txBufferLength >= BUFFER_LENGTH){
244+
if(txBufferLength >= TX_BUFFER_SIZE){
244245
setWriteError();
245246
return 0;
246247
}
@@ -334,7 +335,7 @@ void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes)
334335
// copy twi rx buffer into local read buffer
335336
// this enables new reads to happen in parallel
336337
for(uint8_t i = 0; i < numBytes; ++i){
337-
rxBuffer[i] = inBytes[i];
338+
rxBuffer[i] = inBytes[i];
338339
}
339340
// set rx iterator vars
340341
rxBufferIndex = 0;

Diff for: libraries/Wire/src/Wire.h

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
TwoWire.h - TWI/I2C library for Arduino & Wiring
2+
Wire.h - TWI/I2C library for Arduino & Wiring
33
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
44
55
This library is free software; you can redistribute it and/or
@@ -20,26 +20,24 @@
2020
Modified 2020 by Greyson Christoforo ([email protected]) to implement timeouts
2121
*/
2222

23+
#pragma once
24+
2325
#ifndef TwoWire_h
2426
#define TwoWire_h
2527

2628
#include <inttypes.h>
2729
#include "Stream.h"
2830

29-
#define BUFFER_LENGTH 32
30-
3131
// WIRE_HAS_END means Wire has end()
3232
#define WIRE_HAS_END 1
3333

3434
class TwoWire : public Stream
3535
{
3636
private:
37-
static uint8_t rxBuffer[];
3837
static uint8_t rxBufferIndex;
3938
static uint8_t rxBufferLength;
4039

4140
static uint8_t txAddress;
42-
static uint8_t txBuffer[];
4341
static uint8_t txBufferIndex;
4442
static uint8_t txBufferLength;
4543

Diff for: libraries/Wire/src/WireBuffer.cpp

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
WireBuffer.cpp - TWI/I2C library for Arduino & Wiring
3+
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
4+
5+
This library is free software; you can redistribute it and/or
6+
modify it under the terms of the GNU Lesser General Public
7+
License as published by the Free Software Foundation; either
8+
version 2.1 of the License, or (at your option) any later version.
9+
10+
This library is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public
16+
License along with this library; if not, write to the Free Software
17+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
#include <stdint.h>
21+
#include <stddef.h>
22+
#include "WireBuffer.h"
23+
24+
// Default buffers as weak buffers
25+
namespace WireBuffer {
26+
extern __attribute__((weak)) const bufferSize_t TX_BUFFER_SIZE = WIRE_BUFFER_DEFAULT_SIZE;
27+
extern __attribute__((weak)) const bufferSize_t RX_BUFFER_SIZE = WIRE_BUFFER_DEFAULT_SIZE;
28+
__attribute__((weak)) uint8_t rxBuffer[WIRE_BUFFER_DEFAULT_SIZE];
29+
__attribute__((weak)) uint8_t txBuffer[WIRE_BUFFER_DEFAULT_SIZE];
30+
}

0 commit comments

Comments
 (0)