From 59355fe635ff4fb720b5cde59eea70108935b741 Mon Sep 17 00:00:00 2001 From: dac1e Date: Thu, 2 Jan 2025 19:55:15 +0100 Subject: [PATCH 1/7] Renamed twi.c to twi.cpp --- libraries/Wire/src/Wire.cpp | 10 ++++------ libraries/Wire/src/utility/{twi.c => twi.cpp} | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) rename libraries/Wire/src/utility/{twi.c => twi.cpp} (99%) diff --git a/libraries/Wire/src/Wire.cpp b/libraries/Wire/src/Wire.cpp index 001d924df..7c45eb366 100644 --- a/libraries/Wire/src/Wire.cpp +++ b/libraries/Wire/src/Wire.cpp @@ -21,12 +21,10 @@ Modified 2020 by Greyson Christoforo (grey@christoforo.net) to implement timeouts */ -extern "C" { - #include - #include - #include - #include "utility/twi.h" -} +#include +#include +#include +#include "utility/twi.h" #include "Wire.h" diff --git a/libraries/Wire/src/utility/twi.c b/libraries/Wire/src/utility/twi.cpp similarity index 99% rename from libraries/Wire/src/utility/twi.c rename to libraries/Wire/src/utility/twi.cpp index e09a33caf..953dcec56 100644 --- a/libraries/Wire/src/utility/twi.c +++ b/libraries/Wire/src/utility/twi.cpp @@ -1,5 +1,5 @@ /* - twi.c - TWI/I2C library for Wiring & Arduino + twi.cpp - TWI/I2C library for Wiring & Arduino Copyright (c) 2006 Nicholas Zambetti. All right reserved. This library is free software; you can redistribute it and/or From 56ef4a4c1ea74fd1bfa52ae4940d94d4a28bb586 Mon Sep 17 00:00:00 2001 From: dac1e Date: Thu, 2 Jan 2025 20:05:42 +0100 Subject: [PATCH 2/7] Make Wire and twi buffers weak and allow to override by macro SET_Wire_Buffers(). --- .../master_reader_custombuffer.ino | 59 +++++++++++++++++ .../master_writer_custombuffer.ino | 56 +++++++++++++++++ .../slave_receiver_custombuffer.ino | 63 +++++++++++++++++++ .../slave_sender_custombuffer.ino | 55 ++++++++++++++++ libraries/Wire/src/Wire.cpp | 15 ++--- libraries/Wire/src/Wire.h | 8 +-- libraries/Wire/src/WireBuffer.cpp | 30 +++++++++ libraries/Wire/src/WireBuffer.h | 57 +++++++++++++++++ libraries/Wire/src/utility/twi.cpp | 16 ++--- libraries/Wire/src/utility/twi.h | 19 ++++-- libraries/Wire/src/utility/twiBuffer.cpp | 33 ++++++++++ libraries/Wire/src/utility/twiBuffer.h | 63 +++++++++++++++++++ 12 files changed, 448 insertions(+), 26 deletions(-) create mode 100644 libraries/Wire/examples/master_reader_custombuffer/master_reader_custombuffer.ino create mode 100644 libraries/Wire/examples/master_writer_custombuffer/master_writer_custombuffer.ino create mode 100644 libraries/Wire/examples/slave_receiver_custombuffer/slave_receiver_custombuffer.ino create mode 100644 libraries/Wire/examples/slave_sender_custombuffer/slave_sender_custombuffer.ino create mode 100644 libraries/Wire/src/WireBuffer.cpp create mode 100644 libraries/Wire/src/WireBuffer.h create mode 100644 libraries/Wire/src/utility/twiBuffer.cpp create mode 100644 libraries/Wire/src/utility/twiBuffer.h diff --git a/libraries/Wire/examples/master_reader_custombuffer/master_reader_custombuffer.ino b/libraries/Wire/examples/master_reader_custombuffer/master_reader_custombuffer.ino new file mode 100644 index 000000000..898cfb23a --- /dev/null +++ b/libraries/Wire/examples/master_reader_custombuffer/master_reader_custombuffer.ino @@ -0,0 +1,59 @@ +// Wire Master Reader Custom Buffer + +// Demonstrates use of the Wire library with customized buffers +// Reads data from an I2C/TWI slave device +// Refer to the "Wire Slave Sender Custom Buffer" example for use with this + +// Created 31 Dec 2024 + +// This example code is in the public domain. + + +#include +#include +#include "Arduino.h" + +// request 6 bytes from slave device #8 +constexpr size_t REQUESTED_BYTE_COUNT = 6; + +constexpr size_t RECEIVE_BUFFER_SIZE = REQUESTED_BYTE_COUNT; +constexpr size_t TRANSMIT_BUFFER_SIZE = 0; // There is no transmit in this sketch. + +SET_Wire_BUFFERS(RECEIVE_BUFFER_SIZE, TRANSMIT_BUFFER_SIZE, + true /* master buffers needed */, false /* no slave buffers needed */ ); + +void setup() { + Wire.begin(); // join I2C bus (address optional for master) + Serial.begin(9600); // start serial for output + + // This is just for curiosity and could be removed + printWireBufferSize(Serial); +} + +void loop() { + Wire.requestFrom(8, REQUESTED_BYTE_COUNT); + + size_t count = 0; + while (Wire.available()) { // slave may send less than requested + ++count; + char c = Wire.read(); // receive a byte as character + Serial.print(c); // print the character + } + if(count) { + Serial.println(); + } + delay(500); +} + +void printWireBufferSize(Stream& stream) { + stream.print("Wire receive buffer size is "); + stream.println(WireBuffer::RX_BUFFER_SIZE); + stream.print("Wire transmit buffer size is "); + stream.println(WireBuffer::TX_BUFFER_SIZE); + stream.print("twi_masterBuffer size is "); + stream.println(twiBuffer::TWI_MASTER_BUFFER_SIZE); + stream.print("twi_rxBuffer size is "); + stream.println(twiBuffer::TWI_RX_BUFFER_SIZE); + stream.print("twi_txBuffer size is "); + stream.println(twiBuffer::TWI_TX_BUFFER_SIZE); +} diff --git a/libraries/Wire/examples/master_writer_custombuffer/master_writer_custombuffer.ino b/libraries/Wire/examples/master_writer_custombuffer/master_writer_custombuffer.ino new file mode 100644 index 000000000..70343bf92 --- /dev/null +++ b/libraries/Wire/examples/master_writer_custombuffer/master_writer_custombuffer.ino @@ -0,0 +1,56 @@ +// Wire Master Writer Custom Buffer + +// Demonstrates use of the Wire library with customized buffers +// Writes data to an I2C/TWI slave device +// Refer to the "Wire Slave Receiver Custom Buffer" example for use with this + +// Created 31 Dec 2024 + +// This example code is in the public domain. + + +#include +#include +#include "Arduino.h" + +// The following text will not fit into the default buffer of 32 bytes. +static const char text[] = "You really won't believe it, but x is "; + +constexpr size_t RECEIVE_BUFFER_SIZE = 0; // There is no receive in this sketch. +constexpr size_t TRANSMIT_BUFFER_SIZE = 42; // Enhance the buffer to 42 characters. + +SET_Wire_BUFFERS(RECEIVE_BUFFER_SIZE, TRANSMIT_BUFFER_SIZE, + true /* master buffers needed */, false /* no slave buffers needed */ ); + +void setup() { + Wire.begin(); // join I2C bus (address optional for master) + + // This is just for curiosity and could be removed + Serial.begin(9600); // start serial for output + printWireBufferSize(Serial); +} + +static byte x = 0; + +void loop() { + Wire.beginTransmission(8); // transmit to device #8 + Wire.write(text); // sends multiple bytes + Wire.write(x); // sends one byte + Wire.endTransmission(); // stop transmitting + + x++; + delay(500); +} + +void printWireBufferSize(Stream& stream) { + stream.print("Wire receive buffer size is "); + stream.println(WireBuffer::RX_BUFFER_SIZE); + stream.print("Wire transmit buffer size is "); + stream.println(WireBuffer::TX_BUFFER_SIZE); + stream.print("twi_masterBuffer size is "); + stream.println(twiBuffer::TWI_MASTER_BUFFER_SIZE); + stream.print("twi_rxBuffer size is "); + stream.println(twiBuffer::TWI_RX_BUFFER_SIZE); + stream.print("twi_txBuffer size is "); + stream.println(twiBuffer::TWI_TX_BUFFER_SIZE); +} diff --git a/libraries/Wire/examples/slave_receiver_custombuffer/slave_receiver_custombuffer.ino b/libraries/Wire/examples/slave_receiver_custombuffer/slave_receiver_custombuffer.ino new file mode 100644 index 000000000..3b4345953 --- /dev/null +++ b/libraries/Wire/examples/slave_receiver_custombuffer/slave_receiver_custombuffer.ino @@ -0,0 +1,63 @@ +// Wire Slave Receiver Custom Buffer + +// Demonstrates use of the Wire library with customized buffers +// Receives data as an I2C/TWI slave device +// Refer to the "Wire Master Writer Custom Buffer" example for use with this + +// Created 31 Dec 2024 + +// This example code is in the public domain. + + +#include +#include +#include "Arduino.h" + +constexpr size_t RECEIVE_BUFFER_SIZE = 42; // Be able receive up to 42 characters in one message. +constexpr size_t TRANSMIT_BUFFER_SIZE = 0; // There is no transmit in this sketch. + +SET_Wire_BUFFERS(RECEIVE_BUFFER_SIZE, TRANSMIT_BUFFER_SIZE, + false /* no master buffers needed */, true /* slave buffers needed */ ); + +void setup() { + Wire.begin(8); // join I2C bus with address #8 + Wire.onReceive(receiveEvent); // register event + Serial.begin(9600); // start serial for output + + // This is just for curiosity and could be removed + printWireBufferSize(Serial); +} + +void loop() { + delay(100); +} + +// function that executes whenever data is received from master +// this function is registered as an event, see setup() +// +// Hint: This function is called within an interrupt context. +// That means, that there must be enough space in the Serial output +// buffer for the characters to be printed. Otherwise the +// Serial.print() call will lock up. +void receiveEvent(int howMany) { + while (1 < Wire.available()) { // loop through all but the last + const char c = Wire.read(); // receive byte as a character + Serial.print(c); // print the character + } + const int x = Wire.read(); // receive byte as an integer + Serial.println(x); // print the integer +} + +void printWireBufferSize(Stream& stream) { + stream.print("Wire receive buffer size is "); + stream.println(WireBuffer::RX_BUFFER_SIZE); + stream.print("Wire transmit buffer size is "); + stream.println(WireBuffer::TX_BUFFER_SIZE); + stream.print("twi_masterBuffer size is "); + stream.println(twiBuffer::TWI_MASTER_BUFFER_SIZE); + stream.print("twi_rxBuffer size is "); + stream.println(twiBuffer::TWI_RX_BUFFER_SIZE); + stream.print("twi_txBuffer size is "); + stream.println(twiBuffer::TWI_TX_BUFFER_SIZE); + delay(250); // Give time to free up Serial output buffer. +} diff --git a/libraries/Wire/examples/slave_sender_custombuffer/slave_sender_custombuffer.ino b/libraries/Wire/examples/slave_sender_custombuffer/slave_sender_custombuffer.ino new file mode 100644 index 000000000..51a763a19 --- /dev/null +++ b/libraries/Wire/examples/slave_sender_custombuffer/slave_sender_custombuffer.ino @@ -0,0 +1,55 @@ +// Wire Slave Sender Custom Buffer + +// Demonstrates use of the Wire library with customized buffers +// Sends data as an I2C/TWI slave device +// Refer to the "Wire Master Reader Custom Buffer" example for use with this + +// Created 31 Dec 2024 + +// This example code is in the public domain. + + +#include +#include +#include "Arduino.h" + +static const char text[] = "hello "; // respond with message of 6 bytes + +constexpr size_t RECEIVE_BUFFER_SIZE = 0; // There is no receive in this sketch. +constexpr size_t TRANSMIT_BUFFER_SIZE = sizeof(text)-1; // Don't need a byte for the \0 + +SET_Wire_BUFFERS(RECEIVE_BUFFER_SIZE, TRANSMIT_BUFFER_SIZE, + false /* no master buffers needed */, true /* slave buffers needed */ ); + +void setup() { + Wire.begin(8); // join I2C bus with address #8 + Wire.onRequest(requestEvent); // register event + + // This is just for curiosity and could be removed + Serial.begin(9600); + printWireBufferSize(Serial); +} + +void loop() { + delay(100); +} + +// function that executes whenever data is requested by master +// this function is registered as an event, see setup() +void requestEvent() { + Wire.write(text); + // as expected by master +} + +void printWireBufferSize(Stream& stream) { + stream.print("Wire receive buffer size is "); + stream.println(WireBuffer::RX_BUFFER_SIZE); + stream.print("Wire transmit buffer size is "); + stream.println(WireBuffer::TX_BUFFER_SIZE); + stream.print("twi_masterBuffer size is "); + stream.println(twiBuffer::TWI_MASTER_BUFFER_SIZE); + stream.print("twi_rxBuffer size is "); + stream.println(twiBuffer::TWI_RX_BUFFER_SIZE); + stream.print("twi_txBuffer size is "); + stream.println(twiBuffer::TWI_TX_BUFFER_SIZE); +} diff --git a/libraries/Wire/src/Wire.cpp b/libraries/Wire/src/Wire.cpp index 7c45eb366..f5281c0ce 100644 --- a/libraries/Wire/src/Wire.cpp +++ b/libraries/Wire/src/Wire.cpp @@ -1,5 +1,5 @@ /* - TwoWire.cpp - TWI/I2C library for Wiring & Arduino + Wire.cpp - TWI/I2C library for Wiring & Arduino Copyright (c) 2006 Nicholas Zambetti. All right reserved. This library is free software; you can redistribute it and/or @@ -26,16 +26,15 @@ #include #include "utility/twi.h" +#include "WireBuffer.h" #include "Wire.h" // Initialize Class Variables ////////////////////////////////////////////////// -uint8_t TwoWire::rxBuffer[BUFFER_LENGTH]; uint8_t TwoWire::rxBufferIndex = 0; uint8_t TwoWire::rxBufferLength = 0; uint8_t TwoWire::txAddress = 0; -uint8_t TwoWire::txBuffer[BUFFER_LENGTH]; uint8_t TwoWire::txBufferIndex = 0; uint8_t TwoWire::txBufferLength = 0; @@ -43,6 +42,8 @@ uint8_t TwoWire::transmitting = 0; void (*TwoWire::user_onRequest)(void); void (*TwoWire::user_onReceive)(int); +using namespace WireBuffer; + // Constructors //////////////////////////////////////////////////////////////// TwoWire::TwoWire() @@ -152,8 +153,8 @@ uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddres } // clamp to buffer length - if(quantity > BUFFER_LENGTH){ - quantity = BUFFER_LENGTH; + if(quantity > RX_BUFFER_SIZE){ + quantity = RX_BUFFER_SIZE; } // perform blocking read into buffer uint8_t read = twi_readFrom(address, rxBuffer, quantity, sendStop); @@ -240,7 +241,7 @@ size_t TwoWire::write(uint8_t data) if(transmitting){ // in master transmitter mode // don't bother if buffer is full - if(txBufferLength >= BUFFER_LENGTH){ + if(txBufferLength >= TX_BUFFER_SIZE){ setWriteError(); return 0; } @@ -334,7 +335,7 @@ void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes) // copy twi rx buffer into local read buffer // this enables new reads to happen in parallel for(uint8_t i = 0; i < numBytes; ++i){ - rxBuffer[i] = inBytes[i]; + rxBuffer[i] = inBytes[i]; } // set rx iterator vars rxBufferIndex = 0; diff --git a/libraries/Wire/src/Wire.h b/libraries/Wire/src/Wire.h index e70d72edb..849dc5027 100644 --- a/libraries/Wire/src/Wire.h +++ b/libraries/Wire/src/Wire.h @@ -1,5 +1,5 @@ /* - TwoWire.h - TWI/I2C library for Arduino & Wiring + Wire.h - TWI/I2C library for Arduino & Wiring Copyright (c) 2006 Nicholas Zambetti. All right reserved. This library is free software; you can redistribute it and/or @@ -20,26 +20,24 @@ Modified 2020 by Greyson Christoforo (grey@christoforo.net) to implement timeouts */ +#pragma once + #ifndef TwoWire_h #define TwoWire_h #include #include "Stream.h" -#define BUFFER_LENGTH 32 - // WIRE_HAS_END means Wire has end() #define WIRE_HAS_END 1 class TwoWire : public Stream { private: - static uint8_t rxBuffer[]; static uint8_t rxBufferIndex; static uint8_t rxBufferLength; static uint8_t txAddress; - static uint8_t txBuffer[]; static uint8_t txBufferIndex; static uint8_t txBufferLength; diff --git a/libraries/Wire/src/WireBuffer.cpp b/libraries/Wire/src/WireBuffer.cpp new file mode 100644 index 000000000..552e7cdab --- /dev/null +++ b/libraries/Wire/src/WireBuffer.cpp @@ -0,0 +1,30 @@ +/* + WireBuffer.cpp - TWI/I2C library for Arduino & Wiring + Copyright (c) 2006 Nicholas Zambetti. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#include "WireBuffer.h" + +// Default buffers as weak buffers +namespace WireBuffer { + extern __attribute__((weak)) const bufferSize_t TX_BUFFER_SIZE = WIRE_BUFFER_DEFAULT_SIZE; + extern __attribute__((weak)) const bufferSize_t RX_BUFFER_SIZE = WIRE_BUFFER_DEFAULT_SIZE; + __attribute__((weak)) uint8_t rxBuffer[WIRE_BUFFER_DEFAULT_SIZE]; + __attribute__((weak)) uint8_t txBuffer[WIRE_BUFFER_DEFAULT_SIZE]; +} diff --git a/libraries/Wire/src/WireBuffer.h b/libraries/Wire/src/WireBuffer.h new file mode 100644 index 000000000..6e5532b3c --- /dev/null +++ b/libraries/Wire/src/WireBuffer.h @@ -0,0 +1,57 @@ +/* + WireBuffer.h - TWI/I2C library for Arduino & Wiring + Copyright (c) 2006 Nicholas Zambetti. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#pragma once + +#ifndef Wire_WireBuffer_h_ +#define Wire_WireBuffer_h_ + +#include +#include +#include "utility/twiBuffer.h" + +// Use extra namespace to avoid collision with other symbols +namespace WireBuffer { + // Declare twi buffers + typedef size_t bufferSize_t; + constexpr bufferSize_t WIRE_BUFFER_DEFAULT_SIZE = twiBuffer::TWI_DEFAULT_BUFFER_SIZE; + extern const bufferSize_t RX_BUFFER_SIZE; + extern const bufferSize_t TX_BUFFER_SIZE; + extern uint8_t rxBuffer[]; + extern uint8_t txBuffer[]; +} + +#define SET_Wire_BUFFERS(rxBufferSize, txBufferSize, enableMaster, enableSlave) \ + namespace twiBuffer { \ + const bufferSize_t TWI_MASTER_BUFFER_SIZE = sizes::M; \ + const bufferSize_t TWI_RX_BUFFER_SIZE = sizes::RX; \ + const bufferSize_t TWI_TX_BUFFER_SIZE = sizes::TX; \ + uint8_t twi_masterBuffer[TWI_MASTER_BUFFER_SIZE]; \ + uint8_t twi_rxBuffer[TWI_RX_BUFFER_SIZE]; \ + uint8_t twi_txBuffer[TWI_TX_BUFFER_SIZE]; \ + } \ + namespace WireBuffer { \ + const bufferSize_t TX_BUFFER_SIZE = txBufferSize; \ + const bufferSize_t RX_BUFFER_SIZE = rxBufferSize; \ + uint8_t rxBuffer[rxBufferSize]; \ + uint8_t txBuffer[txBufferSize]; \ + } + + +#endif /* Wire_WireBuffer_h_ */ diff --git a/libraries/Wire/src/utility/twi.cpp b/libraries/Wire/src/utility/twi.cpp index 953dcec56..470b18b86 100644 --- a/libraries/Wire/src/utility/twi.cpp +++ b/libraries/Wire/src/utility/twi.cpp @@ -27,6 +27,7 @@ #include #include #include +#include "twiBuffer.h" #include "Arduino.h" // for digitalWrite and micros #ifndef cbi @@ -58,19 +59,18 @@ static volatile bool twi_do_reset_on_timeout = false; // reset the TWI register static void (*twi_onSlaveTransmit)(void); static void (*twi_onSlaveReceive)(uint8_t*, int); -static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH]; static volatile uint8_t twi_masterBufferIndex; static volatile uint8_t twi_masterBufferLength; -static uint8_t twi_txBuffer[TWI_BUFFER_LENGTH]; static volatile uint8_t twi_txBufferIndex; static volatile uint8_t twi_txBufferLength; -static uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH]; static volatile uint8_t twi_rxBufferIndex; static volatile uint8_t twi_error; +using namespace twiBuffer; + /* * Function twi_init * Desc readys twi pins and sets twi bitrate @@ -161,7 +161,7 @@ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sen uint8_t i; // ensure data will fit into buffer - if(TWI_BUFFER_LENGTH < length){ + if(TWI_MASTER_BUFFER_SIZE < length){ return 0; } @@ -255,7 +255,7 @@ uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait uint8_t i; // ensure data will fit into buffer - if(TWI_BUFFER_LENGTH < length){ + if(TWI_MASTER_BUFFER_SIZE < length){ return 1; } @@ -344,7 +344,7 @@ uint8_t twi_transmit(const uint8_t* data, uint8_t length) uint8_t i; // ensure data will fit into buffer - if(TWI_BUFFER_LENGTH < (twi_txBufferLength+length)){ + if(TWI_TX_BUFFER_SIZE < (twi_txBufferLength+length)){ return 1; } @@ -591,7 +591,7 @@ ISR(TWI_vect) case TW_SR_DATA_ACK: // data received, returned ack case TW_SR_GCALL_DATA_ACK: // data received generally, returned ack // if there is still room in the rx buffer - if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){ + if(twi_rxBufferIndex < TWI_RX_BUFFER_SIZE){ // put byte in buffer and ack twi_rxBuffer[twi_rxBufferIndex++] = TWDR; twi_reply(1); @@ -604,7 +604,7 @@ ISR(TWI_vect) // ack future responses and leave slave receiver state twi_releaseBus(); // put a null char after data if there's room - if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){ + if(twi_rxBufferIndex < TWI_RX_BUFFER_SIZE){ twi_rxBuffer[twi_rxBufferIndex] = '\0'; } // callback to user defined callback diff --git a/libraries/Wire/src/utility/twi.h b/libraries/Wire/src/utility/twi.h index 85b983794..37113771e 100644 --- a/libraries/Wire/src/utility/twi.h +++ b/libraries/Wire/src/utility/twi.h @@ -19,27 +19,25 @@ Modified 2020 by Greyson Christoforo (grey@christoforo.net) to implement timeouts */ +#pragma once + #ifndef twi_h #define twi_h #include - //#define ATMEGA8 #ifndef TWI_FREQ #define TWI_FREQ 100000L #endif - #ifndef TWI_BUFFER_LENGTH - #define TWI_BUFFER_LENGTH 32 - #endif - #define TWI_READY 0 #define TWI_MRX 1 #define TWI_MTX 2 #define TWI_SRX 3 #define TWI_STX 4 - + + void twi_init(void); void twi_disable(void); void twi_setAddress(uint8_t); @@ -56,4 +54,13 @@ void twi_handleTimeout(bool); bool twi_manageTimeoutFlag(bool); +#if DEBUG_TWI_BUFFER + size_t twi_getMasterBufferSize(); + size_t twi_getMasterBuffer(); + size_t twi_getRxBufferSize(); + size_t twi_getRxBuffer(); + size_t twi_getTxBufferSize(); + size_t twi_getTxBuffer(); +#endif + #endif diff --git a/libraries/Wire/src/utility/twiBuffer.cpp b/libraries/Wire/src/utility/twiBuffer.cpp new file mode 100644 index 000000000..d032cc0aa --- /dev/null +++ b/libraries/Wire/src/utility/twiBuffer.cpp @@ -0,0 +1,33 @@ +/* + twiBuffer.cpp - TWI/I2C library for Arduino & Wiring + Copyright (c) 2006 Nicholas Zambetti. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#include "twiBuffer.h" + +// Default buffers as weak buffers +namespace twiBuffer { \ + extern __attribute__((weak)) const bufferSize_t TWI_MASTER_BUFFER_SIZE = TWI_DEFAULT_BUFFER_SIZE; + extern __attribute__((weak)) const bufferSize_t TWI_TX_BUFFER_SIZE = TWI_DEFAULT_BUFFER_SIZE; + extern __attribute__((weak)) const bufferSize_t TWI_RX_BUFFER_SIZE = TWI_DEFAULT_BUFFER_SIZE; + __attribute__((weak)) uint8_t twi_masterBuffer[TWI_DEFAULT_BUFFER_SIZE]; + __attribute__((weak)) uint8_t twi_txBuffer[TWI_DEFAULT_BUFFER_SIZE]; + __attribute__((weak)) uint8_t twi_rxBuffer[TWI_DEFAULT_BUFFER_SIZE]; +} + diff --git a/libraries/Wire/src/utility/twiBuffer.h b/libraries/Wire/src/utility/twiBuffer.h new file mode 100644 index 000000000..514f60616 --- /dev/null +++ b/libraries/Wire/src/utility/twiBuffer.h @@ -0,0 +1,63 @@ +/* + twiBuffer.h - TWI/I2C library for Arduino & Wiring + Copyright (c) 2006 Nicholas Zambetti. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#pragma once + +#ifndef twi_twiBuffer_h_ +#define twi_twiBuffer_h_ + +#include +#include + +// Use extra namespace to avoid collision with other symbols +namespace twiBuffer { + typedef size_t bufferSize_t; + + // Template struct calculating twi buffer sizes. + template< + size_t RX_SIZE, // Receive buffer size. May be zero, if only transmitting data is needed + size_t TX_SIZE, // Transmit buffer size. May be zero, if only receiving data is needed + bool ENABLE_MASTER, // If master is disabled, it will save twi master buffer space + bool ENABLE_SLAVE // If slave is disabled, it will save twi slave buffer space + > + struct sizes { + static_assert(ENABLE_MASTER == true || ENABLE_SLAVE == true, "You should not disable master and slave together."); + + // twi master capacity becomes max of RX_SIZE, TX_SIZE + static constexpr twiBuffer::bufferSize_t TWI_MASTER_BUFFER_SIZE = RX_SIZE > TX_SIZE ? RX_SIZE : TX_SIZE; + + // Set the twi master buffer capacity to 0, if master mode isn't needed. + static constexpr twiBuffer::bufferSize_t M = ENABLE_MASTER ? TWI_MASTER_BUFFER_SIZE : 0; + + // Set the twi slave buffers capacity to 0, if slave mode isn't needed. + static constexpr twiBuffer::bufferSize_t RX = ENABLE_SLAVE ? RX_SIZE : 0; + static constexpr twiBuffer::bufferSize_t TX = ENABLE_SLAVE ? TX_SIZE : 0; + }; + + // Declare twi buffers + constexpr bufferSize_t TWI_DEFAULT_BUFFER_SIZE = 32; + extern uint8_t twi_masterBuffer[]; + extern const bufferSize_t TWI_MASTER_BUFFER_SIZE; + extern uint8_t twi_rxBuffer[]; + extern const bufferSize_t TWI_RX_BUFFER_SIZE; + extern uint8_t twi_txBuffer[]; + extern const bufferSize_t TWI_TX_BUFFER_SIZE; +} + +#endif twi_twiBuffer_h_ From cb707b8414a31c89744fae497d99850c004522ab Mon Sep 17 00:00:00 2001 From: dac1e Date: Fri, 3 Jan 2025 12:35:18 +0100 Subject: [PATCH 3/7] Moved macros from twi.h to twi.cpp. Placed TWI states in enum TWI_STATE : uint8_t. --- libraries/Wire/src/utility/twi.cpp | 12 +++++++++++- libraries/Wire/src/utility/twi.h | 11 ----------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/libraries/Wire/src/utility/twi.cpp b/libraries/Wire/src/utility/twi.cpp index 470b18b86..1fba81adf 100644 --- a/libraries/Wire/src/utility/twi.cpp +++ b/libraries/Wire/src/utility/twi.cpp @@ -41,7 +41,17 @@ #include "pins_arduino.h" #include "twi.h" -static volatile uint8_t twi_state; +constexpr uint32_t TWI_FREQ = 100000L; + +enum TWI_STATE : uint8_t { + TWI_READY = 0, + TWI_MRX = 1, + TWI_MTX = 2, + TWI_SRX = 3, + TWI_STX = 4, +}; + +static volatile TWI_STATE twi_state; static volatile uint8_t twi_slarw; static volatile uint8_t twi_sendStop; // should the transaction end with a stop static volatile uint8_t twi_inRepStart; // in the middle of a repeated start diff --git a/libraries/Wire/src/utility/twi.h b/libraries/Wire/src/utility/twi.h index 37113771e..3a9a51367 100644 --- a/libraries/Wire/src/utility/twi.h +++ b/libraries/Wire/src/utility/twi.h @@ -27,17 +27,6 @@ #include //#define ATMEGA8 - #ifndef TWI_FREQ - #define TWI_FREQ 100000L - #endif - - #define TWI_READY 0 - #define TWI_MRX 1 - #define TWI_MTX 2 - #define TWI_SRX 3 - #define TWI_STX 4 - - void twi_init(void); void twi_disable(void); void twi_setAddress(uint8_t); From 7d5eae1bb7aa57cb159f95eaf22d28f417c5779a Mon Sep 17 00:00:00 2001 From: dac1e Date: Fri, 3 Jan 2025 12:40:55 +0100 Subject: [PATCH 4/7] Moved Wire api functions that do just type cast from .cpp file to .h file. --- libraries/Wire/src/Wire.cpp | 24 ------------------------ libraries/Wire/src/Wire.h | 22 +++++++++++++++++----- 2 files changed, 17 insertions(+), 29 deletions(-) diff --git a/libraries/Wire/src/Wire.cpp b/libraries/Wire/src/Wire.cpp index f5281c0ce..58731f2c0 100644 --- a/libraries/Wire/src/Wire.cpp +++ b/libraries/Wire/src/Wire.cpp @@ -165,25 +165,6 @@ uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddres return read; } -uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop) { - return requestFrom((uint8_t)address, (uint8_t)quantity, (uint32_t)0, (uint8_t)0, (uint8_t)sendStop); -} - -uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity) -{ - return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true); -} - -uint8_t TwoWire::requestFrom(int address, int quantity) -{ - return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true); -} - -uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop) -{ - return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)sendStop); -} - void TwoWire::beginTransmission(uint8_t address) { // indicate that we are transmitting @@ -195,11 +176,6 @@ void TwoWire::beginTransmission(uint8_t address) txBufferLength = 0; } -void TwoWire::beginTransmission(int address) -{ - beginTransmission((uint8_t)address); -} - // // Originally, 'endTransmission' was an f(void) function. // It has been modified to take one parameter indicating diff --git a/libraries/Wire/src/Wire.h b/libraries/Wire/src/Wire.h index 849dc5027..6e6d83876 100644 --- a/libraries/Wire/src/Wire.h +++ b/libraries/Wire/src/Wire.h @@ -57,14 +57,26 @@ class TwoWire : public Stream bool getWireTimeoutFlag(void); void clearWireTimeoutFlag(void); void beginTransmission(uint8_t); - void beginTransmission(int); + void beginTransmission(int address) {beginTransmission((uint8_t) (address));} uint8_t endTransmission(void); uint8_t endTransmission(uint8_t); - uint8_t requestFrom(uint8_t, uint8_t); - uint8_t requestFrom(uint8_t, uint8_t, uint8_t); uint8_t requestFrom(uint8_t, uint8_t, uint32_t, uint8_t, uint8_t); - uint8_t requestFrom(int, int); - uint8_t requestFrom(int, int, int); + uint8_t requestFrom(uint8_t address, uint8_t quantity) { + return requestFrom((uint8_t) (address), (uint8_t) (quantity), + (uint8_t) (true)); + } + uint8_t requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop) { + return requestFrom((uint8_t) (address), (uint8_t) (quantity), + (uint32_t) (0), (uint8_t) (0), (uint8_t) (sendStop)); + } + uint8_t requestFrom(int address, int quantity) { + return requestFrom((uint8_t) (address), (uint8_t) (quantity), + (uint8_t) (true)); + } + uint8_t requestFrom(int address, int quantity, int sendStop) { + return requestFrom((uint8_t) (address), (uint8_t) (quantity), + (uint8_t) (sendStop)); + } virtual size_t write(uint8_t); virtual size_t write(const uint8_t *, size_t); virtual int available(void); From c1eaa792574b1647cadee93e93d60d5c4618139a Mon Sep 17 00:00:00 2001 From: dac1e Date: Fri, 3 Jan 2025 12:44:36 +0100 Subject: [PATCH 5/7] Use C++ static_cast instead of C cast. --- libraries/Wire/src/Wire.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/libraries/Wire/src/Wire.h b/libraries/Wire/src/Wire.h index 6e6d83876..2103529af 100644 --- a/libraries/Wire/src/Wire.h +++ b/libraries/Wire/src/Wire.h @@ -57,25 +57,25 @@ class TwoWire : public Stream bool getWireTimeoutFlag(void); void clearWireTimeoutFlag(void); void beginTransmission(uint8_t); - void beginTransmission(int address) {beginTransmission((uint8_t) (address));} + inline void beginTransmission(int address) {beginTransmission(static_cast (address));} uint8_t endTransmission(void); uint8_t endTransmission(uint8_t); uint8_t requestFrom(uint8_t, uint8_t, uint32_t, uint8_t, uint8_t); - uint8_t requestFrom(uint8_t address, uint8_t quantity) { - return requestFrom((uint8_t) (address), (uint8_t) (quantity), - (uint8_t) (true)); + inline uint8_t requestFrom(uint8_t address, uint8_t quantity) { + return requestFrom(static_cast(address), static_cast(quantity), + static_cast (true)); } - uint8_t requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop) { - return requestFrom((uint8_t) (address), (uint8_t) (quantity), - (uint32_t) (0), (uint8_t) (0), (uint8_t) (sendStop)); + inline uint8_t requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop) { + return requestFrom(static_cast(address), static_cast(quantity), + static_cast(0), static_cast(0), static_cast(sendStop)); } - uint8_t requestFrom(int address, int quantity) { - return requestFrom((uint8_t) (address), (uint8_t) (quantity), - (uint8_t) (true)); + inline uint8_t requestFrom(int address, int quantity) { + return requestFrom(static_cast(address), static_cast(quantity), + static_cast(true)); } - uint8_t requestFrom(int address, int quantity, int sendStop) { - return requestFrom((uint8_t) (address), (uint8_t) (quantity), - (uint8_t) (sendStop)); + inline uint8_t requestFrom(int address, int quantity, int sendStop) { + return requestFrom(static_cast(address), static_cast(quantity), + static_cast(sendStop)); } virtual size_t write(uint8_t); virtual size_t write(const uint8_t *, size_t); From b9df583c3576329ad0a2d21413440001dc82a1ec Mon Sep 17 00:00:00 2001 From: dac1e Date: Fri, 3 Jan 2025 12:47:40 +0100 Subject: [PATCH 6/7] Use override specifier in Wire.h --- libraries/Wire/src/Wire.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/Wire/src/Wire.h b/libraries/Wire/src/Wire.h index 2103529af..8c735aa6d 100644 --- a/libraries/Wire/src/Wire.h +++ b/libraries/Wire/src/Wire.h @@ -77,12 +77,12 @@ class TwoWire : public Stream return requestFrom(static_cast(address), static_cast(quantity), static_cast(sendStop)); } - virtual size_t write(uint8_t); - virtual size_t write(const uint8_t *, size_t); - virtual int available(void); - virtual int read(void); - virtual int peek(void); - virtual void flush(void); + size_t write(uint8_t) override; + size_t write(const uint8_t *, size_t) override; + int available(void) override; + int read(void) override; + int peek(void) override; + void flush(void) override; void onReceive( void (*)(int) ); void onRequest( void (*)(void) ); From 4962837e9c67c3232df4a34d781813284c7c64cd Mon Sep 17 00:00:00 2001 From: dac1e Date: Sat, 4 Jan 2025 10:12:26 +0100 Subject: [PATCH 7/7] Deleted obsolete debug code. --- libraries/Wire/src/utility/twi.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/libraries/Wire/src/utility/twi.h b/libraries/Wire/src/utility/twi.h index 3a9a51367..23ca80816 100644 --- a/libraries/Wire/src/utility/twi.h +++ b/libraries/Wire/src/utility/twi.h @@ -43,13 +43,4 @@ void twi_handleTimeout(bool); bool twi_manageTimeoutFlag(bool); -#if DEBUG_TWI_BUFFER - size_t twi_getMasterBufferSize(); - size_t twi_getMasterBuffer(); - size_t twi_getRxBufferSize(); - size_t twi_getRxBuffer(); - size_t twi_getTxBufferSize(); - size_t twi_getTxBuffer(); -#endif - #endif