diff --git a/cores/arduino/SERCOM.cpp b/cores/arduino/SERCOM.cpp index 34d3aa18b..b6b390593 100644 --- a/cores/arduino/SERCOM.cpp +++ b/cores/arduino/SERCOM.cpp @@ -485,17 +485,19 @@ void SERCOM::prepareCommandBitsWire(uint8_t cmd) } } -bool SERCOM::startTransmissionWIRE(uint8_t address, SercomWireReadWriteFlag flag) +bool SERCOM::startTransmissionWIRE(uint8_t address, SercomWireReadWriteFlag flag, bool _repeatstart) { // 7-bits address + 1-bits R/W address = (address << 0x1ul) | flag; - // Wait idle bus mode - while ( !isBusIdleWIRE() ); + // Wait idle bus mode (except repeated start) + if (! _repeatstart) { + while ( !isBusIdleWIRE() ); + } - // Send start and address + // Send start and address, in repeated start mode this will kick off the repstart too! sercom->I2CM.ADDR.bit.ADDR = address; - + // Address Transmitted if ( flag == WIRE_WRITE_FLAG ) // Write mode { diff --git a/cores/arduino/SERCOM.h b/cores/arduino/SERCOM.h index 58953d019..7419ed5b0 100644 --- a/cores/arduino/SERCOM.h +++ b/cores/arduino/SERCOM.h @@ -193,7 +193,7 @@ class SERCOM void prepareNackBitWIRE( void ) ; void prepareAckBitWIRE( void ) ; void prepareCommandBitsWire(uint8_t cmd); - bool startTransmissionWIRE(uint8_t address, SercomWireReadWriteFlag flag) ; + bool startTransmissionWIRE(uint8_t address, SercomWireReadWriteFlag flag, bool rs = false); 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 635b1e6d8..b510dfb57 100644 --- a/libraries/Wire/Wire.cpp +++ b/libraries/Wire/Wire.cpp @@ -32,6 +32,7 @@ TwoWire::TwoWire(SERCOM * s, uint8_t pinSDA, uint8_t pinSCL) this->_uc_pinSDA=pinSDA; this->_uc_pinSCL=pinSCL; transmissionBegun = false; + _repeatedstart = false; } void TwoWire::begin(void) { @@ -71,7 +72,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()); @@ -114,6 +115,13 @@ uint8_t TwoWire::endTransmission(bool stopBit) { transmissionBegun = false ; + SercomMasterCommandWire cmd; + if (stopBit) { + _repeatedstart = false; + } else { + _repeatedstart = true; + } + // Start I2C transmission if ( !sercom->startTransmissionWIRE( txAddress, WIRE_WRITE_FLAG ) ) { @@ -131,7 +139,12 @@ uint8_t TwoWire::endTransmission(bool stopBit) return 3 ; // Nack or error } } - sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); + + if (stopBit) { + sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); + } + /* We dont actually send any command now, next time we try to do a read + it will automagically send a repeated start, see Table 27-12. Command Description */ return 0; } diff --git a/libraries/Wire/Wire.h b/libraries/Wire/Wire.h index ab7ccae60..63dea1569 100644 --- a/libraries/Wire/Wire.h +++ b/libraries/Wire/Wire.h @@ -60,14 +60,16 @@ class TwoWire : public Stream using Print::write; void onService(void); - private: SERCOM * sercom; + uint8_t _uc_pinSDA; uint8_t _uc_pinSCL; bool transmissionBegun; + bool _repeatedstart; + // RX Buffer RingBuffer rxBuffer;