From 0bdc02cea5c0a1cd28f3999c70c2f879db12b6db Mon Sep 17 00:00:00 2001 From: "David A. Mellis" Date: Sat, 21 Jun 2008 23:16:27 +0000 Subject: [PATCH] Wire library patch to provide better error handling. --- hardware/cores/arduino/Print.cpp | 2 +- hardware/libraries/Wire/Wire.cpp | 17 +++++++------ hardware/libraries/Wire/Wire.h | 6 ++--- hardware/libraries/Wire/utility/twi.c | 36 +++++++++++++++++++++++---- hardware/libraries/Wire/utility/twi.h | 12 ++++----- todo.txt | 21 ++++++++++------ 6 files changed, 65 insertions(+), 29 deletions(-) diff --git a/hardware/cores/arduino/Print.cpp b/hardware/cores/arduino/Print.cpp index d150b750c..feff940a5 100755 --- a/hardware/cores/arduino/Print.cpp +++ b/hardware/cores/arduino/Print.cpp @@ -30,7 +30,7 @@ void Print::print(uint8_t b) { - write(b); + this->write(b); } void Print::print(char c) diff --git a/hardware/libraries/Wire/Wire.cpp b/hardware/libraries/Wire/Wire.cpp index 73369b3e4..0ee301203 100755 --- a/hardware/libraries/Wire/Wire.cpp +++ b/hardware/libraries/Wire/Wire.cpp @@ -77,22 +77,24 @@ void TwoWire::begin(int address) begin((uint8_t)address); } -void TwoWire::requestFrom(uint8_t address, uint8_t quantity) +uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity) { // clamp to buffer length if(quantity > BUFFER_LENGTH){ quantity = BUFFER_LENGTH; } // perform blocking read into buffer - twi_readFrom(address, rxBuffer, quantity); + uint8_t read = twi_readFrom(address, rxBuffer, quantity); // set rx buffer iterator vars rxBufferIndex = 0; - rxBufferLength = quantity; + rxBufferLength = read; + + return read; } -void TwoWire::requestFrom(int address, int quantity) +uint8_t TwoWire::requestFrom(int address, int quantity) { - requestFrom((uint8_t)address, (uint8_t)quantity); + return requestFrom((uint8_t)address, (uint8_t)quantity); } void TwoWire::beginTransmission(uint8_t address) @@ -111,15 +113,16 @@ void TwoWire::beginTransmission(int address) beginTransmission((uint8_t)address); } -void TwoWire::endTransmission(void) +uint8_t TwoWire::endTransmission(void) { // transmit buffer (blocking) - twi_writeTo(txAddress, txBuffer, txBufferLength, 1); + int8_t ret = twi_writeTo(txAddress, txBuffer, txBufferLength, 1); // reset tx buffer iterator vars txBufferIndex = 0; txBufferLength = 0; // indicate that we are done transmitting transmitting = 0; + return ret; } // must be called in: diff --git a/hardware/libraries/Wire/Wire.h b/hardware/libraries/Wire/Wire.h index 9c91b9b39..9e849d5e1 100755 --- a/hardware/libraries/Wire/Wire.h +++ b/hardware/libraries/Wire/Wire.h @@ -48,9 +48,9 @@ class TwoWire void begin(int); void beginTransmission(uint8_t); void beginTransmission(int); - void endTransmission(void); - void requestFrom(uint8_t, uint8_t); - void requestFrom(int, int); + uint8_t endTransmission(void); + uint8_t requestFrom(uint8_t, uint8_t); + uint8_t requestFrom(int, int); void send(uint8_t); void send(uint8_t*, uint8_t); void send(int); diff --git a/hardware/libraries/Wire/utility/twi.c b/hardware/libraries/Wire/utility/twi.c index 563b41b36..3e5489ffa 100644 --- a/hardware/libraries/Wire/utility/twi.c +++ b/hardware/libraries/Wire/utility/twi.c @@ -51,6 +51,8 @@ static volatile uint8_t twi_txBufferLength; static uint8_t* twi_rxBuffer; static volatile uint8_t twi_rxBufferIndex; +static volatile uint8_t twi_error; + /* * Function twi_init * Desc readys twi pins and sets twi bitrate @@ -112,7 +114,7 @@ void twi_setAddress(uint8_t address) * Input address: 7bit i2c device address * data: pointer to byte array * length: number of bytes to read into array - * Output byte: 0 ok, 1 length too long for buffer + * Output number of bytes read */ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length) { @@ -120,7 +122,7 @@ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length) // ensure data will fit into buffer if(TWI_BUFFER_LENGTH < length){ - return 1; + return 0; } // wait until twi is ready, become master receiver @@ -128,6 +130,8 @@ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length) continue; } twi_state = TWI_MRX; + // reset error state (0xFF.. no error occured) + twi_error = 0xFF; // initialize buffer iteration vars twi_masterBufferIndex = 0; @@ -145,12 +149,15 @@ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length) continue; } + if (twi_masterBufferIndex < length) + length = twi_masterBufferIndex; + // copy twi buffer to data for(i = 0; i < length; ++i){ data[i] = twi_masterBuffer[i]; } - return 0; + return length; } /* @@ -161,7 +168,11 @@ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length) * data: pointer to byte array * length: number of bytes in array * wait: boolean indicating to wait for write or not - * Output byte: 0 ok, 1 length too long for buffer + * 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, ..) */ uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait) { @@ -177,6 +188,8 @@ uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait continue; } twi_state = TWI_MTX; + // reset error state (0xFF.. no error occured) + twi_error = 0xFF; // initialize buffer iteration vars twi_masterBufferIndex = 0; @@ -199,7 +212,14 @@ uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait continue; } - return 0; + if (twi_error == 0xFF) + return 0; // success + else if (twi_error == TW_MT_SLA_NACK) + return 2; // error: address send, nack received + else if (twi_error == TW_MT_DATA_NACK) + return 3; // error: data send, nack received + else + return 4; // other twi error } /* @@ -333,10 +353,15 @@ SIGNAL(SIG_2WIRE_SERIAL) } break; case TW_MT_SLA_NACK: // address sent, nack received + twi_error = TW_MT_SLA_NACK; + twi_stop(); + break; case TW_MT_DATA_NACK: // data sent, nack received + twi_error = TW_MT_DATA_NACK; twi_stop(); break; case TW_MT_ARB_LOST: // lost bus arbitration + twi_error = TW_MT_ARB_LOST; twi_releaseBus(); break; @@ -441,6 +466,7 @@ SIGNAL(SIG_2WIRE_SERIAL) case TW_NO_INFO: // no state information break; case TW_BUS_ERROR: // bus error, illegal stop/start + twi_error = TW_BUS_ERROR; twi_stop(); break; } diff --git a/hardware/libraries/Wire/utility/twi.h b/hardware/libraries/Wire/utility/twi.h index 7ccbf5caf..1258d8d38 100755 --- a/hardware/libraries/Wire/utility/twi.h +++ b/hardware/libraries/Wire/utility/twi.h @@ -17,18 +17,18 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef twi_h -#define twi_h +#ifndef twi_h +#define twi_h #include //#define ATMEGA8 - #ifndef CPU_FREQ + #ifndef CPU_FREQ #define CPU_FREQ 16000000L #endif - #ifndef TWI_FREQ + #ifndef TWI_FREQ #define TWI_FREQ 100000L #endif @@ -51,7 +51,7 @@ void twi_attachSlaveTxEvent( void (*)(void) ); void twi_reply(uint8_t); void twi_stop(void); - void twi_releaseBus(void); - + void twi_releaseBus(void); + #endif diff --git a/todo.txt b/todo.txt index 3174047f8..baa8bb5fb 100644 --- a/todo.txt +++ b/todo.txt @@ -9,7 +9,6 @@ Add String library. Add Servo library. Comment LiquidCrystal examples. Write LiquidCrystal documentation. -Wire library patch: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1206621511 [done] Move #include after other #include's? (prevent it from interfering with standard libraries) [done] Add LiquidCrystal library. [done] Fix millis() so it overflows on a nice variable-size boundary; see: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1205949448 @@ -18,7 +17,7 @@ Wire library patch: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1206621511 AVR Support pin change interrupts. -Fix interference between millis() / timer 0 overflow interrupt and pwm output on pins 5 and 6. +Switch pwm output on pins 5 and 6 to phase-correct mode, if possible. Problems including WProgram.h twice? Add #defines for the analog input pins. Add parameter to shiftOut() for specifying a number of bits. @@ -32,6 +31,7 @@ Way to print floats. Fix delayMicroseconds(0). Add sleep function(s). Add SPI library. +Add OneWire library. Add pulseOut(), etc. functions from Wiring. Add Ping example. Supporting EEMEM directive by changing compiler command line: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1202157667 @@ -84,7 +84,6 @@ Create form for submitting projects. DOCUMENTATION / META -Create community to do list. Create community section of site. List of examples we'd like to have. Style guide for examples, references, and foundations. @@ -99,18 +98,22 @@ Move Environment into the Reference section (which should be renamed Programming DOCUMENTATION / CONTENTS Document Matrix, Sprite, and Wire libraries on the Arduino site. -Add examples using specific hardware (simple analog sensors, optocouplers, etc.) -Get good top-down, well-lit, plain-white-background photos of the Arduino boards. Documentation for moving from Arduino to custom PCBs. -Examples should demonstrate use of functions. Arduino feature list (in Getting Started > Introduction). Programming tutorial for Arduino. Write advanced library tutorial. Better documentation of the Arduino BT. Tutorial about serial communication. +DOCUMENTATION / EXAMPLES + +Add examples using specific hardware (simple analog sensors, optocouplers, etc.) +Examples should demonstrate use of functions. +Add I2C EEPROM example using Wire library. + DOCUMENTATION / IMAGES +Get good top-down, well-lit, plain-white-background photos of the Arduino boards. Replace rainbow diagram on the guide to the board page. Update pictures to use Arduino Diecimila: Guide/Board, tutorials, Create diagrams and schematics for the examples. @@ -121,4 +124,8 @@ Consider deleting many of the pictures in the howto's as they just make it harde Tell people not to put the board on a Powerbook. People don't know what a jumper is. Add picture of the RX/TX LEDs flashing. -Show a picture of the LED flashing. \ No newline at end of file +Show a picture of the LED flashing. + +DOCUMENTATION / TROUBLESHOOTING + +Add explanation of how to work around auto-reset. \ No newline at end of file