From e5166fb9228eb96e9e64a13daec68dbaab21e762 Mon Sep 17 00:00:00 2001
From: Sandeep Mistry <s.mistry@arduino.cc>
Date: Mon, 18 Jan 2016 17:42:05 -0500
Subject: [PATCH] Use TX buffer for slave writes, empty on master read mode +
 DRDY IRQ

---
 cores/arduino/SERCOM.cpp |  5 +---
 libraries/Wire/Wire.cpp  | 59 ++++++++++++++++++++--------------------
 2 files changed, 30 insertions(+), 34 deletions(-)

diff --git a/cores/arduino/SERCOM.cpp b/cores/arduino/SERCOM.cpp
index d0fa4db8..3447d9dd 100644
--- a/cores/arduino/SERCOM.cpp
+++ b/cores/arduino/SERCOM.cpp
@@ -557,11 +557,8 @@ bool SERCOM::sendDataSlaveWIRE(uint8_t data)
   //Send data
   sercom->I2CS.DATA.bit.DATA = data;
 
-  //Wait data transmission successful
-  while(!sercom->I2CS.INTFLAG.bit.DRDY);
-
   //Problems on line? nack received?
-  if(sercom->I2CS.STATUS.bit.RXNACK)
+  if(!sercom->I2CS.INTFLAG.bit.DRDY || sercom->I2CS.STATUS.bit.RXNACK)
     return false;
   else
     return true;
diff --git a/libraries/Wire/Wire.cpp b/libraries/Wire/Wire.cpp
index 7857a3d0..0326bf68 100644
--- a/libraries/Wire/Wire.cpp
+++ b/libraries/Wire/Wire.cpp
@@ -153,27 +153,15 @@ uint8_t TwoWire::endTransmission()
 
 size_t TwoWire::write(uint8_t ucData)
 {
-  if(sercom->isMasterWIRE())
+  // No writing, without begun transmission or a full buffer
+  if ( !transmissionBegun || txBuffer.isFull() )
   {
-    // No writing, without begun transmission or a full buffer
-    if ( !transmissionBegun || txBuffer.isFull() )
-    {
-      return 0 ;
-    }
-
-    txBuffer.store_char( ucData ) ;
-
-    return 1 ;
-  }
-  else
-  {
-    if(sercom->sendDataSlaveWIRE( ucData ))
-    {
-      return 1;
-    }
+    return 0 ;
   }
 
-  return 0;
+  txBuffer.store_char( ucData ) ;
+
+  return 1 ;
 }
 
 size_t TwoWire::write(const uint8_t *data, size_t quantity)
@@ -246,9 +234,9 @@ void TwoWire::onService(void)
 
       if(sercom->isMasterReadOperationWIRE()) //Is a request ?
       {
-        // wait for data ready flag,
-        // before calling request callback
-        while(!sercom->isDataReadyWIRE());
+        txBuffer.clear();
+
+        transmissionBegun = true;
 
         //Calling onRequestCallback, if exists
         if(onRequestCallback)
@@ -257,18 +245,29 @@ void TwoWire::onService(void)
         }
       }
     }
-    else if(sercom->isDataReadyWIRE()) //Received data
+    else if(sercom->isDataReadyWIRE())
     {
-      if (rxBuffer.isFull()) {
-        sercom->prepareNackBitWIRE(); 
-      } else {
-        //Store data
-        rxBuffer.store_char(sercom->readDataWIRE());
+      if (sercom->isMasterReadOperationWIRE())
+      {
+        uint8_t c = 0xff;
 
-        sercom->prepareAckBitWIRE(); 
-      }
+        if( txBuffer.available() ) {
+          c = txBuffer.read_char();
+        }
 
-      sercom->prepareCommandBitsWire(0x03);
+        transmissionBegun = sercom->sendDataSlaveWIRE(c);
+      } else { //Received data
+        if (rxBuffer.isFull()) {
+          sercom->prepareNackBitWIRE(); 
+        } else {
+          //Store data
+          rxBuffer.store_char(sercom->readDataWIRE());
+
+          sercom->prepareAckBitWIRE(); 
+        }
+
+        sercom->prepareCommandBitsWire(0x03);
+      }
     }
   }
 }
-- 
GitLab