From 4efe39eb4908109bdbd96e9c4f23894e7e5b4523 Mon Sep 17 00:00:00 2001 From: Sandeep Mistry <s.mistry@arduino.cc> Date: Tue, 8 Sep 2015 17:47:30 -0400 Subject: [PATCH] Changes to get Wire slave receiver working --- cores/arduino/SERCOM.cpp | 36 ++++++++++++++++++----------- cores/arduino/SERCOM.h | 2 +- libraries/Wire/Wire.cpp | 50 +++++++++++++++++++++++++--------------- 3 files changed, 56 insertions(+), 32 deletions(-) diff --git a/cores/arduino/SERCOM.cpp b/cores/arduino/SERCOM.cpp index 2cfb172a..08297882 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 fbd27e62..974cebd7 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 31e0a1d8..273b03e7 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,26 +219,11 @@ void TwoWire::onService(void) { if ( sercom->isSlaveWIRE() ) { - //Received data - if(sercom->isDataReadyWIRE()) + if(sercom->isAddressMatch()) //Address Match { - //Store data - rxBuffer.store_char(sercom->readDataWIRE()); - - //Stop or Restart detected - if(sercom->isStopDetectedWIRE() || sercom->isRestartDetectedWIRE()) - { - //Calling onReceiveCallback, if exists - if(onReceiveCallback) - { - onReceiveCallback(available()); - } - } - } + sercom->prepareAckBitWIRE(); + sercom->prepareCommandBitsWire(0x03); - //Address Match - if(sercom->isAddressMatch()) - { //Is a request ? if(sercom->isMasterReadOperationWIRE()) { @@ -246,6 +234,32 @@ 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); + } + else if(sercom->isStopDetectedWIRE() || sercom->isRestartDetectedWIRE()) //Stop or Restart detected + { + sercom->prepareAckBitWIRE(); + sercom->prepareCommandBitsWire(0x03); + + //Calling onReceiveCallback, if exists + if(onReceiveCallback) + { + onReceiveCallback(available()); + } + + rxBuffer.clear(); + } } } -- GitLab