@@ -28,12 +28,12 @@ extern "C" {
28
28
#include " Wire.h"
29
29
30
30
// Initialize Class Variables //////////////////////////////////////////////////
31
- uint8_t TwoWire::rxBuffer[BUFFER_LENGTH] ;
31
+ uint8_t * TwoWire::rxBuffer = nullptr ;
32
32
uint8_t TwoWire::rxBufferIndex = 0 ;
33
33
uint8_t TwoWire::rxBufferLength = 0 ;
34
34
35
35
uint8_t TwoWire::txAddress = 0 ;
36
- uint8_t TwoWire::txBuffer[BUFFER_LENGTH] ;
36
+ uint8_t * TwoWire::txBuffer = nullptr ;
37
37
uint8_t TwoWire::txBufferIndex = 0 ;
38
38
uint8_t TwoWire::txBufferLength = 0 ;
39
39
@@ -66,9 +66,11 @@ void TwoWire::begin(uint8_t address)
66
66
{
67
67
rxBufferIndex = 0 ;
68
68
rxBufferLength = 0 ;
69
+ rxBuffer = resetBuffer (rxBuffer);
69
70
70
71
txBufferIndex = 0 ;
71
72
txBufferLength = 0 ;
73
+ txBuffer = resetBuffer (txBuffer);
72
74
73
75
transmitting = 0 ;
74
76
@@ -97,6 +99,10 @@ void TwoWire::begin(int address)
97
99
98
100
void TwoWire::end (void )
99
101
{
102
+ free (txBuffer);
103
+ txBuffer = nullptr ;
104
+ free (rxBuffer);
105
+ rxBuffer = nullptr ;
100
106
i2c_deinit (&_i2c);
101
107
}
102
108
@@ -109,6 +115,13 @@ uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddres
109
115
{
110
116
UNUSED (sendStop);
111
117
if (master == true ) {
118
+ rxBuffer = allocateBuffer (rxBuffer, quantity);
119
+ // error if no memory block available to allocate the buffer
120
+ if (rxBuffer == nullptr ){
121
+ setWriteError ();
122
+ return 0 ;
123
+ }
124
+
112
125
if (isize > 0 ) {
113
126
// send internal address; this mode allows sending a repeated start to access
114
127
// some devices' internal registers. This function is executed by the hardware
@@ -128,12 +141,7 @@ uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddres
128
141
endTransmission (false );
129
142
}
130
143
131
- // clamp to buffer length
132
- if (quantity > BUFFER_LENGTH){
133
- quantity = BUFFER_LENGTH;
134
- }
135
144
// perform blocking read into buffer
136
- // uint8_t read = twi_readFrom(address, rxBuffer, quantity, sendStop);
137
145
uint8_t read = 0 ;
138
146
if (I2C_OK == i2c_master_read (&_i2c, address << 1 , rxBuffer, quantity))
139
147
read = quantity;
@@ -216,9 +224,15 @@ uint8_t TwoWire::endTransmission(uint8_t sendStop)
216
224
break ;
217
225
}
218
226
227
+ // Reduce buffer size to free memory in case of large memory use
228
+ if (txBufferLength > BUFFER_LENGTH) {
229
+ txBuffer = resetBuffer (txBuffer);
230
+ }
231
+
219
232
// reset tx buffer iterator vars
220
233
txBufferIndex = 0 ;
221
234
txBufferLength = 0 ;
235
+
222
236
// indicate that we are done transmitting
223
237
transmitting = 0 ;
224
238
}
@@ -241,8 +255,9 @@ size_t TwoWire::write(uint8_t data)
241
255
{
242
256
if (transmitting){
243
257
// in master transmitter mode
244
- // don't bother if buffer is full
245
- if (txBufferLength >= BUFFER_LENGTH){
258
+ txBuffer = allocateBuffer (txBuffer, txBufferLength + 1 );
259
+ // error if no memory block available to allocate the buffer
260
+ if (txBuffer == nullptr ){
246
261
setWriteError ();
247
262
return 0 ;
248
263
}
@@ -254,27 +269,38 @@ size_t TwoWire::write(uint8_t data)
254
269
}else {
255
270
// in slave send mode
256
271
// reply to master
257
- i2c_slave_write_IT (&_i2c,&data,1 );
272
+ if (i2c_slave_write_IT (&_i2c,&data,1 ) != I2C_OK) {
273
+ return 0 ;
274
+ }
258
275
}
259
276
return 1 ;
260
277
}
261
278
262
- // must be called in:
263
- // slave tx event callback
264
- // or after beginTransmission(address)
279
+ /* *
280
+ * @brief This function must be called in slave Tx event callback or after
281
+ * beginTransmission() and before endTransmission().
282
+ * @param pdata: pointer to the buffer data
283
+ * @param quantity: number of bytes to write
284
+ * @retval number of bytes ready to write.
285
+ */
265
286
size_t TwoWire::write (const uint8_t *data, size_t quantity)
266
287
{
288
+ size_t nb = 0 ;
289
+
267
290
if (transmitting){
268
291
// in master transmitter mode
269
292
for (size_t i = 0 ; i < quantity; ++i){
270
- write (data[i]);
293
+ nb += write (data[i]);
271
294
}
295
+ return nb;
272
296
}else {
273
297
// in slave send mode
274
298
// reply to master
275
- i2c_slave_write_IT (&_i2c,(uint8_t *)data,quantity);
299
+ if (i2c_slave_write_IT (&_i2c, (uint8_t *)data, quantity) == I2C_OK) {
300
+ return quantity;
301
+ }
276
302
}
277
- return quantity ;
303
+ return 0 ;
278
304
}
279
305
280
306
// must be called in:
@@ -296,6 +322,12 @@ int TwoWire::read(void)
296
322
if (rxBufferIndex < rxBufferLength){
297
323
value = rxBuffer[rxBufferIndex];
298
324
++rxBufferIndex;
325
+
326
+ /* Reduce buffer size to free memory in case of large memory use when no more
327
+ data available */
328
+ if ((rxBufferIndex == rxBufferLength) && (rxBufferLength > BUFFER_LENGTH)) {
329
+ rxBuffer = resetBuffer (rxBuffer);
330
+ }
299
331
}
300
332
301
333
return value;
@@ -319,8 +351,10 @@ void TwoWire::flush(void)
319
351
{
320
352
rxBufferIndex = 0 ;
321
353
rxBufferLength = 0 ;
354
+ rxBuffer = resetBuffer (rxBuffer);
322
355
txBufferIndex = 0 ;
323
356
txBufferLength = 0 ;
357
+ txBuffer = resetBuffer (txBuffer);
324
358
}
325
359
326
360
// behind the scenes function that is called when data is received
@@ -377,6 +411,37 @@ void TwoWire::onRequest( void (*function)(void) )
377
411
user_onRequest = function;
378
412
}
379
413
414
+ /* *
415
+ * @brief Change the size of the buffer.
416
+ * @param buffer: pointer to the allocated buffer
417
+ * @param length: number of bytes to allocate
418
+ * @retval pointer to the new buffer location
419
+ */
420
+ uint8_t *TwoWire::allocateBuffer (uint8_t *buffer, size_t length)
421
+ {
422
+ // By default we allocate BUFFER_LENGTH bytes. It is the min size of the buffer.
423
+ if (length < BUFFER_LENGTH) {
424
+ length = BUFFER_LENGTH;
425
+ }
426
+
427
+ buffer = (uint8_t *)realloc (buffer, length * sizeof (uint8_t ));
428
+ return buffer;
429
+ }
430
+
431
+ /* *
432
+ * @brief Reset the buffer. Reduce its size to BUFFER_LENGTH.
433
+ * @param buffer: pointer to the allocated buffer
434
+ * @retval pointer to the new buffer location
435
+ */
436
+ uint8_t *TwoWire::resetBuffer (uint8_t *buffer)
437
+ {
438
+ buffer = (uint8_t *)realloc (buffer, BUFFER_LENGTH * sizeof (uint8_t ));
439
+ if (buffer != nullptr ) {
440
+ memset (buffer, 0 , BUFFER_LENGTH);
441
+ }
442
+ return buffer;
443
+ }
444
+
380
445
// Preinstantiate Objects //////////////////////////////////////////////////////
381
446
382
447
TwoWire Wire = TwoWire(); // D14-D15
0 commit comments