@@ -28,12 +28,14 @@ extern "C" {
2828#include " Wire.h"
2929
3030// Initialize Class Variables //////////////////////////////////////////////////
31- uint8_t TwoWire::rxBuffer[BUFFER_LENGTH];
31+ uint8_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 ;
36- uint8_t TwoWire::txBuffer[BUFFER_LENGTH];
37+ uint8_t *TwoWire::txBuffer = nullptr ;
38+ uint8_t TwoWire::txBufferAllocated = 0 ;
3739uint8_t TwoWire::txBufferIndex = 0 ;
3840uint8_t TwoWire::txBufferLength = 0 ;
3941
@@ -66,9 +68,11 @@ void TwoWire::begin(uint8_t address)
6668{
6769 rxBufferIndex = 0 ;
6870 rxBufferLength = 0 ;
71+ resetRxBuffer ();
6972
7073 txBufferIndex = 0 ;
7174 txBufferLength = 0 ;
75+ resetTxBuffer ();
7276
7377 transmitting = 0 ;
7478
@@ -97,6 +101,12 @@ void TwoWire::begin(int address)
97101
98102void TwoWire::end (void )
99103{
104+ free (txBuffer);
105+ txBuffer = nullptr ;
106+ txBufferAllocated = 0 ;
107+ free (rxBuffer);
108+ rxBuffer = nullptr ;
109+ rxBufferAllocated = 0 ;
100110 i2c_deinit (&_i2c);
101111}
102112
@@ -109,6 +119,13 @@ uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddres
109119{
110120 UNUSED (sendStop);
111121 if (master == true ) {
122+ allocateRxBuffer (quantity);
123+ // error if no memory block available to allocate the buffer
124+ if (rxBuffer == nullptr ){
125+ setWriteError ();
126+ return 0 ;
127+ }
128+
112129 if (isize > 0 ) {
113130 // send internal address; this mode allows sending a repeated start to access
114131 // some devices' internal registers. This function is executed by the hardware
@@ -128,12 +145,7 @@ uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddres
128145 endTransmission (false );
129146 }
130147
131- // clamp to buffer length
132- if (quantity > BUFFER_LENGTH){
133- quantity = BUFFER_LENGTH;
134- }
135148 // perform blocking read into buffer
136- // uint8_t read = twi_readFrom(address, rxBuffer, quantity, sendStop);
137149 uint8_t read = 0 ;
138150 if (I2C_OK == i2c_master_read (&_i2c, address << 1 , rxBuffer, quantity))
139151 read = quantity;
@@ -216,9 +228,13 @@ uint8_t TwoWire::endTransmission(uint8_t sendStop)
216228 break ;
217229 }
218230
231+ // reset Tx buffer
232+ resetTxBuffer ();
233+
219234 // reset tx buffer iterator vars
220235 txBufferIndex = 0 ;
221236 txBufferLength = 0 ;
237+
222238 // indicate that we are done transmitting
223239 transmitting = 0 ;
224240 }
@@ -241,8 +257,9 @@ size_t TwoWire::write(uint8_t data)
241257{
242258 if (transmitting){
243259 // in master transmitter mode
244- // don't bother if buffer is full
245- if (txBufferLength >= BUFFER_LENGTH){
260+ allocateTxBuffer (txBufferLength + 1 );
261+ // error if no memory block available to allocate the buffer
262+ if (txBuffer == nullptr ){
246263 setWriteError ();
247264 return 0 ;
248265 }
@@ -254,27 +271,44 @@ size_t TwoWire::write(uint8_t data)
254271 }else {
255272 // in slave send mode
256273 // reply to master
257- i2c_slave_write_IT (&_i2c,&data,1 );
274+ if (i2c_slave_write_IT (&_i2c,&data,1 ) != I2C_OK) {
275+ return 0 ;
276+ }
258277 }
259278 return 1 ;
260279}
261280
262- // must be called in:
263- // slave tx event callback
264- // or after beginTransmission(address)
281+ /* *
282+ * @brief This function must be called in slave Tx event callback or after
283+ * beginTransmission() and before endTransmission().
284+ * @param pdata: pointer to the buffer data
285+ * @param quantity: number of bytes to write
286+ * @retval number of bytes ready to write.
287+ */
265288size_t TwoWire::write (const uint8_t *data, size_t quantity)
266289{
267290 if (transmitting){
268291 // in master transmitter mode
269- for (size_t i = 0 ; i < quantity; ++i){
270- 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 ;
271297 }
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;
272304 }else {
273305 // in slave send mode
274306 // reply to master
275- i2c_slave_write_IT (&_i2c,(uint8_t *)data,quantity);
307+ if (i2c_slave_write_IT (&_i2c, (uint8_t *)data, quantity) == I2C_OK) {
308+ return quantity;
309+ }
276310 }
277- return quantity ;
311+ return 0 ;
278312}
279313
280314// must be called in:
@@ -296,6 +330,13 @@ int TwoWire::read(void)
296330 if (rxBufferIndex < rxBufferLength){
297331 value = rxBuffer[rxBufferIndex];
298332 ++rxBufferIndex;
333+
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+ }*/
299340 }
300341
301342 return value;
@@ -319,8 +360,10 @@ void TwoWire::flush(void)
319360{
320361 rxBufferIndex = 0 ;
321362 rxBufferLength = 0 ;
363+ resetRxBuffer ();
322364 txBufferIndex = 0 ;
323365 txBufferLength = 0 ;
366+ resetTxBuffer ();
324367}
325368
326369// behind the scenes function that is called when data is received
@@ -339,9 +382,7 @@ void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes)
339382 }
340383 // copy twi rx buffer into local read buffer
341384 // this enables new reads to happen in parallel
342- for (uint8_t i = 0 ; i < numBytes; ++i){
343- rxBuffer[i] = inBytes[i];
344- }
385+ memcpy (rxBuffer, inBytes, numBytes);
345386 // set rx iterator vars
346387 rxBufferIndex = 0 ;
347388 rxBufferLength = numBytes;
@@ -377,6 +418,44 @@ void TwoWire::onRequest( void (*function)(void) )
377418 user_onRequest = function;
378419}
379420
421+ /* *
422+ * @brief Allocate the Rx/Tx buffer to the requested length if needed
423+ * @note Minimum allocated size is BUFFER_LENGTH)
424+ * @param length: number of bytes to allocate
425+ */
426+ inline void TwoWire::allocateRxBuffer (size_t length)
427+ {
428+ if (rxBufferAllocated < length) {
429+ // By default we allocate BUFFER_LENGTH bytes. It is the min size of the buffer.
430+ if (length < BUFFER_LENGTH) { length = BUFFER_LENGTH; }
431+ rxBuffer = (uint8_t *)realloc (rxBuffer, length * sizeof (uint8_t ));
432+ rxBufferAllocated = (rxBuffer != nullptr ) ? length: 0 ;
433+ }
434+ }
435+
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+ }
444+ }
445+
446+ /* *
447+ * @brief Reset Rx/Tx buffer content to 0
448+ */
449+ inline void TwoWire::resetRxBuffer (void )
450+ {
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);
457+ }
458+
380459// Preinstantiate Objects //////////////////////////////////////////////////////
381460
382461TwoWire Wire = TwoWire(); // D14-D15
0 commit comments