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 <Wire.h>
+#include <WireBuffer.h>
+#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 <Wire.h>
+#include <WireBuffer.h>
+#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 <Wire.h>
+#include <WireBuffer.h>
+#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 <Wire.h>
+#include <WireBuffer.h>
+#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 001d924df..58731f2c0 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
@@ -21,23 +21,20 @@
   Modified 2020 by Greyson Christoforo (grey@christoforo.net) to implement timeouts
 */
 
-extern "C" {
-  #include <stdlib.h>
-  #include <string.h>
-  #include <inttypes.h>
-  #include "utility/twi.h"
-}
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#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;
 
@@ -45,6 +42,8 @@ uint8_t TwoWire::transmitting = 0;
 void (*TwoWire::user_onRequest)(void);
 void (*TwoWire::user_onReceive)(int);
 
+using namespace WireBuffer;
+
 // Constructors ////////////////////////////////////////////////////////////////
 
 TwoWire::TwoWire()
@@ -154,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);
@@ -166,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
@@ -196,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
@@ -242,7 +217,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;
     }
@@ -336,7 +311,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..8c735aa6d 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 <inttypes.h>
 #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;
 
@@ -59,20 +57,32 @@ class TwoWire : public Stream
     bool getWireTimeoutFlag(void);
     void clearWireTimeoutFlag(void);
     void beginTransmission(uint8_t);
-    void beginTransmission(int);
+    inline void beginTransmission(int address) {beginTransmission(static_cast<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);
-    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);
+    inline uint8_t requestFrom(uint8_t address, uint8_t quantity) {
+      return requestFrom(static_cast<uint8_t>(address), static_cast<uint8_t>(quantity),
+          static_cast<uint8_t> (true));
+    }
+    inline uint8_t requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop) {
+      return requestFrom(static_cast<uint8_t>(address), static_cast<uint8_t>(quantity),
+          static_cast<uint32_t>(0), static_cast<uint8_t>(0), static_cast<uint8_t>(sendStop));
+    }
+    inline uint8_t requestFrom(int address, int quantity) {
+      return requestFrom(static_cast<uint8_t>(address), static_cast<uint8_t>(quantity),
+          static_cast<uint8_t>(true));
+    }
+    inline uint8_t requestFrom(int address, int quantity, int sendStop) {
+      return requestFrom(static_cast<uint8_t>(address), static_cast<uint8_t>(quantity),
+          static_cast<uint8_t>(sendStop));
+    }
+    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) );
 
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 <stdint.h>
+#include <stddef.h>
+#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 <stdint.h>
+#include <stddef.h>
+#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<rxBufferSize, txBufferSize, enableMaster, enableSlave>::M; \
+      const bufferSize_t TWI_RX_BUFFER_SIZE = sizes<rxBufferSize, txBufferSize, enableMaster, enableSlave>::RX; \
+      const bufferSize_t TWI_TX_BUFFER_SIZE = sizes<rxBufferSize, txBufferSize, enableMaster, enableSlave>::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.c b/libraries/Wire/src/utility/twi.cpp
similarity index 97%
rename from libraries/Wire/src/utility/twi.c
rename to libraries/Wire/src/utility/twi.cpp
index e09a33caf..1fba81adf 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
@@ -27,6 +27,7 @@
 #include <avr/interrupt.h>
 #include <util/delay.h>
 #include <compat/twi.h>
+#include "twiBuffer.h"
 #include "Arduino.h" // for digitalWrite and micros
 
 #ifndef cbi
@@ -40,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
@@ -58,19 +69,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 +171,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 +265,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 +354,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 +601,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 +614,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..23ca80816 100644
--- a/libraries/Wire/src/utility/twi.h
+++ b/libraries/Wire/src/utility/twi.h
@@ -19,27 +19,14 @@
   Modified 2020 by Greyson Christoforo (grey@christoforo.net) to implement timeouts
 */
 
+#pragma once
+
 #ifndef twi_h
 #define twi_h
 
   #include <inttypes.h>
-
   //#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);
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 <stdint.h>
+#include <stddef.h>
+#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 <stdint.h>
+#include <stddef.h>
+
+// 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_