Skip to content
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
52 changes: 40 additions & 12 deletions framework/cores/AVR8Bit/libraries/Wire/Wire.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
|| @contribution Hernando Barragan <b@wiring.org.co>
|| @contribution Alexander Brevig <abrevig@wiring.org.co>
|| @contribution Brett Hagman <bhagman@wiring.org.co>
|| @contribution Ed Baafi <ed@modk.it>
||
|| @description
|| | TWI Library.
Expand Down Expand Up @@ -40,6 +41,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 ////////////////////////////////////////////////////////////////

Expand Down Expand Up @@ -213,12 +215,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
Expand All @@ -233,8 +245,14 @@ 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
Expand All @@ -252,16 +270,26 @@ 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 = recFunction;
}

// 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_onReceive = function;
user_onReceive = recFunction;
user_onGcallReceive = gcallRecFunction;
//enable general call addressing
twi_enableGenCall();
}

// sets function called on slave read
void TwoWire::onRequest( void (*function)(void) )
// sets function called when master requests data from slave
void TwoWire::onRequest( void (*reqFunction)(void) )
{
user_onRequest = function;
user_onRequest = reqFunction;
}

// Preinstantiate Objects //////////////////////////////////////////////////////
Expand Down
5 changes: 4 additions & 1 deletion framework/cores/AVR8Bit/libraries/Wire/Wire.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
|| @contribution Hernando Barragan <b@wiring.org.co>
|| @contribution Alexander Brevig <abrevig@wiring.org.co>
|| @contribution Brett Hagman <bhagman@wiring.org.co>
|| @contribution Ed Baafi <ed@modk.it>
||
|| @description
|| | TWI Library.
Expand Down Expand Up @@ -39,8 +40,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();
Expand All @@ -60,6 +62,7 @@ class TwoWire : public Stream
int peek(void);
void flush(void);
void onReceive(void (*)(int));
void onReceive( void (*)(int), void (*)(int) );
void onRequest(void (*)(void));
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Author: Ed Baafi
* Date: 11/11/11
*
* This example demonstrates the TWI (I2C) "General Call" capabilities.
*
* General call is like a broadcast that can be received by many listeners at the same same. This
* is useful when you don't know the address of the device you want to talk to or it can be used as
* a sort of interrupt over the TWI (I2C). For more info on General Call, please see the I2C specs.
*
* The Wire library now supports General Call by adding a second receive callback to Wire.onReceive()
* This second callback will be called whenever a message is received over the general call address.
*
* This code is for the master device. Instructions are in comments for the slave device code.
*
*/

#include <Wire.h>

//button to send a general call message (connect button between pin10 and ground)
#define GENERAL_CALL_ADDR_BUTTON 10
//button to send a normal i2c message (connect button between pin 9 and ground)
#define SLAVE_ADDR_BUTTON 9

#define SLAVE_ADDRESS 0x9
#define GENERAL_CALL_ADDR 0x0

//store state of slave message button
boolean slave_btn_state = HIGH;
//store state of general call message button
boolean general_call_btn_state = HIGH;

void setup() {
Serial.begin(9600);

//setup general call button as input with internal pullup
pinMode(GENERAL_CALL_ADDR_BUTTON, INPUT);
digitalWrite(GENERAL_CALL_ADDR_BUTTON, HIGH);

//setup normal i2c send button as input with internal pullup
pinMode(SLAVE_ADDR_BUTTON, INPUT);
digitalWrite(SLAVE_ADDR_BUTTON, HIGH);

//setup TWI as master
Wire.begin();

}

void loop() {
//if general call button state changes, send new state over message to general call address
if (digitalRead(GENERAL_CALL_ADDR_BUTTON) != general_call_btn_state){
general_call_btn_state = !general_call_btn_state;
Wire.beginTransmission(GENERAL_CALL_ADDR);
Wire.write(general_call_btn_state);
Wire.endTransmission();
delay(100);
}

//if slave address send button changes state, send new state over message to slave address
if (digitalRead(SLAVE_ADDR_BUTTON) != slave_btn_state){
slave_btn_state = !slave_btn_state;
Wire.beginTransmission(SLAVE_ADDRESS);
Wire.write(slave_btn_state);
Wire.endTransmission();
//we need a small delay or we'll crash the Wire library - TODO - fix it
delay(100);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Author: Ed Baafi
* Date: 11/11/11
*
* This example demonstrates the TWI (I2C) "General Call" capabilities.
*
* General call is like a broadcast that can be received by many listeners at the same same. This
* is useful when you don't know the address of the device you want to talk to or it can be used as
* a sort of interrupt over the TWI (I2C). For more info on General Call, please see the I2C specs.
*
* The Wire library now supports General Call by adding a second receive callback to Wire.onReceive()
* This second callback will be called whenever a message is received over the general call address.
*
* 1) This code is for the slave device. Connect the slave device (through usb) to your PC and open
* up the serial monitor (set it to 9600 bps). You can optionally connect two LEDs to pins 12 and 11
*
* 2) On the master device, connect a button between pin10 and ground and another between pin9
* and ground. The pin10 button will send its state to the general call address (can be picked up by
* any attached slave device) and the pin9 button will sent through to a specific slave address.
*
* 3) Connect the SCL and SDA lines from the slave to the master. For UNO boards SDA is on analog pin
* 4 and SCL is on analog pin 5.
*
* 4) Pressing one button will send a message to general call and the other will send a message through
* the slave's address. Want to go further, add a second slave device and/or use the LEDs to see which
* address is being sent to.
*/

