Wire library support for TWI General Call

Squash and rebase of https://github.com/arduino/Arduino/pull/49
This commit is contained in:
edbaafi 2017-11-13 14:04:44 +01:00 committed by Martino Facchin
parent 6c861d8c70
commit ef4482afef
4 changed files with 73 additions and 22 deletions

View File

@ -42,6 +42,7 @@ uint8_t TwoWire::txBufferLength = 0;
uint8_t TwoWire::transmitting = 0;
void (*TwoWire::user_onRequest)(void);
void (*TwoWire::user_onReceive)(int);
void (*TwoWire::user_onGcallReceive)(int);
// Constructors ////////////////////////////////////////////////////////////////
@ -273,12 +274,22 @@ void TwoWire::flush(void)
}
// behind the scenes function that is called when data is received
void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes)
void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes, uint8_t isGeneralCall)
{
// don't bother if user hasn't registered a callback
if(!user_onReceive){
return;
}
//check if general call or normal receive
if(isGeneralCall){
// don't bother if user hasn't registered a general call callback
if(!user_onGcallReceive){
return;
}
}
else{
// don't bother if user hasn't registered a callback
if(!user_onReceive){
return;
}
}
// don't bother if rx buffer is in use by a master requestFrom() op
// i know this drops data, but it allows for slight stupidity
// meaning, they may not have read all the master requestFrom() data yet
@ -293,8 +304,15 @@ void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes)
// set rx iterator vars
rxBufferIndex = 0;
rxBufferLength = numBytes;
// alert user program
user_onReceive(numBytes);
if(isGeneralCall){
// alert user's general call receive callback
user_onGcallReceive(numBytes);
}
else{
// alert user's receive callback
user_onReceive(numBytes);
}
}
// behind the scenes function that is called when data is requested
@ -312,16 +330,27 @@ void TwoWire::onRequestService(void)
user_onRequest();
}
// sets function called on slave write
void TwoWire::onReceive( void (*function)(int) )
// sets function called when slave receives data from master at slave's address
void TwoWire::onReceive( void (*recFunction)(int) )
{
user_onReceive = function;
user_onReceive = recFunction;
}
// sets function called on slave read
void TwoWire::onRequest( void (*function)(void) )
// sets function called when slave receives data from master at slaves address
// and another function called when slave receives data from a general call
void TwoWire::onReceive( void (*recFunction)(int), void (*gcallRecFunction)(int) )
{
user_onRequest = function;
user_onReceive = recFunction;
user_onGcallReceive = gcallRecFunction;
//enable general call addressing
twi_enableGenCall();
}
// sets function called when master requests data from slave
void TwoWire::onRequest( void (*reqFunction)(void) )
{
user_onRequest = reqFunction;
}
// Preinstantiate Objects //////////////////////////////////////////////////////

View File

@ -45,8 +45,9 @@ class TwoWire : public Stream
static uint8_t transmitting;
static void (*user_onRequest)(void);
static void (*user_onReceive)(int);
static void (*user_onGcallReceive)(int);
static void onRequestService(void);
static void onReceiveService(uint8_t*, int);
static void onReceiveService(uint8_t*, int,uint8_t);
public:
TwoWire();
void begin();
@ -70,6 +71,7 @@ class TwoWire : public Stream
virtual int peek(void);
virtual void flush(void);
void onReceive( void (*)(int) );
void onReceive( void (*)(int), void (*)(int) );
void onRequest( void (*)(void) );
inline size_t write(unsigned long n) { return write((uint8_t)n); }

View File

@ -44,7 +44,7 @@ static volatile uint8_t twi_sendStop; // should the transaction end with a sto
static volatile uint8_t twi_inRepStart; // in the middle of a repeated start
static void (*twi_onSlaveTransmit)(void);
static void (*twi_onSlaveReceive)(uint8_t*, int);
static void (*twi_onSlaveReceive)(uint8_t*, int, uint8_t);
static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH];
static volatile uint8_t twi_masterBufferIndex;
@ -58,6 +58,8 @@ static uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH];
static volatile uint8_t twi_rxBufferIndex;
static volatile uint8_t twi_error;
static volatile uint8_t twi_gcall_data;
/*
* Function twi_init
@ -114,8 +116,8 @@ void twi_disable(void)
*/
void twi_setAddress(uint8_t address)
{
// set twi slave address (skip over TWGCE bit)
TWAR = address << 1;
// set twi slave address and leave TWGCE bit (LSB)
TWAR = (address << TWA0) | ( TWAR & (1 << TWGCE) ) ;
}
/*
@ -134,6 +136,18 @@ void twi_setFrequency(uint32_t frequency)
It is 72 for a 16mhz Wiring board with 100kHz TWI */
}
/*
* Function twi_enableGenCall
* Desc enables general call address for slave
* Input none
* Output none
*/
void twi_enableGenCall(void)
{
// set TWGCE bit (LSB) and leave rest of address
TWAR |= 1 << TWGCE;
}
/*
* Function twi_readFrom
* Desc attempts to become twi bus master and read a
@ -328,7 +342,7 @@ uint8_t twi_transmit(const uint8_t* data, uint8_t length)
* Input function: callback function to use
* Output none
*/
void twi_attachSlaveRxEvent( void (*function)(uint8_t*, int) )
void twi_attachSlaveRxEvent( void (*function)(uint8_t*, int, uint8_t) )
{
twi_onSlaveReceive = function;
}
@ -481,10 +495,15 @@ ISR(TWI_vect)
twi_state = TWI_SRX;
// indicate that rx buffer can be overwritten and ack
twi_rxBufferIndex = 0;
twi_reply(1);
//indicate that we have not received any gcall data
twi_gcall_data = 0;
twi_reply(1);
break;
case TW_SR_DATA_ACK: // data received, returned ack
case TW_SR_GCALL_DATA_ACK: // data received generally, returned ack
twi_gcall_data = 1; //indicate that we received some gcall data - need to send flag to receiver
case TW_SR_DATA_ACK: // data received, returned ack
// if there is still room in the rx buffer
if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){
// put byte in buffer and ack
@ -503,7 +522,7 @@ ISR(TWI_vect)
twi_rxBuffer[twi_rxBufferIndex] = '\0';
}
// callback to user defined callback
twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex);
twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex,twi_gcall_data);
// since we submit rx buffer to "wire" library, we can reset it
twi_rxBufferIndex = 0;
break;

View File

@ -41,11 +41,12 @@
void twi_init(void);
void twi_disable(void);
void twi_setAddress(uint8_t);
void twi_enableGenCall(void);
void twi_setFrequency(uint32_t);
uint8_t twi_readFrom(uint8_t, uint8_t*, uint8_t, uint8_t);
uint8_t twi_writeTo(uint8_t, uint8_t*, uint8_t, uint8_t, uint8_t);
uint8_t twi_transmit(const uint8_t*, uint8_t);
void twi_attachSlaveRxEvent( void (*)(uint8_t*, int) );
void twi_attachSlaveRxEvent( void (*)(uint8_t*, int, uint8_t) );
void twi_attachSlaveTxEvent( void (*)(void) );
void twi_reply(uint8_t);
void twi_stop(void);