diff --git a/cores/arduino/SERCOM.cpp b/cores/arduino/SERCOM.cpp index 2cfb172aa..08297882d 100644 --- a/cores/arduino/SERCOM.cpp +++ b/cores/arduino/SERCOM.cpp @@ -410,14 +410,12 @@ void SERCOM::initSlaveWIRE( uint8_t ucAddress ) // Set slave mode sercom->I2CS.CTRLA.bit.MODE = I2C_SLAVE_OPERATION ; - // Enable Quick Command - sercom->I2CM.CTRLB.bit.QCEN = 1 ; - sercom->I2CS.ADDR.reg = SERCOM_I2CS_ADDR_ADDR( ucAddress & 0x7Ful ) | // 0x7F, select only 7 bits SERCOM_I2CS_ADDR_ADDRMASK( 0x3FFul ) ; // 0x3FF all bits set // Set the interrupt register - sercom->I2CS.INTENSET.reg = SERCOM_I2CS_INTENSET_AMATCH | // Address Match + sercom->I2CS.INTENSET.reg = SERCOM_I2CS_INTENSET_PREC | // Stop + SERCOM_I2CS_INTENSET_AMATCH | // Address Match SERCOM_I2CS_INTENSET_DRDY ; // Data Ready while ( sercom->I2CM.SYNCBUSY.bit.SYSOP != 0 ) @@ -450,23 +448,35 @@ void SERCOM::initMasterWIRE( uint32_t baudrate ) void SERCOM::prepareNackBitWIRE( void ) { - // Send a NACK - sercom->I2CM.CTRLB.bit.ACKACT = 1; + if(isMasterWIRE()) { + // Send a NACK + sercom->I2CM.CTRLB.bit.ACKACT = 1; + } else { + sercom->I2CS.CTRLB.bit.ACKACT = 1; + } } void SERCOM::prepareAckBitWIRE( void ) { - // Send an ACK - sercom->I2CM.CTRLB.bit.ACKACT = 0; + if(isMasterWIRE()) { + // Send an ACK + sercom->I2CM.CTRLB.bit.ACKACT = 0; + } else { + sercom->I2CS.CTRLB.bit.ACKACT = 0; + } } -void SERCOM::prepareCommandBitsWire(SercomMasterCommandWire cmd) +void SERCOM::prepareCommandBitsWire(uint8_t cmd) { - sercom->I2CM.CTRLB.bit.CMD = cmd; + if(isMasterWIRE()) { + sercom->I2CM.CTRLB.bit.CMD = cmd; - while(sercom->I2CM.SYNCBUSY.bit.SYSOP) - { - // Waiting for synchronization + while(sercom->I2CM.SYNCBUSY.bit.SYSOP) + { + // Waiting for synchronization + } + } else { + sercom->I2CS.CTRLB.bit.CMD = cmd; } } diff --git a/cores/arduino/SERCOM.h b/cores/arduino/SERCOM.h index fbd27e624..974cebd7c 100644 --- a/cores/arduino/SERCOM.h +++ b/cores/arduino/SERCOM.h @@ -191,7 +191,7 @@ class SERCOM void disableWIRE( void ); void prepareNackBitWIRE( void ) ; void prepareAckBitWIRE( void ) ; - void prepareCommandBitsWire(SercomMasterCommandWire cmd); + void prepareCommandBitsWire(uint8_t cmd); bool startTransmissionWIRE(uint8_t address, SercomWireReadWriteFlag flag) ; bool sendDataMasterWIRE(uint8_t data) ; bool sendDataSlaveWIRE(uint8_t data) ; diff --git a/libraries/Wire/Wire.cpp b/libraries/Wire/Wire.cpp index 31e0a1d8a..41ec53879 100644 --- a/libraries/Wire/Wire.cpp +++ b/libraries/Wire/Wire.cpp @@ -47,6 +47,9 @@ void TwoWire::begin(uint8_t address) { //Slave mode sercom->initSlaveWIRE(address); sercom->enableWIRE(); + + pinPeripheral(_uc_pinSDA, g_APinDescription[_uc_pinSDA].ulPinType); + pinPeripheral(_uc_pinSCL, g_APinDescription[_uc_pinSCL].ulPinType); } void TwoWire::end() { @@ -216,29 +219,31 @@ void TwoWire::onService(void) { if ( sercom->isSlaveWIRE() ) { - //Received data - if(sercom->isDataReadyWIRE()) + if(sercom->isStopDetectedWIRE() || + (sercom->isAddressMatch() && sercom->isRestartDetectedWIRE() && !sercom->isMasterReadOperationWIRE())) //Stop or Restart detected { - //Store data - rxBuffer.store_char(sercom->readDataWIRE()); + sercom->prepareAckBitWIRE(); + sercom->prepareCommandBitsWire(0x03); - //Stop or Restart detected - if(sercom->isStopDetectedWIRE() || sercom->isRestartDetectedWIRE()) + //Calling onReceiveCallback, if exists + if(onReceiveCallback) { - //Calling onReceiveCallback, if exists - if(onReceiveCallback) - { - onReceiveCallback(available()); - } + onReceiveCallback(available()); } + + rxBuffer.clear(); } - - //Address Match - if(sercom->isAddressMatch()) + else if(sercom->isAddressMatch()) //Address Match { - //Is a request ? - if(sercom->isMasterReadOperationWIRE()) + sercom->prepareAckBitWIRE(); + sercom->prepareCommandBitsWire(0x03); + + if(sercom->isMasterReadOperationWIRE()) //Is a request ? { + // wait for data ready flag, + // before calling request callback + while(!sercom->isDataReadyWIRE()); + //Calling onRequestCallback, if exists if(onRequestCallback) { @@ -246,6 +251,19 @@ void TwoWire::onService(void) } } } + else if(sercom->isDataReadyWIRE()) //Received data + { + if (rxBuffer.isFull()) { + sercom->prepareNackBitWIRE(); + } else { + //Store data + rxBuffer.store_char(sercom->readDataWIRE()); + + sercom->prepareAckBitWIRE(); + } + + sercom->prepareCommandBitsWire(0x03); + } } }