#include <Wire.h>

//led to tie to the master's general call i2c button
#define GENERAL_CALL_RECV_LED 12
//led to tie to the master's normal i2c button
#define RECV_LED 11

#define MY_ADDRESS 0x9

void setup() {
Serial.begin(9600);

//set general call led pin as output and set low (turn off)
pinMode(GENERAL_CALL_RECV_LED, OUTPUT);
digitalWrite(GENERAL_CALL_RECV_LED, LOW);

//set slave receive led pin as output and set low (turn off)
pinMode(RECV_LED, OUTPUT);
digitalWrite(RECV_LED, LOW);

//setup TWI as slave and set address
Wire.begin(MY_ADDRESS);

//setup first callback to fire when data is received on MY_ADDRESS
//and the second when a data is received on the general call address (0x0)
//if you omit the second callback, general call wil not be enabled in the Wire library
Wire.onReceive(receiveCallback,generalCallReceiveCallback);

}

void loop() {
//do nothing - wait for callbacks to fire
}

void receiveCallback(int howMany){


//print data sent to MY_ADDRESS to the serial monitor
Serial.print("\nSLAVE ADDR: ");
while (Wire.available() > 0 && howMany > 0){
boolean b = Wire.read();
Serial.print(b, DEC);
digitalWrite(RECV_LED, !b);
howMany--;
}
}

void generalCallReceiveCallback(int howMany){
//print data sent to the general call address to the serial monitor
Serial.print("\nGENERAL CALL: ");
while (Wire.available() > 0 && howMany > 0){
boolean b = Wire.read();
Serial.print(b, DEC);
digitalWrite(GENERAL_CALL_RECV_LED, !b);
howMany--;
}
}

39 changes: 28 additions & 11 deletions framework/cores/AVR8Bit/libraries/Wire/utility/twi.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
|| @contribution Hernando Barragan <b@wiring.org.co>
|| @contribution Alexander Brevig <abrevig@wiring.org.co>
|| @contribution Brett Hagman <bhagman@wiring.org.co>
|| @contribution Ed Baafi <ed@modk.it>
||
|| @description
|| | TWI utility library.
Expand Down Expand Up @@ -38,7 +39,7 @@ static volatile uint8_t twi_state;
static uint8_t twi_slarw;

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;
Expand All @@ -52,6 +53,7 @@ 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
Expand Down Expand Up @@ -100,15 +102,27 @@ void twi_init(void)
}

/*
* Function twi_slaveInit
* Desc sets slave address and enables interrupt
* Input none
* Function twi_setAddress
* Desc sets slave address
* Input address: 7bit i2c device address
* Output none
*/
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) ) ;
}

/*
* 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;
}

/*
Expand Down Expand Up @@ -270,7 +284,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;
}
Expand Down Expand Up @@ -403,10 +417,13 @@ SIGNAL(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_GCALL_DATA_ACK: // data received on general call, 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
case TW_SR_GCALL_DATA_ACK: // data received generally, returned ack
// if there is still room in the rx buffer
if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){
// put byte in buffer and ack
Expand All @@ -425,8 +442,8 @@ SIGNAL(TWI_vect)
// sends ack and stops interface for clock stretching
twi_stop();
// callback to user defined callback
twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex);
// since we submit rx buffer to "wire" library, we can reset it
twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex,twi_gcall_data);
// since we submit rx buffer to "wire" library, we can reset it
twi_rxBufferIndex = 0;
// ack future responses and leave slave receiver state
twi_releaseBus();
Expand Down
4 changes: 3 additions & 1 deletion framework/cores/AVR8Bit/libraries/Wire/utility/twi.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
|| @contribution Hernando Barragan <b@wiring.org.co>
|| @contribution Alexander Brevig <abrevig@wiring.org.co>
|| @contribution Brett Hagman <bhagman@wiring.org.co>
|| @contribution Ed Baafi <ed@modk.it>
||
|| @description
|| | TWI utility library.
Expand Down Expand Up @@ -39,10 +40,11 @@

void twi_init(void);
void twi_setAddress(uint8_t);
void twi_enableGenCall(void);
uint8_t twi_readFrom(uint8_t, uint8_t*, uint8_t);
uint8_t twi_writeTo(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);
Expand Down