@@ -29,11 +29,13 @@ extern "C" {
2929
3030// Initialize Class Variables //////////////////////////////////////////////////
3131uint8_t *TwoWire::rxBuffer = nullptr ;
32+ uint8_t TwoWire::rxBufferAllocated = 0 ;
3233uint8_t TwoWire::rxBufferIndex = 0 ;
3334uint8_t TwoWire::rxBufferLength = 0 ;
3435
3536uint8_t TwoWire::txAddress = 0 ;
3637uint8_t *TwoWire::txBuffer = nullptr ;
38+ uint8_t TwoWire::txBufferAllocated = 0 ;
3739uint8_t TwoWire::txBufferIndex = 0 ;
3840uint8_t TwoWire::txBufferLength = 0 ;
3941
@@ -66,11 +68,11 @@ void TwoWire::begin(uint8_t address)
6668{
6769 rxBufferIndex = 0 ;
6870 rxBufferLength = 0 ;
69- rxBuffer = resetBuffer (rxBuffer );
71+ resetRxBuffer ( );
7072
7173 txBufferIndex = 0 ;
7274 txBufferLength = 0 ;
73- txBuffer = resetBuffer (txBuffer );
75+ resetTxBuffer ( );
7476
7577 transmitting = 0 ;
7678
@@ -101,8 +103,10 @@ void TwoWire::end(void)
101103{
102104 free (txBuffer);
103105 txBuffer = nullptr ;
106+ txBufferAllocated = 0 ;
104107 free (rxBuffer);
105108 rxBuffer = nullptr ;
109+ rxBufferAllocated = 0 ;
106110 i2c_deinit (&_i2c);
107111}
108112
@@ -115,7 +119,7 @@ uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddres
115119{
116120 UNUSED (sendStop);
117121 if (master == true ) {
118- rxBuffer = allocateBuffer (rxBuffer, quantity);
122+ allocateRxBuffer ( quantity);
119123 // error if no memory block available to allocate the buffer
120124 if (rxBuffer == nullptr ){
121125 setWriteError ();
@@ -224,10 +228,8 @@ uint8_t TwoWire::endTransmission(uint8_t sendStop)
224228 break ;
225229 }
226230
227- // Reduce buffer size to free memory in case of large memory use
228- if (txBufferLength > BUFFER_LENGTH) {
229- txBuffer = resetBuffer (txBuffer);
230- }
231+ // reset Tx buffer
232+ resetTxBuffer ();
231233
232234 // reset tx buffer iterator vars
233235 txBufferIndex = 0 ;
@@ -255,7 +257,7 @@ size_t TwoWire::write(uint8_t data)
255257{
256258 if (transmitting){
257259 // in master transmitter mode
258- txBuffer = allocateBuffer (txBuffer, txBufferLength + 1 );
260+ allocateTxBuffer ( txBufferLength + 1 );
259261 // error if no memory block available to allocate the buffer
260262 if (txBuffer == nullptr ){
261263 setWriteError ();
@@ -285,14 +287,20 @@ size_t TwoWire::write(uint8_t data)
285287 */
286288size_t TwoWire::write (const uint8_t *data, size_t quantity)
287289{
288- size_t nb = 0 ;
289-
290290 if (transmitting){
291291 // in master transmitter mode
292- for (size_t i = 0 ; i < quantity; ++i){
293- nb += write (data[i]);
292+ allocateTxBuffer (txBufferLength + quantity);
293+ // error if no memory block available to allocate the buffer
294+ if (txBuffer == nullptr ){
295+ setWriteError ();
296+ return 0 ;
294297 }
295- return nb;
298+ // put bytes in tx buffer
299+ memcpy (&(txBuffer[txBufferIndex]), data, quantity);
300+ txBufferIndex= txBufferIndex + quantity;
301+ // update amount in buffer
302+ txBufferLength = txBufferIndex;
303+ return quantity;
296304 }else {
297305 // in slave send mode
298306 // reply to master
@@ -323,11 +331,12 @@ int TwoWire::read(void)
323331 value = rxBuffer[rxBufferIndex];
324332 ++rxBufferIndex;
325333
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- }
334+ /* Commented as not I think it is not useful
335+ * but kept to show that it is possible to
336+ * reset rx buffer when no more data available */
337+ /* if(rxBufferIndex == rxBufferLength) {
338+ resetRxBuffer();
339+ }*/
331340 }
332341
333342 return value;
@@ -351,10 +360,10 @@ void TwoWire::flush(void)
351360{
352361 rxBufferIndex = 0 ;
353362 rxBufferLength = 0 ;
354- rxBuffer = resetBuffer (rxBuffer );
363+ resetRxBuffer ( );
355364 txBufferIndex = 0 ;
356365 txBufferLength = 0 ;
357- txBuffer = resetBuffer (txBuffer );
366+ resetTxBuffer ( );
358367}
359368
360369// behind the scenes function that is called when data is received
@@ -373,9 +382,7 @@ void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes)
373382 }
374383 // copy twi rx buffer into local read buffer
375384 // this enables new reads to happen in parallel
376- for (uint8_t i = 0 ; i < numBytes; ++i){
377- rxBuffer[i] = inBytes[i];
378- }
385+ memcpy (rxBuffer, inBytes, numBytes);
379386 // set rx iterator vars
380387 rxBufferIndex = 0 ;
381388 rxBufferLength = numBytes;
@@ -412,34 +419,41 @@ void TwoWire::onRequest( void (*function)(void) )
412419}
413420
414421/* *
415- * @brief Change the size of the buffer.
416- * @param buffer: pointer to the allocated buffer
422+ * @brief Allocate the Rx/Tx buffer to the requested length if needed
423+ * @note Minimum allocated size is BUFFER_LENGTH)
417424 * @param length: number of bytes to allocate
418- * @retval pointer to the new buffer location
419425 */
420- uint8_t * TwoWire::allocateBuffer ( uint8_t *buffer, size_t length)
426+ inline void TwoWire::allocateRxBuffer ( size_t length)
421427{
428+ if (rxBufferAllocated < length) {
422429 // By default we allocate BUFFER_LENGTH bytes. It is the min size of the buffer.
423- if (length < BUFFER_LENGTH) {
424- length = BUFFER_LENGTH;
430+ if (length < BUFFER_LENGTH) { length = BUFFER_LENGTH; }
431+ rxBuffer = (uint8_t *)realloc (rxBuffer, length * sizeof (uint8_t ));
432+ rxBufferAllocated = (rxBuffer != nullptr ) ? length: 0 ;
425433 }
434+ }
426435
427- buffer = (uint8_t *)realloc (buffer, length * sizeof (uint8_t ));
428- return buffer;
436+ inline void TwoWire::allocateTxBuffer (size_t length)
437+ {
438+ if (txBufferAllocated < length) {
439+ // By default we allocate BUFFER_LENGTH bytes. It is the min size of the buffer.
440+ if (length < BUFFER_LENGTH) { length = BUFFER_LENGTH; }
441+ txBuffer = (uint8_t *)realloc (txBuffer, length * sizeof (uint8_t ));
442+ txBufferAllocated = (txBuffer != nullptr ) ? length: 0 ;
443+ }
429444}
430445
431446/* *
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
447+ * @brief Reset Rx/Tx buffer content to 0
435448 */
436- uint8_t * TwoWire::resetBuffer ( uint8_t *buffer )
449+ inline void TwoWire::resetRxBuffer ( void )
437450{
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;
451+ if (rxBuffer != nullptr ) memset (rxBuffer, 0 , rxBufferAllocated);
452+ }
453+
454+ inline void TwoWire::resetTxBuffer (void )
455+ {
456+ if (txBuffer != nullptr ) memset (txBuffer, 0 , txBufferAllocated);
443457}
444458
445459// Preinstantiate Objects //////////////////////////////////////////////////////
0 commit comments