diff --git a/miosix/util/software_i2c.h b/miosix/util/software_i2c.h
index 63a0f6f333bfbeb70b4d857526a85a75f757e313..7d0e84660954f913349af63c27a22e62f125af4b 100644
--- a/miosix/util/software_i2c.h
+++ b/miosix/util/software_i2c.h
@@ -38,8 +38,9 @@ namespace miosix {
  * \param SDA SDA gpio pin. Pass a Gpio<P,N> class
  * \param SCL SCL gpio pin. Pass a Gpio<P,N> class
  * \param timeout for clock stretching, in milliseconds
+ * \param fast false=~100KHz true=~400KHz
  */
-template <typename SDA, typename SCL, unsigned stretchTimeout=50>
+template <typename SDA, typename SCL, unsigned stretchTimeout=50, bool fast=false>
 class SoftwareI2C
 {
 public:
@@ -92,8 +93,8 @@ private:
     static bool waitForClockStretching();
 };
 
-template <typename SDA, typename SCL, unsigned stretchTimeout>
-void SoftwareI2C<SDA, SCL, stretchTimeout>::init()
+template <typename SDA, typename SCL, unsigned stretchTimeout, bool fast>
+void SoftwareI2C<SDA, SCL, stretchTimeout, fast>::init()
 {
     SDA::high();
     SCL::high();
@@ -101,121 +102,121 @@ void SoftwareI2C<SDA, SCL, stretchTimeout>::init()
     SCL::mode(Mode::OPEN_DRAIN);
 }
 
-template <typename SDA, typename SCL, unsigned stretchTimeout>
-void SoftwareI2C<SDA, SCL, stretchTimeout>::sendStart()
+template <typename SDA, typename SCL, unsigned stretchTimeout, bool fast>
+void SoftwareI2C<SDA, SCL, stretchTimeout, fast>::sendStart()
 {
     SDA::low();
-    delayUs(3);
+    delayUs(fast ? 1 : 3);
     SCL::low();
-    delayUs(3);
+    delayUs(fast ? 1 : 3);
 }
 
-template <typename SDA, typename SCL, unsigned stretchTimeout>
-void SoftwareI2C<SDA, SCL, stretchTimeout>::sendRepeatedStart()
+template <typename SDA, typename SCL, unsigned stretchTimeout, bool fast>
+void SoftwareI2C<SDA, SCL, stretchTimeout, fast>::sendRepeatedStart()
 {
     SDA::high();
-    delayUs(3);
+    delayUs(fast ? 1 : 3);
     SCL::high();
-    delayUs(3);
+    delayUs(fast ? 1 : 3);
     waitForClockStretching();
     sendStart();
 }
 
-template <typename SDA, typename SCL, unsigned stretchTimeout>
-void SoftwareI2C<SDA, SCL, stretchTimeout>::sendStop()
+template <typename SDA, typename SCL, unsigned stretchTimeout, bool fast>
+void SoftwareI2C<SDA, SCL, stretchTimeout, fast>::sendStop()
 {
     SDA::low();
-    delayUs(3);
+    delayUs(fast ? 1 : 3);
     SCL::high();
-    delayUs(3);
+    delayUs(fast ? 1 : 3);
     waitForClockStretching();
     SDA::high();
-    delayUs(3);
+    delayUs(fast ? 1 : 3);
 }
 
-template <typename SDA, typename SCL, unsigned stretchTimeout>
-bool SoftwareI2C<SDA, SCL, stretchTimeout>::send(unsigned char data)
+template <typename SDA, typename SCL, unsigned stretchTimeout, bool fast>
+bool SoftwareI2C<SDA, SCL, stretchTimeout, fast>::send(unsigned char data)
 {
     for(int i=0;i<8;i++)
     {
         if(data & 0x80) SDA::high(); else SDA::low();
-        delayUs(3);
+        delayUs(fast ? 1 : 3);
         SCL::high();
         data<<=1;
-        delayUs(5);//Double delay
+        delayUs(fast ? 2 : 5);//Double delay
         waitForClockStretching();
         SCL::low();
-        delayUs(3);
+        delayUs(fast ? 1 : 3);
     }
     SDA::high();
-    delayUs(3);
+    delayUs(fast ? 1 : 3);
     SCL::high();
-    delayUs(3);
+    delayUs(fast ? 1 : 3);
     bool timeout=waitForClockStretching();
     bool result=(SDA::value()==0);
-    delayUs(3);
+    delayUs(fast ? 1 : 3);
     SCL::low();
-    delayUs(3);
+    delayUs(fast ? 1 : 3);
     return result && timeout;
 }
 
-template <typename SDA, typename SCL, unsigned stretchTimeout>
-unsigned char SoftwareI2C<SDA, SCL, stretchTimeout>::recvWithAck()
+template <typename SDA, typename SCL, unsigned stretchTimeout, bool fast>
+unsigned char SoftwareI2C<SDA, SCL, stretchTimeout, fast>::recvWithAck()
 {
     SDA::high();
     unsigned char result=0;
-    delayUs(3);
+    delayUs(fast ? 1 : 3);
     for(int i=0;i<8;i++)
     {
         result<<=1;
         
         if(SDA::value()) result |= 1;
-        delayUs(3);
+        delayUs(fast ? 1 : 3);
         SCL::high();
-        delayUs(5);//Double delay
+        delayUs(fast ? 2 : 5);//Double delay
         waitForClockStretching();
         SCL::low();
-        delayUs(3);
+        delayUs(fast ? 1 : 3);
     }
     SDA::low();
-    delayUs(3);
+    delayUs(fast ? 1 : 3);
     SCL::high();
-    delayUs(5);//Double delay
+    delayUs(fast ? 2 : 5);//Double delay
     waitForClockStretching();
     SCL::low();
-    delayUs(3);
+    delayUs(fast ? 1 : 3);
     return result;
 }
 
-template <typename SDA, typename SCL, unsigned stretchTimeout>
-unsigned char SoftwareI2C<SDA, SCL, stretchTimeout>::recvWithNack()
+template <typename SDA, typename SCL, unsigned stretchTimeout, bool fast>
+unsigned char SoftwareI2C<SDA, SCL, stretchTimeout, fast>::recvWithNack()
 {
     SDA::high();
     unsigned char result=0;
-    delayUs(3);
+    delayUs(fast ? 1 : 3);
     for(int i=0;i<8;i++)
     {
         result<<=1;
 
         if(SDA::value()) result |= 1;
-        delayUs(3);
+        delayUs(fast ? 1 : 3);
         SCL::high();
-        delayUs(5);//Double delay
+        delayUs(fast ? 2 : 5);//Double delay
         waitForClockStretching();
         SCL::low();
-        delayUs(3);
+        delayUs(fast ? 1 : 3);
     }
-    delayUs(3);
+    delayUs(fast ? 1 : 3);
     SCL::high();
-    delayUs(5);//Double delay
+    delayUs(fast ? 2 : 5);//Double delay
     waitForClockStretching();
     SCL::low();
-    delayUs(3);
+    delayUs(fast ? 1 : 3);
     return result;
 }
 
-template <typename SDA, typename SCL, unsigned stretchTimeout>
-bool SoftwareI2C<SDA, SCL, stretchTimeout>::waitForClockStretching()
+template <typename SDA, typename SCL, unsigned stretchTimeout, bool fast>
+bool SoftwareI2C<SDA, SCL, stretchTimeout, fast>::waitForClockStretching()
 {
     if(SCL::value()==1) return true;
     for(unsigned int i=0;i<stretchTimeout;i++)