Skip to content

Overload beginTransmission and requestFrom to support using an external buffer #289

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

Closed
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
88 changes: 74 additions & 14 deletions libraries/Wire/Wire.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ TwoWire::TwoWire(SERCOM * s, uint8_t pinSDA, uint8_t pinSCL)
this->_uc_pinSDA=pinSDA;
this->_uc_pinSCL=pinSCL;
transmissionBegun = false;
externalTxBuffer = NULL;
externalTxBufferLength = 0;
externalTxBufferQuantity = 0;
}

void TwoWire::begin(void) {
Expand Down Expand Up @@ -62,7 +65,22 @@ void TwoWire::end() {
sercom->disableWIRE();
}

uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity)
{
return requestFrom(address, quantity, true);
}

uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity, bool stopBit)
{
return requestFrom(address, NULL, quantity, stopBit);
}

uint8_t TwoWire::requestFrom(uint8_t address, uint8_t buffer[], size_t quantity)
{
return requestFrom(address, buffer, quantity, true);
}

uint8_t TwoWire::requestFrom(uint8_t address, uint8_t buffer[], size_t quantity, bool stopBit)
{
if(quantity == 0)
{
Expand All @@ -76,14 +94,22 @@ uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity, bool stopBit)
if(sercom->startTransmissionWIRE(address, WIRE_READ_FLAG))
{
// Read first data
rxBuffer.store_char(sercom->readDataWIRE());
if (buffer == NULL) {
rxBuffer.store_char(sercom->readDataWIRE());
} else {
buffer[0] = sercom->readDataWIRE();
}

// Connected to slave
for (byteRead = 1; byteRead < quantity; ++byteRead)
{
sercom->prepareAckBitWIRE(); // Prepare Acknowledge
sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_READ); // Prepare the ACK command for the slave
rxBuffer.store_char(sercom->readDataWIRE()); // Read data and send the ACK
if (buffer == NULL) {
rxBuffer.store_char(sercom->readDataWIRE()); // Read data and send the ACK
} else {
buffer[byteRead] = sercom->readDataWIRE();
}
}
sercom->prepareNackBitWIRE(); // Prepare NACK to stop slave transmission
//sercom->readDataWIRE(); // Clear data register to send NACK
Expand All @@ -97,15 +123,17 @@ uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity, bool stopBit)
return byteRead;
}

uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity)
{
return requestFrom(address, quantity, true);
void TwoWire::beginTransmission(uint8_t address) {
beginTransmission(address, NULL, 0, 0);
}

void TwoWire::beginTransmission(uint8_t address) {
void TwoWire::beginTransmission(uint8_t address, uint8_t buffer[], size_t length, size_t quantity) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the name of the arguments in beginTransmission is confusing. How about bufferLength and usedBytes?

// save address of target and clear buffer
txAddress = address;
txBuffer.clear();
externalTxBuffer = buffer;
externalTxBufferLength = length;
externalTxBufferQuantity = quantity;

transmissionBegun = true;
}
Expand All @@ -127,14 +155,29 @@ uint8_t TwoWire::endTransmission(bool stopBit)
return 2 ; // Address error
}

// Send all buffer
while( txBuffer.available() )
if (externalTxBuffer == NULL)
{
// Trying to send data
if ( !sercom->sendDataMasterWIRE( txBuffer.read_char() ) )
// Send all buffer
while( txBuffer.available() )
{
sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
return 3 ; // Nack or error
// Trying to send data
if ( !sercom->sendDataMasterWIRE( txBuffer.read_char() ) )
{
sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
return 3 ; // Nack or error
}
}
}
else
{
for (size_t i = 0; i < externalTxBufferQuantity; i++)
{
// Trying to send data
if ( !sercom->sendDataMasterWIRE( externalTxBuffer[i] ) )
{
sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
return 3 ; // Nack or error
}
}
}

Expand All @@ -154,12 +197,29 @@ uint8_t TwoWire::endTransmission()
size_t TwoWire::write(uint8_t ucData)
{
// No writing, without begun transmission or a full buffer
if ( !transmissionBegun || txBuffer.isFull() )
if ( !transmissionBegun )
{
return 0 ;
}

txBuffer.store_char( ucData ) ;
if (externalTxBuffer == NULL)
{
if ( txBuffer.isFull() )
{
return 0;
}

txBuffer.store_char( ucData ) ;
}
else
{
if ( externalTxBufferLength == externalTxBufferQuantity )
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would use >= for robustness

{
return 0;
}

externalTxBuffer[externalTxBufferQuantity++] = ucData;
}

return 1 ;
}
Expand Down
10 changes: 9 additions & 1 deletion libraries/Wire/Wire.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,14 @@ class TwoWire : public Stream
void setClock(uint32_t);

void beginTransmission(uint8_t);
void beginTransmission(uint8_t address, uint8_t buffer[], size_t length, size_t quantity = 0);
uint8_t endTransmission(bool stopBit);
uint8_t endTransmission(void);

uint8_t requestFrom(uint8_t address, size_t quantity, bool stopBit);
uint8_t requestFrom(uint8_t address, size_t quantity);
uint8_t requestFrom(uint8_t address, uint8_t buffer[], size_t quantity);
uint8_t requestFrom(uint8_t address, uint8_t buffer[], size_t quantity, bool stopBit);

size_t write(uint8_t data);
size_t write(const uint8_t * data, size_t quantity);
Expand Down Expand Up @@ -73,10 +76,15 @@ class TwoWire : public Stream
// RX Buffer
RingBuffer rxBuffer;

//TX buffer
// TX buffer
RingBuffer txBuffer;
uint8_t txAddress;

// external TX buffer
uint8_t* externalTxBuffer;
size_t externalTxBufferLength;
size_t externalTxBufferQuantity;

// Callback user functions
void (*onRequestCallback)(void);
void (*onReceiveCallback)(int);
Expand Down