From b993249630e6d67cd543cb69391170d6d2576942 Mon Sep 17 00:00:00 2001 From: William Date: Mon, 9 Nov 2015 22:57:08 -0800 Subject: [PATCH 1/3] Add I2C Repeated Start Capability Adjust requestFrom, endTransmission, and startTransmissionWire to handle repeated starts --- cores/arduino/SERCOM.cpp | 7 ++++++- cores/arduino/SERCOM.h | 1 + libraries/Wire/Wire.cpp | 18 ++++++++++++++---- libraries/Wire/Wire.h | 3 ++- 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/cores/arduino/SERCOM.cpp b/cores/arduino/SERCOM.cpp index b88159f1d..b45ecdc42 100644 --- a/cores/arduino/SERCOM.cpp +++ b/cores/arduino/SERCOM.cpp @@ -476,12 +476,17 @@ void SERCOM::prepareCommandBitsWire(SercomMasterCommandWire cmd) } bool SERCOM::startTransmissionWIRE(uint8_t address, SercomWireReadWriteFlag flag) +{ + return startTransmissionWIRE(address, flag, false); +} + +bool SERCOM::startTransmissionWIRE(uint8_t address, SercomWireReadWriteFlag flag, bool repeatedStart) { // 7-bits address + 1-bits R/W address = (address << 0x1ul) | flag; // Wait idle bus mode - while ( !isBusIdleWIRE() ); + while ( !repeatedStart && !isBusIdleWIRE()); // Send start and address sercom->I2CM.ADDR.bit.ADDR = address; diff --git a/cores/arduino/SERCOM.h b/cores/arduino/SERCOM.h index 7608386c9..307f5a9c3 100644 --- a/cores/arduino/SERCOM.h +++ b/cores/arduino/SERCOM.h @@ -194,6 +194,7 @@ class SERCOM void prepareAckBitWIRE( void ) ; void prepareCommandBitsWire(SercomMasterCommandWire cmd); bool startTransmissionWIRE(uint8_t address, SercomWireReadWriteFlag flag) ; + bool startTransmissionWIRE(uint8_t address, SercomWireReadWriteFlag flag, bool repeatedStart) ; bool sendDataMasterWIRE(uint8_t data) ; bool sendDataSlaveWIRE(uint8_t data) ; bool isMasterWIRE( void ) ; diff --git a/libraries/Wire/Wire.cpp b/libraries/Wire/Wire.cpp index d45bfe379..00c261415 100644 --- a/libraries/Wire/Wire.cpp +++ b/libraries/Wire/Wire.cpp @@ -68,7 +68,7 @@ uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity, bool stopBit) size_t byteRead = 0; - if(sercom->startTransmissionWIRE(address, WIRE_READ_FLAG)) + if(sercom->startTransmissionWIRE(address, WIRE_READ_FLAG, repeatedStart)) { // Read first data rxBuffer.store_char(sercom->readDataWIRE()); @@ -82,7 +82,12 @@ uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity, bool stopBit) } sercom->prepareNackBitWIRE(); // Prepare NACK to stop slave transmission //sercom->readDataWIRE(); // Clear data register to send NACK - sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); // Send Stop + + repeatedStart = !stopBit; + if (stopBit) + { + sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); // Send Stop + } } return byteRead; @@ -112,7 +117,7 @@ uint8_t TwoWire::endTransmission(bool stopBit) transmissionBegun = false ; // Start I2C transmission - if ( !sercom->startTransmissionWIRE( txAddress, WIRE_WRITE_FLAG ) ) + if ( !sercom->startTransmissionWIRE( txAddress, WIRE_WRITE_FLAG, repeatedStart ) ) { sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); return 2 ; // Address error @@ -128,7 +133,12 @@ uint8_t TwoWire::endTransmission(bool stopBit) return 3 ; // Nack or error } } - sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); + + repeatedStart = !stopBit; + if (stopBit) + { + sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); + } return 0; } diff --git a/libraries/Wire/Wire.h b/libraries/Wire/Wire.h index ab7ccae60..cdff10de1 100644 --- a/libraries/Wire/Wire.h +++ b/libraries/Wire/Wire.h @@ -67,7 +67,8 @@ class TwoWire : public Stream uint8_t _uc_pinSCL; bool transmissionBegun; - + bool repeatedStart; + // RX Buffer RingBuffer rxBuffer; From 9977fa34679735b9dc970780318cbce19002faae Mon Sep 17 00:00:00 2001 From: Sandeep Mistry Date: Tue, 17 Nov 2015 17:34:25 -0500 Subject: [PATCH 2/3] Make white space consistent --- libraries/Wire/Wire.cpp | 14 +++++++------- libraries/Wire/Wire.h | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libraries/Wire/Wire.cpp b/libraries/Wire/Wire.cpp index 00c261415..c4747947b 100644 --- a/libraries/Wire/Wire.cpp +++ b/libraries/Wire/Wire.cpp @@ -82,12 +82,12 @@ uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity, bool stopBit) } sercom->prepareNackBitWIRE(); // Prepare NACK to stop slave transmission //sercom->readDataWIRE(); // Clear data register to send NACK - - repeatedStart = !stopBit; - if (stopBit) - { - sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); // Send Stop - } + + repeatedStart = !stopBit; + if (stopBit) + { + sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); // Send Stop + } } return byteRead; @@ -137,7 +137,7 @@ uint8_t TwoWire::endTransmission(bool stopBit) repeatedStart = !stopBit; if (stopBit) { - sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); + sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); } return 0; diff --git a/libraries/Wire/Wire.h b/libraries/Wire/Wire.h index cdff10de1..bc2968abc 100644 --- a/libraries/Wire/Wire.h +++ b/libraries/Wire/Wire.h @@ -67,8 +67,8 @@ class TwoWire : public Stream uint8_t _uc_pinSCL; bool transmissionBegun; - bool repeatedStart; - + bool repeatedStart; + // RX Buffer RingBuffer rxBuffer; From a2949d505f977ab267ce28c4b02ad17a4088a4e1 Mon Sep 17 00:00:00 2001 From: Sandeep Mistry Date: Wed, 18 Nov 2015 09:19:04 -0500 Subject: [PATCH 3/3] Wait for idle or bus owner state in startTransmissionWIRE instead of storing repeated start state. --- cores/arduino/SERCOM.cpp | 14 +++++++------- cores/arduino/SERCOM.h | 2 +- libraries/Wire/Wire.cpp | 6 ++---- libraries/Wire/Wire.h | 1 - 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/cores/arduino/SERCOM.cpp b/cores/arduino/SERCOM.cpp index b45ecdc42..dacae2274 100644 --- a/cores/arduino/SERCOM.cpp +++ b/cores/arduino/SERCOM.cpp @@ -476,17 +476,12 @@ void SERCOM::prepareCommandBitsWire(SercomMasterCommandWire cmd) } bool SERCOM::startTransmissionWIRE(uint8_t address, SercomWireReadWriteFlag flag) -{ - return startTransmissionWIRE(address, flag, false); -} - -bool SERCOM::startTransmissionWIRE(uint8_t address, SercomWireReadWriteFlag flag, bool repeatedStart) { // 7-bits address + 1-bits R/W address = (address << 0x1ul) | flag; - // Wait idle bus mode - while ( !repeatedStart && !isBusIdleWIRE()); + // Wait idle or owner bus mode + while ( !isBusIdleWIRE() && !isBusOwnerWIRE() ); // Send start and address sercom->I2CM.ADDR.bit.ADDR = address; @@ -580,6 +575,11 @@ bool SERCOM::isBusIdleWIRE( void ) return sercom->I2CM.STATUS.bit.BUSSTATE == WIRE_IDLE_STATE; } +bool SERCOM::isBusOwnerWIRE( void ) +{ + return sercom->I2CM.STATUS.bit.BUSSTATE == WIRE_OWNER_STATE; +} + bool SERCOM::isDataReadyWIRE( void ) { return sercom->I2CS.INTFLAG.bit.DRDY; diff --git a/cores/arduino/SERCOM.h b/cores/arduino/SERCOM.h index 307f5a9c3..26a437e8f 100644 --- a/cores/arduino/SERCOM.h +++ b/cores/arduino/SERCOM.h @@ -194,12 +194,12 @@ class SERCOM void prepareAckBitWIRE( void ) ; void prepareCommandBitsWire(SercomMasterCommandWire cmd); bool startTransmissionWIRE(uint8_t address, SercomWireReadWriteFlag flag) ; - bool startTransmissionWIRE(uint8_t address, SercomWireReadWriteFlag flag, bool repeatedStart) ; bool sendDataMasterWIRE(uint8_t data) ; bool sendDataSlaveWIRE(uint8_t data) ; bool isMasterWIRE( void ) ; bool isSlaveWIRE( void ) ; bool isBusIdleWIRE( void ) ; + bool isBusOwnerWIRE( void ) ; bool isDataReadyWIRE( void ) ; bool isStopDetectedWIRE( void ) ; bool isRestartDetectedWIRE( void ) ; diff --git a/libraries/Wire/Wire.cpp b/libraries/Wire/Wire.cpp index c4747947b..21d39f71d 100644 --- a/libraries/Wire/Wire.cpp +++ b/libraries/Wire/Wire.cpp @@ -68,7 +68,7 @@ uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity, bool stopBit) size_t byteRead = 0; - if(sercom->startTransmissionWIRE(address, WIRE_READ_FLAG, repeatedStart)) + if(sercom->startTransmissionWIRE(address, WIRE_READ_FLAG)) { // Read first data rxBuffer.store_char(sercom->readDataWIRE()); @@ -83,7 +83,6 @@ uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity, bool stopBit) sercom->prepareNackBitWIRE(); // Prepare NACK to stop slave transmission //sercom->readDataWIRE(); // Clear data register to send NACK - repeatedStart = !stopBit; if (stopBit) { sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); // Send Stop @@ -117,7 +116,7 @@ uint8_t TwoWire::endTransmission(bool stopBit) transmissionBegun = false ; // Start I2C transmission - if ( !sercom->startTransmissionWIRE( txAddress, WIRE_WRITE_FLAG, repeatedStart ) ) + if ( !sercom->startTransmissionWIRE( txAddress, WIRE_WRITE_FLAG ) ) { sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); return 2 ; // Address error @@ -134,7 +133,6 @@ uint8_t TwoWire::endTransmission(bool stopBit) } } - repeatedStart = !stopBit; if (stopBit) { sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); diff --git a/libraries/Wire/Wire.h b/libraries/Wire/Wire.h index bc2968abc..ab7ccae60 100644 --- a/libraries/Wire/Wire.h +++ b/libraries/Wire/Wire.h @@ -67,7 +67,6 @@ class TwoWire : public Stream uint8_t _uc_pinSCL; bool transmissionBegun; - bool repeatedStart; // RX Buffer RingBuffer rxBuffer;