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

View File

@ -45,8 +45,9 @@ class TwoWire : public Stream
static uint8_t transmitting; static uint8_t transmitting;
static void (*user_onRequest)(void); static void (*user_onRequest)(void);
static void (*user_onReceive)(int); static void (*user_onReceive)(int);
static void (*user_onGcallReceive)(int);
static void onRequestService(void); static void onRequestService(void);
static void onReceiveService(uint8_t*, int); static void onReceiveService(uint8_t*, int,uint8_t);
public: public:
TwoWire(); TwoWire();
void begin(); void begin();
@ -70,6 +71,7 @@ class TwoWire : public Stream
virtual int peek(void); virtual int peek(void);
virtual void flush(void); virtual void flush(void);
void onReceive( void (*)(int) ); void onReceive( void (*)(int) );
void onReceive( void (*)(int), void (*)(int) );
void onRequest( void (*)(void) ); void onRequest( void (*)(void) );
inline size_t write(unsigned long n) { return write((uint8_t)n); } 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 volatile uint8_t twi_inRepStart; // in the middle of a repeated start
static void (*twi_onSlaveTransmit)(void); 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 uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH];
static volatile uint8_t twi_masterBufferIndex; 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_rxBufferIndex;
static volatile uint8_t twi_error; static volatile uint8_t twi_error;
static volatile uint8_t twi_gcall_data;
/* /*
* Function twi_init * Function twi_init
@ -114,8 +116,8 @@ void twi_disable(void)
*/ */
void twi_setAddress(uint8_t address) void twi_setAddress(uint8_t address)
{ {
// set twi slave address (skip over TWGCE bit) // set twi slave address and leave TWGCE bit (LSB)
TWAR = address << 1; 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 */ 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 * Function twi_readFrom
* Desc attempts to become twi bus master and read a * 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 * Input function: callback function to use
* Output none * Output none
*/ */
void twi_attachSlaveRxEvent( void (*function)(uint8_t*, int) ) void twi_attachSlaveRxEvent( void (*function)(uint8_t*, int, uint8_t) )
{ {
twi_onSlaveReceive = function; twi_onSlaveReceive = function;
} }
@ -481,10 +495,15 @@ ISR(TWI_vect)
twi_state = TWI_SRX; twi_state = TWI_SRX;
// indicate that rx buffer can be overwritten and ack // indicate that rx buffer can be overwritten and ack
twi_rxBufferIndex = 0; twi_rxBufferIndex = 0;
//indicate that we have not received any gcall data
twi_gcall_data = 0;
twi_reply(1); twi_reply(1);
break; break;
case TW_SR_DATA_ACK: // data received, returned ack
case TW_SR_GCALL_DATA_ACK: // data received generally, 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 there is still room in the rx buffer
if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){ if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){
// put byte in buffer and ack // put byte in buffer and ack
@ -503,7 +522,7 @@ ISR(TWI_vect)
twi_rxBuffer[twi_rxBufferIndex] = '\0'; twi_rxBuffer[twi_rxBufferIndex] = '\0';
} }
// callback to user defined callback // 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 // since we submit rx buffer to "wire" library, we can reset it
twi_rxBufferIndex = 0; twi_rxBufferIndex = 0;
break; break;

View File

@ -41,11 +41,12 @@
void twi_init(void); void twi_init(void);
void twi_disable(void); void twi_disable(void);
void twi_setAddress(uint8_t); void twi_setAddress(uint8_t);
void twi_enableGenCall(void);
void twi_setFrequency(uint32_t); void twi_setFrequency(uint32_t);
uint8_t twi_readFrom(uint8_t, uint8_t*, uint8_t, uint8_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_writeTo(uint8_t, uint8_t*, uint8_t, uint8_t, uint8_t);
uint8_t twi_transmit(const 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_attachSlaveTxEvent( void (*)(void) );
void twi_reply(uint8_t); void twi_reply(uint8_t);
void twi_stop(void); void twi_stop(void);