Skip to content

Commit 3df1392

Browse files
authored
Added 'TwoWire::setBufferSize()' to Wire library (#2962)
'setBufferSize()' allows to modify the receive buffer size (inspired by the ESP32 code)
1 parent 7c51742 commit 3df1392

File tree

2 files changed

+47
-5
lines changed

2 files changed

+47
-5
lines changed

libraries/Wire/src/Wire.cpp

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
You should have received a copy of the GNU Lesser General Public
2020
License along with this library; if not, write to the Free Software
2121
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22+
23+
Modified May 2025 by Sven Bruns (Lorandil on GitHub) to support user defined buffer size (inspired by ESP32 code)
2224
*/
2325

2426
#include <Arduino.h>
@@ -46,6 +48,10 @@ TwoWire::TwoWire(i2c_inst_t *i2c, pin_size_t sda, pin_size_t scl) {
4648
_running = false;
4749
_txBegun = false;
4850
_buffLen = 0;
51+
52+
// allocate buffer memory early, so we don't fragment the heap later
53+
_buffSize = WIRE_BUFFER_SIZE;
54+
_buff = (uint8_t *)malloc(_buffSize);
4955
}
5056

5157
bool TwoWire::setSDA(pin_size_t pin) {
@@ -158,6 +164,16 @@ void TwoWire::begin(uint8_t addr) {
158164
// ERROR
159165
return;
160166
}
167+
168+
// allocate buffer if necessary
169+
if (!_buff) {
170+
_buff = (uint8_t *)malloc(_buffSize);
171+
if (!_buff) {
172+
// ERROR
173+
return;
174+
}
175+
}
176+
161177
_slave = true;
162178
i2c_init(_i2c, _clkHz);
163179
i2c_set_slave_mode(_i2c, true, addr);
@@ -192,7 +208,7 @@ void TwoWire::onIRQ() {
192208
// First, pull off any data available
193209
if (irqstat & (1 << 2)) {
194210
// RX_FULL
195-
if (_buffLen < (int)sizeof(_buff)) {
211+
if (_buffLen < int(_buffSize)) {
196212
_buff[_buffLen++] = _i2c->hw->data_cmd & 0xff;
197213
} else {
198214
_i2c->hw->data_cmd;
@@ -271,7 +287,7 @@ void TwoWire::beginTransmission(uint8_t addr) {
271287
}
272288

273289
size_t TwoWire::requestFrom(uint8_t address, size_t quantity, bool stopBit) {
274-
if (!_running || _txBegun || !quantity || (quantity > sizeof(_buff))) {
290+
if (!_running || _txBegun || !quantity || (quantity > _buffSize)) {
275291
return 0;
276292
}
277293

@@ -448,7 +464,7 @@ size_t TwoWire::write(uint8_t ucData) {
448464
return 0;
449465
}
450466
} else {
451-
if (!_txBegun || (_buffLen == sizeof(_buff))) {
467+
if (!_txBegun || (_buffLen == int(_buffSize))) {
452468
return 0;
453469
}
454470
_buff[_buffLen++] = ucData;
@@ -745,6 +761,20 @@ void TwoWire::clearTimeoutFlag() {
745761
_timeoutFlag = false;
746762
}
747763

764+
size_t TwoWire::setBufferSize(size_t bSize) {
765+
if (_running) {
766+
// ERROR - transmission already running. Report back current buffer size
767+
return _buffSize;
768+
}
769+
// only free the buffer, if it already exists and the new size differs from the current one
770+
if (_buff && (bSize != _buffSize)) {
771+
free(_buff);
772+
_buff = nullptr;
773+
}
774+
_buffSize = max(WIRE_BUFFER_SIZE_MIN, int(bSize)); // enforce minimum buffer size
775+
return _buffSize;
776+
}
777+
748778
#ifndef __WIRE0_DEVICE
749779
#define __WIRE0_DEVICE i2c0
750780
#endif

libraries/Wire/src/Wire.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
You should have received a copy of the GNU Lesser General Public
2020
License along with this library; if not, write to the Free Software
2121
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22+
23+
Modified May 2025 by Sven Bruns (Lorandil on GitHub) to support user defined buffer size (inspired by ESP32 code)
2224
*/
2325

2426
#pragma once
@@ -30,8 +32,14 @@
3032
// WIRE_HAS_END means Wire has end()
3133
#define WIRE_HAS_END 1
3234

35+
// WIRE_HAS_BUFFER_SIZE means Wire has setBufferSize()
36+
#define WIRE_HAS_BUFFER_SIZE 1
37+
3338
#ifndef WIRE_BUFFER_SIZE
34-
#define WIRE_BUFFER_SIZE 256
39+
#define WIRE_BUFFER_SIZE 256 // default size, if none is set using Wire::setBuffersize(size_t)
40+
#endif
41+
#ifndef WIRE_BUFFER_SIZE_MIN
42+
#define WIRE_BUFFER_SIZE_MIN 32 // minimum size for safe operation
3543
#endif
3644

3745
class TwoWire : public HardwareI2C {
@@ -97,6 +105,8 @@ class TwoWire : public HardwareI2C {
97105
bool getTimeoutFlag(void);
98106
void clearTimeoutFlag(void);
99107

108+
size_t setBufferSize(size_t bSize); // set buffer size (call prior to 'begin()')
109+
100110
// IRQ callback
101111
void onIRQ();
102112

@@ -115,7 +125,9 @@ class TwoWire : public HardwareI2C {
115125
bool _reset_with_timeout;
116126
void _handleTimeout(bool reset);
117127

118-
uint8_t _buff[WIRE_BUFFER_SIZE];
128+
uint8_t *_buff; // pointer to i2c buffer
129+
size_t _buffSize; // current buffer size
130+
119131
int _buffLen;
120132
int _buffOff;
121133

0 commit comments

Comments
 (0)