@@ -28,12 +28,12 @@ extern "C" {
2828#include " Wire.h"
2929
3030// Initialize Class Variables //////////////////////////////////////////////////
31- uint8_t TwoWire::rxBuffer[BUFFER_LENGTH] ;
31+ uint8_t * TwoWire::rxBuffer = nullptr ;
3232uint8_t TwoWire::rxBufferIndex = 0 ;
3333uint8_t TwoWire::rxBufferLength = 0 ;
3434
3535uint8_t TwoWire::txAddress = 0 ;
36- uint8_t TwoWire::txBuffer[BUFFER_LENGTH] ;
36+ uint8_t * TwoWire::txBuffer = nullptr ;
3737uint8_t TwoWire::txBufferIndex = 0 ;
3838uint8_t TwoWire::txBufferLength = 0 ;
3939
@@ -66,9 +66,11 @@ void TwoWire::begin(uint8_t address)
6666{
6767 rxBufferIndex = 0 ;
6868 rxBufferLength = 0 ;
69+ rxBuffer = resetBuffer (rxBuffer);
6970
7071 txBufferIndex = 0 ;
7172 txBufferLength = 0 ;
73+ txBuffer = resetBuffer (txBuffer);
7274
7375 transmitting = 0 ;
7476
@@ -97,6 +99,10 @@ void TwoWire::begin(int address)
9799
98100void TwoWire::end (void )
99101{
102+ free (txBuffer);
103+ txBuffer = nullptr ;
104+ free (rxBuffer);
105+ rxBuffer = nullptr ;
100106 i2c_deinit (&_i2c);
101107}
102108
@@ -109,6 +115,13 @@ uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddres
109115{
110116 UNUSED (sendStop);
111117 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+
112125 if (isize > 0 ) {
113126 // send internal address; this mode allows sending a repeated start to access
114127 // 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
128141 endTransmission (false );
129142 }
130143
131- // clamp to buffer length
132- if (quantity > BUFFER_LENGTH){
133- quantity = BUFFER_LENGTH;
134- }
135144 // perform blocking read into buffer
136- // uint8_t read = twi_readFrom(address, rxBuffer, quantity, sendStop);
137145 uint8_t read = 0 ;
138146 if (I2C_OK == i2c_master_read (&_i2c, address << 1 , rxBuffer, quantity))
139147 read = quantity;
@@ -216,9 +224,15 @@ uint8_t TwoWire::endTransmission(uint8_t sendStop)
216224 break ;
217225 }
218226
227+ // Reduce buffer size to free memory in case of large memory use
228+ if (txBufferLength > BUFFER_LENGTH) {
229+ txBuffer = resetBuffer (txBuffer);
230+ }
231+
219232 // reset tx buffer iterator vars
220233 txBufferIndex = 0 ;
221234 txBufferLength = 0 ;
235+
222236 // indicate that we are done transmitting
223237 transmitting = 0 ;
224238 }
@@ -241,8 +255,9 @@ size_t TwoWire::write(uint8_t data)
241255{
242256 if (transmitting){
243257 // 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 ){
246261 setWriteError ();
247262 return 0 ;
248263 }
@@ -254,27 +269,38 @@ size_t TwoWire::write(uint8_t data)
254269 }else {
255270 // in slave send mode
256271 // 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+ }
258275 }
259276 return 1 ;
260277}
261278
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+ */
265286size_t TwoWire::write (const uint8_t *data, size_t quantity)
266287{
288+ size_t nb = 0 ;
289+
267290 if (transmitting){
268291 // in master transmitter mode
269292 for (size_t i = 0 ; i < quantity; ++i){
270- write (data[i]);
293+ nb += write (data[i]);
271294 }
295+ return nb;
272296 }else {
273297 // in slave send mode
274298 // 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+ }
276302 }
277- return quantity ;
303+ return 0 ;
278304}
279305
280306// must be called in:
@@ -296,6 +322,12 @@ int TwoWire::read(void)
296322 if (rxBufferIndex < rxBufferLength){
297323 value = rxBuffer[rxBufferIndex];
298324 ++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+ }
299331 }
300332
301333 return value;
@@ -319,8 +351,10 @@ void TwoWire::flush(void)
319351{
320352 rxBufferIndex = 0 ;
321353 rxBufferLength = 0 ;
354+ rxBuffer = resetBuffer (rxBuffer);
322355 txBufferIndex = 0 ;
323356 txBufferLength = 0 ;
357+ txBuffer = resetBuffer (txBuffer);
324358}
325359
326360// behind the scenes function that is called when data is received
@@ -377,6 +411,37 @@ void TwoWire::onRequest( void (*function)(void) )
377411 user_onRequest = function;
378412}
379413
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+
380445// Preinstantiate Objects //////////////////////////////////////////////////////
381446
382447TwoWire Wire = TwoWire(); // D14-D15
0 commit comments