|
19 | 19 | You should have received a copy of the GNU Lesser General Public
|
20 | 20 | License along with this library; if not, write to the Free Software
|
21 | 21 | 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) |
22 | 24 | */
|
23 | 25 |
|
24 | 26 | #include <Arduino.h>
|
@@ -46,6 +48,10 @@ TwoWire::TwoWire(i2c_inst_t *i2c, pin_size_t sda, pin_size_t scl) {
|
46 | 48 | _running = false;
|
47 | 49 | _txBegun = false;
|
48 | 50 | _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); |
49 | 55 | }
|
50 | 56 |
|
51 | 57 | bool TwoWire::setSDA(pin_size_t pin) {
|
@@ -158,6 +164,16 @@ void TwoWire::begin(uint8_t addr) {
|
158 | 164 | // ERROR
|
159 | 165 | return;
|
160 | 166 | }
|
| 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 | + |
161 | 177 | _slave = true;
|
162 | 178 | i2c_init(_i2c, _clkHz);
|
163 | 179 | i2c_set_slave_mode(_i2c, true, addr);
|
@@ -192,7 +208,7 @@ void TwoWire::onIRQ() {
|
192 | 208 | // First, pull off any data available
|
193 | 209 | if (irqstat & (1 << 2)) {
|
194 | 210 | // RX_FULL
|
195 |
| - if (_buffLen < (int)sizeof(_buff)) { |
| 211 | + if (_buffLen < int(_buffSize)) { |
196 | 212 | _buff[_buffLen++] = _i2c->hw->data_cmd & 0xff;
|
197 | 213 | } else {
|
198 | 214 | _i2c->hw->data_cmd;
|
@@ -271,7 +287,7 @@ void TwoWire::beginTransmission(uint8_t addr) {
|
271 | 287 | }
|
272 | 288 |
|
273 | 289 | 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)) { |
275 | 291 | return 0;
|
276 | 292 | }
|
277 | 293 |
|
@@ -448,7 +464,7 @@ size_t TwoWire::write(uint8_t ucData) {
|
448 | 464 | return 0;
|
449 | 465 | }
|
450 | 466 | } else {
|
451 |
| - if (!_txBegun || (_buffLen == sizeof(_buff))) { |
| 467 | + if (!_txBegun || (_buffLen == int(_buffSize))) { |
452 | 468 | return 0;
|
453 | 469 | }
|
454 | 470 | _buff[_buffLen++] = ucData;
|
@@ -745,6 +761,20 @@ void TwoWire::clearTimeoutFlag() {
|
745 | 761 | _timeoutFlag = false;
|
746 | 762 | }
|
747 | 763 |
|
| 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 | + |
748 | 778 | #ifndef __WIRE0_DEVICE
|
749 | 779 | #define __WIRE0_DEVICE i2c0
|
750 | 780 | #endif
|
|
0 commit comments