diff --git a/app/build.xml b/app/build.xml
index 06cc52fd7a1..6e6f07f50ef 100644
--- a/app/build.xml
+++ b/app/build.xml
@@ -37,7 +37,7 @@
-->
- BUFFER_LENGTH){
quantity = BUFFER_LENGTH;
}
// perform blocking read into buffer
- uint8_t read = twi_readFrom(address, rxBuffer, quantity, sendStop);
+ uint8_t read = twi_readFrom_timeout(address, rxBuffer, quantity, sendStop, timeout_us);
// set rx buffer iterator vars
rxBufferIndex = 0;
rxBufferLength = read;
@@ -90,6 +98,10 @@ uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop
return read;
}
+uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop){
+ return requestFrom_timeout(address, quantity, sendStop, 0);
+}
+
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity)
{
return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
@@ -134,10 +146,11 @@ void TwoWire::beginTransmission(int address)
// no call to endTransmission(true) is made. Some I2C
// devices will behave oddly if they do not see a STOP.
//
-uint8_t TwoWire::endTransmission(uint8_t sendStop)
+
+uint8_t TwoWire::endTransmission_timeout(uint8_t sendStop, uint32_t timeout_us)
{
// transmit buffer (blocking)
- int8_t ret = twi_writeTo(txAddress, txBuffer, txBufferLength, 1, sendStop);
+ int8_t ret = twi_writeTo_timeout(txAddress, txBuffer, txBufferLength, 1, sendStop, timeout_us);
// reset tx buffer iterator vars
txBufferIndex = 0;
txBufferLength = 0;
@@ -146,6 +159,10 @@ uint8_t TwoWire::endTransmission(uint8_t sendStop)
return ret;
}
+uint8_t TwoWire::endTransmission(uint8_t sendStop){
+ return endTransmission_timeout(sendStop, 0);
+}
+
// This provides backwards compatibility with the original
// definition, and expected behaviour, of endTransmission
//
diff --git a/libraries/Wire/Wire.h b/libraries/Wire/Wire.h
index a93d0f5bb30..00c2d4362f6 100755
--- a/libraries/Wire/Wire.h
+++ b/libraries/Wire/Wire.h
@@ -49,12 +49,16 @@ class TwoWire : public Stream
void begin();
void begin(uint8_t);
void begin(int);
+ void begin_timeout(uint32_t);
+ void begin_timeout(uint8_t, uint32_t);
void beginTransmission(uint8_t);
void beginTransmission(int);
uint8_t endTransmission(void);
uint8_t endTransmission(uint8_t);
+ uint8_t endTransmission_timeout(uint8_t, uint32_t);
uint8_t requestFrom(uint8_t, uint8_t);
uint8_t requestFrom(uint8_t, uint8_t, uint8_t);
+ uint8_t requestFrom_timeout(uint8_t, uint8_t, uint8_t, uint32_t);
uint8_t requestFrom(int, int);
uint8_t requestFrom(int, int, int);
virtual size_t write(uint8_t);
diff --git a/libraries/Wire/examples/timeout_digital_potentiometer/timeout_digital_potentiometer.ino b/libraries/Wire/examples/timeout_digital_potentiometer/timeout_digital_potentiometer.ino
new file mode 100644
index 00000000000..a9f2e9efc75
--- /dev/null
+++ b/libraries/Wire/examples/timeout_digital_potentiometer/timeout_digital_potentiometer.ino
@@ -0,0 +1,42 @@
+// I2C Digital Potentiometer
+// by Nicholas Zambetti
+// and Shawn Bonkowski
+
+// Demonstrates use of the Wire library
+// Controls AD5171 digital potentiometer via I2C/TWI
+
+// Created 31 March 2006
+// Edited 7 december 2014 by Mauro Mombelli
+
+// This example code is in the public domain.
+
+// This example code is in the public domain.
+
+
+#include
+
+const unsigned long default_wire_timeout_us = 1000UL;
+
+void setup()
+{
+ Wire.begin_timeout(default_wire_timeout_us); // join i2c bus (address optional for master)
+}
+
+byte val = 0;
+
+void loop()
+{
+ Wire.beginTransmission(44); // transmit to device #44 (0x2c)
+ // device address is specified in datasheet
+ Wire.write(byte(0x00)); // sends instruction byte
+ Wire.write(val); // sends potentiometer value byte
+ Wire.endTransmission_timeout(true, default_wire_timeout_us); // stop transmitting
+
+ val++; // increment value
+ if(val == 64) // if reached 64th position (max)
+ {
+ val = 0; // start over from lowest value
+ }
+ delay(500);
+}
+
diff --git a/libraries/Wire/examples/timeout_master_reader/timeout_master_reader.ino b/libraries/Wire/examples/timeout_master_reader/timeout_master_reader.ino
new file mode 100644
index 00000000000..3ca54ffbf4c
--- /dev/null
+++ b/libraries/Wire/examples/timeout_master_reader/timeout_master_reader.ino
@@ -0,0 +1,35 @@
+// Wire Master Reader
+// by Nicholas Zambetti
+
+// Demonstrates use of the Wire library
+// Reads data from an I2C/TWI slave device
+// Refer to the "Wire Slave Sender" example for use with this
+
+// Created 29 March 2006
+// Edited 7 december 2014 by Mauro Mombelli
+
+// This example code is in the public domain.
+
+
+#include
+
+const unsigned long default_timeout_us = 1000UL;
+
+void setup()
+{
+ Wire.begin_timeout(default_timeout_us); // join i2c bus (address optional for master)
+ Serial.begin(9600); // start serial for output
+}
+
+void loop()
+{
+ Wire.requestFrom_timeout(2, 6, true, default_timeout_us); // request 6 bytes from slave device #2
+
+ while(Wire.available()) // slave may send less than requested
+ {
+ char c = Wire.read(); // receive a byte as character
+ Serial.print(c); // print the character
+ }
+
+ delay(500);
+}
diff --git a/libraries/Wire/examples/timeout_slave_receiver/.directory b/libraries/Wire/examples/timeout_slave_receiver/.directory
new file mode 100644
index 00000000000..1da637eee65
--- /dev/null
+++ b/libraries/Wire/examples/timeout_slave_receiver/.directory
@@ -0,0 +1,6 @@
+[Dolphin]
+Timestamp=2014,12,7,15,37,21
+Version=3
+
+[Settings]
+HiddenFilesShown=true
diff --git a/libraries/Wire/examples/timeout_slave_receiver/timeout_slave_receiver.ino b/libraries/Wire/examples/timeout_slave_receiver/timeout_slave_receiver.ino
new file mode 100644
index 00000000000..7eb52e630ce
--- /dev/null
+++ b/libraries/Wire/examples/timeout_slave_receiver/timeout_slave_receiver.ino
@@ -0,0 +1,41 @@
+// Wire Slave Receiver
+// by Nicholas Zambetti
+
+// Demonstrates use of the Wire library
+// Receives data as an I2C/TWI slave device
+// Refer to the "Wire Master Writer" example for use with this
+
+// Created 29 March 2006
+// Edited 7 december 2014 by Mauro Mombelli
+
+// This example code is in the public domain.
+
+
+#include
+
+const unsigned long default_timeout_us = 1000UL;
+
+void setup()
+{
+ Wire.begin_timeout(4, default_timeout_us); // join i2c bus with address #4
+ Wire.onReceive(receiveEvent); // register event
+ Serial.begin(9600); // start serial for output
+}
+
+void loop()
+{
+ delay(100);
+}
+
+// function that executes whenever data is received from master
+// this function is registered as an event, see setup()
+void receiveEvent(int howMany)
+{
+ while(1 < Wire.available()) // loop through all but the last
+ {
+ char c = Wire.read(); // receive byte as a character
+ Serial.print(c); // print the character
+ }
+ int x = Wire.read(); // receive byte as an integer
+ Serial.println(x); // print the integer
+}
diff --git a/libraries/Wire/utility/twi.c b/libraries/Wire/utility/twi.c
index 201d7d1bbbf..139d92078d6 100644
--- a/libraries/Wire/utility/twi.c
+++ b/libraries/Wire/utility/twi.c
@@ -25,7 +25,7 @@
#include
#include
#include
-#include "Arduino.h" // for digitalWrite
+#include "Arduino.h" // for digitalWrite and micros
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
@@ -59,14 +59,19 @@ static volatile uint8_t twi_rxBufferIndex;
static volatile uint8_t twi_error;
+static volatile uint32_t twi_default_timeout;
+
/*
* Function twi_init
* Desc readys twi pins and sets twi bitrate
* Input none
* Output none
*/
-void twi_init(void)
+
+void twi_init_timeout(uint32_t default_timeout)
{
+ twi_default_timeout = default_timeout;
+
// initialize state
twi_state = TWI_READY;
twi_sendStop = true; // default value
@@ -81,15 +86,16 @@ void twi_init(void)
cbi(TWSR, TWPS1);
TWBR = ((F_CPU / TWI_FREQ) - 16) / 2;
- /* twi bit rate formula from atmega128 manual pg 204
- SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR))
- note: TWBR should be 10 or higher for master mode
- It is 72 for a 16mhz Wiring board with 100kHz TWI */
+ // twi bit rate formula from atmega128 manual pg 204
+ //SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR))
+ //note: TWBR should be 10 or higher for master mode
+ //It is 72 for a 16mhz Wiring board with 100kHz TWI
// enable twi module, acks, and twi interrupt
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA);
}
+
/*
* Function twi_slaveInit
* Desc sets slave address and enables interrupt
@@ -101,7 +107,11 @@ void twi_setAddress(uint8_t address)
// set twi slave address (skip over TWGCE bit)
TWAR = address << 1;
}
-
+/*
+uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sendStop){
+ return twi_readFrom_timeout(address, data, length, sendStop, 0);
+}
+*/
/*
* Function twi_readFrom
* Desc attempts to become twi bus master and read a
@@ -110,9 +120,10 @@ void twi_setAddress(uint8_t address)
* data: pointer to byte array
* length: number of bytes to read into array
* sendStop: Boolean indicating whether to send a stop at the end
+ * timeout_us: number of microseconds to wait for answr, 0 = no timeout
* Output number of bytes read
*/
-uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sendStop)
+uint8_t twi_readFrom_timeout(uint8_t address, uint8_t* data, uint8_t length, uint8_t sendStop, uint32_t timeout_us)
{
uint8_t i;
@@ -121,9 +132,15 @@ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sen
return 0;
}
- // wait until twi is ready, become master receiver
+ // wait until twi is ready, become master receiver, or timeout
+ uint32_t start_us = micros();
while(TWI_READY != twi_state){
- continue;
+ if (timeout_us){
+ if (micros() - start_us > timeout_us){
+ twi_state = TWI_ERROR;
+ return 0;
+ }
+ }
}
twi_state = TWI_MRX;
twi_sendStop = sendStop;
@@ -158,9 +175,15 @@ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sen
// send start condition
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA);
- // wait for read operation to complete
- while(TWI_MRX == twi_state){
- continue;
+ // wait for read operation to complete, or timeout
+ start_us = micros();
+ while(TWI_MRX != twi_state){
+ if (timeout_us){
+ if (micros() - start_us > timeout_us){
+ twi_state = TWI_ERROR;
+ return 0;
+ }
+ }
}
if (twi_masterBufferIndex < length)
@@ -172,8 +195,14 @@ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sen
}
return length;
+
}
+/*
+uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait, uint8_t sendStop){
+ return twi_writeTo_timeout(address, data, length, wait, sendStop, 0);
+}
+*/
/*
* Function twi_writeTo
* Desc attempts to become twi bus master and write a
@@ -183,13 +212,15 @@ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sen
* length: number of bytes in array
* wait: boolean indicating to wait for write or not
* sendStop: boolean indicating whether or not to send a stop at the end
+ * timeout_us: number of microseconds to wait for answr, 0 = no timeout
* Output 0 .. success
* 1 .. length to long for buffer
* 2 .. address send, NACK received
* 3 .. data send, NACK received
* 4 .. other twi error (lost bus arbitration, bus error, ..)
+ * 5 .. timeout
*/
-uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait, uint8_t sendStop)
+uint8_t twi_writeTo_timeout(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait, uint8_t sendStop, uint32_t timeout_us)
{
uint8_t i;
@@ -198,10 +229,18 @@ uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait
return 1;
}
- // wait until twi is ready, become master transmitter
+ // wait until twi is ready, become master transmitter, or timeout
+ uint32_t start_us = micros();
while(TWI_READY != twi_state){
+ if (timeout_us){
+ if (micros() - start_us > timeout_us){
+ twi_state = TWI_ERROR;
+ return 5;
+ }
+ }
continue;
}
+
twi_state = TWI_MTX;
twi_sendStop = sendStop;
// reset error state (0xFF.. no error occured)
@@ -238,8 +277,15 @@ uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait
// send start condition
TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE) | _BV(TWSTA); // enable INTs
- // wait for write operation to complete
- while(wait && (TWI_MTX == twi_state)){
+ // wait for write operation to complete, or timeout
+ start_us = micros();
+ while( wait && (TWI_MTX != twi_state) ){
+ if (timeout_us){
+ if (micros() - start_us > timeout_us){
+ twi_state = TWI_ERROR;
+ return 5;
+ }
+ }
continue;
}
@@ -324,21 +370,32 @@ void twi_reply(uint8_t ack)
}
}
+/*
+void twi_stop(void){
+ twi_stop_timeout(0);
+}
+*/
/*
* Function twi_stop
* Desc relinquishes bus master status
- * Input none
+ * Input timeout_us: number of microseconds to wait for answr, 0 = no timeout
* Output none
*/
-void twi_stop(void)
+void twi_stop_timeout(uint32_t timeout_us)
{
// send stop condition
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO);
- // wait for stop condition to be exectued on bus
+ // wait for stop condition to be exectued on bus, or timeout
// TWINT is not set after a stop condition!
- while(TWCR & _BV(TWSTO)){
- continue;
+ uint32_t start_us = micros();
+ while( TWCR & _BV(TWSTO) ){
+ if (timeout_us){
+ if (micros() - start_us > timeout_us){
+ twi_state = TWI_ERROR;
+ return;
+ }
+ }
}
// update twi state
@@ -381,7 +438,7 @@ ISR(TWI_vect)
twi_reply(1);
}else{
if (twi_sendStop)
- twi_stop();
+ twi_stop_timeout(twi_default_timeout);
else {
twi_inRepStart = true; // we're gonna send the START
// don't enable the interrupt. We'll generate the start, but we
@@ -394,11 +451,11 @@ ISR(TWI_vect)
break;
case TW_MT_SLA_NACK: // address sent, nack received
twi_error = TW_MT_SLA_NACK;
- twi_stop();
+ twi_stop_timeout(twi_default_timeout);
break;
case TW_MT_DATA_NACK: // data sent, nack received
twi_error = TW_MT_DATA_NACK;
- twi_stop();
+ twi_stop_timeout(twi_default_timeout);
break;
case TW_MT_ARB_LOST: // lost bus arbitration
twi_error = TW_MT_ARB_LOST;
@@ -421,7 +478,7 @@ ISR(TWI_vect)
// put final byte into buffer
twi_masterBuffer[twi_masterBufferIndex++] = TWDR;
if (twi_sendStop)
- twi_stop();
+ twi_stop_timeout(twi_default_timeout);
else {
twi_inRepStart = true; // we're gonna send the START
// don't enable the interrupt. We'll generate the start, but we
@@ -432,7 +489,7 @@ ISR(TWI_vect)
}
break;
case TW_MR_SLA_NACK: // address sent, nack received
- twi_stop();
+ twi_stop_timeout(twi_default_timeout);
break;
// TW_MR_ARB_LOST handled by TW_MT_ARB_LOST case
@@ -465,7 +522,7 @@ ISR(TWI_vect)
twi_rxBuffer[twi_rxBufferIndex] = '\0';
}
// sends ack and stops interface for clock stretching
- twi_stop();
+ twi_stop_timeout(twi_default_timeout);
// callback to user defined callback
twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex);
// since we submit rx buffer to "wire" library, we can reset it
@@ -520,7 +577,7 @@ ISR(TWI_vect)
break;
case TW_BUS_ERROR: // bus error, illegal stop/start
twi_error = TW_BUS_ERROR;
- twi_stop();
+ twi_stop_timeout(twi_default_timeout);
break;
}
}
diff --git a/libraries/Wire/utility/twi.h b/libraries/Wire/utility/twi.h
index 6526593394e..2fbe57da67d 100755
--- a/libraries/Wire/utility/twi.h
+++ b/libraries/Wire/utility/twi.h
@@ -37,16 +37,21 @@
#define TWI_MTX 2
#define TWI_SRX 3
#define TWI_STX 4
+ #define TWI_ERROR 5
- void twi_init(void);
+ //void twi_init(void);
+ void twi_init_timeout(uint32_t);
void twi_setAddress(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_readFrom(uint8_t, uint8_t*, uint8_t, uint8_t);
+ uint8_t twi_readFrom_timeout(uint8_t, uint8_t*, uint8_t, uint8_t, uint32_t);
+ //uint8_t twi_writeTo(uint8_t, uint8_t*, uint8_t, uint8_t, uint8_t);
+ uint8_t twi_writeTo_timeout(uint8_t, uint8_t*, uint8_t, uint8_t, uint8_t, uint32_t);
uint8_t twi_transmit(const uint8_t*, uint8_t);
void twi_attachSlaveRxEvent( void (*)(uint8_t*, int) );
void twi_attachSlaveTxEvent( void (*)(void) );
void twi_reply(uint8_t);
- void twi_stop(void);
+ //void twi_stop(void);
+ void twi_stop_timeout(uint32_t);
void twi_releaseBus(void);
#endif