Skip to content

Wire Slave #46

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 18, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 23 additions & 13 deletions cores/arduino/SERCOM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 )
Expand Down Expand Up @@ -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;
}
}

Expand Down
2 changes: 1 addition & 1 deletion cores/arduino/SERCOM.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) ;
Expand Down
50 changes: 34 additions & 16 deletions libraries/Wire/Wire.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -216,36 +219,51 @@ 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)
{
onRequestCallback();
}
}
}
else if(sercom->isDataReadyWIRE()) //Received data
{
if (rxBuffer.isFull()) {
sercom->prepareNackBitWIRE();
} else {
//Store data
rxBuffer.store_char(sercom->readDataWIRE());

sercom->prepareAckBitWIRE();
}

sercom->prepareCommandBitsWire(0x03);
}
}
}

Expand Down