From 0acebeeff48cdb28c602f04e1a5906c6b2149a02 Mon Sep 17 00:00:00 2001 From: "David A. Mellis" Date: Sun, 12 Feb 2012 19:52:03 -0500 Subject: [PATCH 1/5] prog_char -> char PROGMEM in Print.cpp http://code.google.com/p/arduino/issues/detail?id=795 --- hardware/arduino/cores/arduino/Print.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hardware/arduino/cores/arduino/Print.cpp b/hardware/arduino/cores/arduino/Print.cpp index ff9b15459..e541a6ce7 100755 --- a/hardware/arduino/cores/arduino/Print.cpp +++ b/hardware/arduino/cores/arduino/Print.cpp @@ -41,7 +41,7 @@ size_t Print::write(const uint8_t *buffer, size_t size) size_t Print::print(const __FlashStringHelper *ifsh) { - const prog_char *p = (const prog_char *)ifsh; + const char PROGMEM *p = (const char PROGMEM *)ifsh; size_t n = 0; while (1) { unsigned char c = pgm_read_byte(p++); From cb8e184ab8fee1e4564699c4b3e7e3a1e5a48d02 Mon Sep 17 00:00:00 2001 From: "David A. Mellis" Date: Sun, 12 Feb 2012 19:58:40 -0500 Subject: [PATCH 2/5] Using setMinimumSize() instead of window listener for editor windows. http://code.google.com/p/arduino/issues/detail?id=52 --- app/src/processing/app/Editor.java | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/app/src/processing/app/Editor.java b/app/src/processing/app/Editor.java index ba2e641c2..65345016e 100644 --- a/app/src/processing/app/Editor.java +++ b/app/src/processing/app/Editor.java @@ -288,19 +288,9 @@ public class Editor extends JFrame implements RunnerListener { setPlacement(location); - // If the window is resized too small this will resize it again to the - // minimums. Adapted by Chris Lonnen from comments here: - // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4320050 - // as a fix for http://dev.processing.org/bugs/show_bug.cgi?id=25 - final int minW = Preferences.getInteger("editor.window.width.min"); - final int minH = Preferences.getInteger("editor.window.height.min"); - addComponentListener(new java.awt.event.ComponentAdapter() { - public void componentResized(ComponentEvent event) { - setSize((getWidth() < minW) ? minW : getWidth(), - (getHeight() < minH) ? minH : getHeight()); - } - }); - + // Set the minimum size for the editor window + setMinimumSize(new Dimension(Preferences.getInteger("editor.window.width.min"), + Preferences.getInteger("editor.window.height.min"))); // System.out.println("t3"); // Bring back the general options for the editor From 6ab18ea1cc4b4d611f3b2f54d0e53f82c21ab540 Mon Sep 17 00:00:00 2001 From: "David A. Mellis" Date: Tue, 14 Feb 2012 16:13:39 -0800 Subject: [PATCH 3/5] Lowering minimum editor heights for netbooks http://code.google.com/p/arduino/issues/detail?id=52 --- app/src/processing/app/Editor.java | 4 +++- build/shared/lib/preferences.txt | 11 ++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/app/src/processing/app/Editor.java b/app/src/processing/app/Editor.java index 65345016e..7ed0103a8 100644 --- a/app/src/processing/app/Editor.java +++ b/app/src/processing/app/Editor.java @@ -264,7 +264,9 @@ public class Editor extends JFrame implements RunnerListener { splitPane.setDividerSize(dividerSize); } - splitPane.setMinimumSize(new Dimension(600, 400)); + // the following changed from 600, 400 for netbooks + // http://code.google.com/p/arduino/issues/detail?id=52 + splitPane.setMinimumSize(new Dimension(600, 100)); box.add(splitPane); // hopefully these are no longer needed w/ swing diff --git a/build/shared/lib/preferences.txt b/build/shared/lib/preferences.txt index bca71bfd9..3db5b824d 100755 --- a/build/shared/lib/preferences.txt +++ b/build/shared/lib/preferences.txt @@ -76,11 +76,16 @@ editor.window.width.default = 500 editor.window.height.default = 600 editor.window.width.min = 400 -editor.window.height.min = 500 +editor.window.height.min = 290 + +# the following commented out to better support netbooks +# http://code.google.com/p/arduino/issues/detail?id=52 +#editor.window.height.min = 500 # tested as approx 440 on OS X -editor.window.height.min.macosx = 450 +#editor.window.height.min.macosx = 450 # tested to be 515 on Windows XP, this leaves some room -editor.window.height.min.windows = 530 +#editor.window.height.min.windows = 530 + # font size for editor editor.font=Monospaced,plain,12 From 561cd7054d6211cad71d8adbd9b1af3f087cb8c6 Mon Sep 17 00:00:00 2001 From: "David A. Mellis" Date: Tue, 14 Feb 2012 16:41:22 -0800 Subject: [PATCH 4/5] Fixing (maybe) a bug involving multiple received UDP packets. http://code.google.com/p/arduino/issues/detail?id=669 --- libraries/Ethernet/EthernetUdp.cpp | 73 ++++++++++++++++++++++-------- libraries/Ethernet/EthernetUdp.h | 1 + 2 files changed, 55 insertions(+), 19 deletions(-) diff --git a/libraries/Ethernet/EthernetUdp.cpp b/libraries/Ethernet/EthernetUdp.cpp index 9c752fcb6..37600529f 100644 --- a/libraries/Ethernet/EthernetUdp.cpp +++ b/libraries/Ethernet/EthernetUdp.cpp @@ -52,15 +52,16 @@ uint8_t EthernetUDP::begin(uint16_t port) { return 0; _port = port; + _remaining = 0; socket(_sock, SnMR::UDP, _port, 0); return 1; } -/* Is data available in rx buffer? Returns 0 if no, number of available bytes if yes. - * returned value includes 8 byte UDP header!*/ +/* return number of bytes available in the current packet, + will return zero if parsePacket hasn't been called yet */ int EthernetUDP::available() { - return W5100.getRXReceivedSize(_sock); + return _remaining; } /* Release any resources being used by this EthernetUDP instance */ @@ -116,11 +117,14 @@ size_t EthernetUDP::write(const uint8_t *buffer, size_t size) int EthernetUDP::parsePacket() { - if (available() > 0) + // discard any remaining bytes in the last packet + flush(); + + if (W5100.getRXReceivedSize(_sock) > 0) { //HACK - hand-parse the UDP packet using TCP recv method uint8_t tmpBuf[8]; - int ret =0; + int ret =0; //read 8 header bytes and get IP and port from it ret = recv(_sock,tmpBuf,8); if (ret > 0) @@ -128,8 +132,11 @@ int EthernetUDP::parsePacket() _remoteIP = tmpBuf; _remotePort = tmpBuf[4]; _remotePort = (_remotePort << 8) + tmpBuf[5]; + _remaining = tmpBuf[6]; + _remaining = (_remaining << 8) + tmpBuf[7]; + // When we get here, any remaining bytes are the data - ret = available(); + ret = _remaining; } return ret; } @@ -140,34 +147,58 @@ int EthernetUDP::parsePacket() int EthernetUDP::read() { uint8_t byte; - if (recv(_sock, &byte, 1) > 0) + + if ((_remaining > 0) && (recv(_sock, &byte, 1) > 0)) { // We read things without any problems + _remaining--; return byte; } + // If we get here, there's no data available return -1; } int EthernetUDP::read(unsigned char* buffer, size_t len) { - /* In the readPacket that copes with truncating packets, the buffer was - filled with this code. Not sure why it loops round reading out a byte - at a time. - int i; - for(i=0;i<(int)bufLen;i++) { - recv(_sock,tmpBuf,1); - buf[i]=tmpBuf[0]; + + if (_remaining > 0) + { + + int got; + + if (_remaining <= len) + { + // data should fit in the buffer + got = recv(_sock, buffer, _remaining); + } + else + { + // too much data for the buffer, + // grab as much as will fit + got = recv(_sock, buffer, len); + } + + if (got > 0) + { + _remaining -= got; + return got; + } + } - */ - return recv(_sock, buffer, len); + + // If we get here, there's no data available or recv failed + return -1; + } int EthernetUDP::peek() { uint8_t b; - // Unlike recv, peek doesn't check to see if there's any data available, so we must - if (!available()) + // Unlike recv, peek doesn't check to see if there's any data available, so we must. + // If the user hasn't called parsePacket yet then return nothing otherwise they + // may get the UDP header + if (!_remaining) return -1; ::peek(_sock, &b); return b; @@ -175,7 +206,11 @@ int EthernetUDP::peek() void EthernetUDP::flush() { - while (available()) + // could this fail (loop endlessly) if _remaining > 0 and recv in read fails? + // should only occur if recv fails after telling us the data is there, lets + // hope the w5100 always behaves :) + + while (_remaining) { read(); } diff --git a/libraries/Ethernet/EthernetUdp.h b/libraries/Ethernet/EthernetUdp.h index 9a2b653e6..8a6b7ab5a 100644 --- a/libraries/Ethernet/EthernetUdp.h +++ b/libraries/Ethernet/EthernetUdp.h @@ -48,6 +48,7 @@ private: IPAddress _remoteIP; // remote IP address for the incoming packet whilst it's being processed uint16_t _remotePort; // remote port for the incoming packet whilst it's being processed uint16_t _offset; // offset into the packet being sent + uint16_t _remaining; // remaining bytes of incoming packet yet to be processed public: EthernetUDP(); // Constructor From 2f29f898de9c8375b37269c26948be59a515e801 Mon Sep 17 00:00:00 2001 From: "David A. Mellis" Date: Sat, 18 Feb 2012 20:05:11 -0500 Subject: [PATCH 5/5] Adding ability to send repeated starts in Wire library. This adds an additional (boolean) parameter to both endTransmission() and requestFrom(), which specifies whether or not to send a stop condition after the corresponding transmission. This defaults to true, as in the previous behavior of the library. http://code.google.com/p/arduino/issues/detail?id=663 --- libraries/Wire/Wire.cpp | 43 ++++++++++++++++++--- libraries/Wire/Wire.h | 5 +++ libraries/Wire/utility/twi.c | 75 +++++++++++++++++++++++++++++++----- libraries/Wire/utility/twi.h | 4 +- 4 files changed, 111 insertions(+), 16 deletions(-) diff --git a/libraries/Wire/Wire.cpp b/libraries/Wire/Wire.cpp index d83f4789e..4e7a17c47 100755 --- a/libraries/Wire/Wire.cpp +++ b/libraries/Wire/Wire.cpp @@ -15,6 +15,8 @@ You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts */ extern "C" { @@ -73,14 +75,14 @@ void TwoWire::begin(int address) begin((uint8_t)address); } -uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity) +uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop) { // clamp to buffer length if(quantity > BUFFER_LENGTH){ quantity = BUFFER_LENGTH; } // perform blocking read into buffer - uint8_t read = twi_readFrom(address, rxBuffer, quantity); + uint8_t read = twi_readFrom(address, rxBuffer, quantity, sendStop); // set rx buffer iterator vars rxBufferIndex = 0; rxBufferLength = read; @@ -88,9 +90,19 @@ uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity) return read; } +uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity) +{ + return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true); +} + uint8_t TwoWire::requestFrom(int address, int quantity) { - return requestFrom((uint8_t)address, (uint8_t)quantity); + return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true); +} + +uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop) +{ + return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)sendStop); } void TwoWire::beginTransmission(uint8_t address) @@ -109,10 +121,23 @@ void TwoWire::beginTransmission(int address) beginTransmission((uint8_t)address); } -uint8_t TwoWire::endTransmission(void) +// +// Originally, 'endTransmission' was an f(void) function. +// It has been modified to take one parameter indicating +// whether or not a STOP should be performed on the bus. +// Calling endTransmission(false) allows a sketch to +// perform a repeated start. +// +// WARNING: Nothing in the library keeps track of whether +// the bus tenure has been properly ended with a STOP. It +// is very possible to leave the bus in a hung state if +// 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) { // transmit buffer (blocking) - int8_t ret = twi_writeTo(txAddress, txBuffer, txBufferLength, 1); + int8_t ret = twi_writeTo(txAddress, txBuffer, txBufferLength, 1, sendStop); // reset tx buffer iterator vars txBufferIndex = 0; txBufferLength = 0; @@ -121,6 +146,14 @@ uint8_t TwoWire::endTransmission(void) return ret; } +// This provides backwards compatibility with the original +// definition, and expected behaviour, of endTransmission +// +uint8_t TwoWire::endTransmission(void) +{ + return endTransmission(true); +} + // must be called in: // slave tx event callback // or after beginTransmission(address) diff --git a/libraries/Wire/Wire.h b/libraries/Wire/Wire.h index 9ea4afd30..a93d0f5bb 100755 --- a/libraries/Wire/Wire.h +++ b/libraries/Wire/Wire.h @@ -15,6 +15,8 @@ You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts */ #ifndef TwoWire_h @@ -50,8 +52,11 @@ class TwoWire : public Stream void beginTransmission(uint8_t); void beginTransmission(int); uint8_t endTransmission(void); + uint8_t endTransmission(uint8_t); uint8_t requestFrom(uint8_t, uint8_t); + uint8_t requestFrom(uint8_t, uint8_t, uint8_t); uint8_t requestFrom(int, int); + uint8_t requestFrom(int, int, int); virtual size_t write(uint8_t); virtual size_t write(const uint8_t *, size_t); virtual int available(void); diff --git a/libraries/Wire/utility/twi.c b/libraries/Wire/utility/twi.c index d80114b6e..6b2db3cdc 100644 --- a/libraries/Wire/utility/twi.c +++ b/libraries/Wire/utility/twi.c @@ -15,6 +15,8 @@ You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts */ #include @@ -37,14 +39,16 @@ #include "twi.h" static volatile uint8_t twi_state; -static uint8_t twi_slarw; +static volatile uint8_t twi_slarw; +static volatile uint8_t twi_sendStop; // should the transaction end with a stop +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 uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH]; static volatile uint8_t twi_masterBufferIndex; -static uint8_t twi_masterBufferLength; +static volatile uint8_t twi_masterBufferLength; static uint8_t twi_txBuffer[TWI_BUFFER_LENGTH]; static volatile uint8_t twi_txBufferIndex; @@ -65,6 +69,8 @@ void twi_init(void) { // initialize state twi_state = TWI_READY; + twi_sendStop = true; // default value + twi_inRepStart = false; // activate internal pullups for twi. digitalWrite(SDA, 1); @@ -103,9 +109,10 @@ 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 + * sendStop: Boolean indicating whether to send a stop at the end * Output number of bytes read */ -uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length) +uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sendStop) { uint8_t i; @@ -119,6 +126,7 @@ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length) continue; } twi_state = TWI_MRX; + twi_sendStop = sendStop; // reset error state (0xFF.. no error occured) twi_error = 0xFF; @@ -135,8 +143,20 @@ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length) twi_slarw = TW_READ; twi_slarw |= address << 1; - // send start condition - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA); + if (true == twi_inRepStart) { + // if we're in the repeated start state, then we've already sent the start, + // (@@@ we hope), and the TWI statemachine is just waiting for the address byte. + // We need to remove ourselves from the repeated start state before we enable interrupts, + // since the ISR is ASYNC, and we could get confused if we hit the ISR before cleaning + // up. Also, don't enable the START interrupt. There may be one pending from the + // repeated start that we sent outselves, and that would really confuse things. + twi_inRepStart = false; // remember, we're dealing with an ASYNC ISR + TWDR = twi_slarw; + TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START + } + else + // 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){ @@ -162,13 +182,14 @@ 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 + * sendStop: boolean indicating whether or not to send a stop at the end * 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) +uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait, uint8_t sendStop) { uint8_t i; @@ -182,6 +203,7 @@ uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait continue; } twi_state = TWI_MTX; + twi_sendStop = sendStop; // reset error state (0xFF.. no error occured) twi_error = 0xFF; @@ -198,8 +220,23 @@ uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait twi_slarw = TW_WRITE; twi_slarw |= address << 1; - // send start condition - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA); + // if we're in a repeated start, then we've already sent the START + // in the ISR. Don't do it again. + // + if (true == twi_inRepStart) { + // if we're in the repeated start state, then we've already sent the start, + // (@@@ we hope), and the TWI statemachine is just waiting for the address byte. + // We need to remove ourselves from the repeated start state before we enable interrupts, + // since the ISR is ASYNC, and we could get confused if we hit the ISR before cleaning + // up. Also, don't enable the START interrupt. There may be one pending from the + // repeated start that we sent outselves, and that would really confuse things. + twi_inRepStart = false; // remember, we're dealing with an ASYNC ISR + TWDR = twi_slarw; + TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START + } + else + // 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)){ @@ -343,7 +380,16 @@ SIGNAL(TWI_vect) TWDR = twi_masterBuffer[twi_masterBufferIndex++]; twi_reply(1); }else{ - twi_stop(); + if (twi_sendStop) + twi_stop(); + else { + twi_inRepStart = true; // we're gonna send the START + // don't enable the interrupt. We'll generate the start, but we + // avoid handling the interrupt until we're in the next transaction, + // at the point where we would normally issue the start. + TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ; + twi_state = TWI_READY; + } } break; case TW_MT_SLA_NACK: // address sent, nack received @@ -374,6 +420,17 @@ SIGNAL(TWI_vect) case TW_MR_DATA_NACK: // data received, nack sent // put final byte into buffer twi_masterBuffer[twi_masterBufferIndex++] = TWDR; + if (twi_sendStop) + twi_stop(); + else { + twi_inRepStart = true; // we're gonna send the START + // don't enable the interrupt. We'll generate the start, but we + // avoid handling the interrupt until we're in the next transaction, + // at the point where we would normally issue the start. + TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ; + twi_state = TWI_READY; + } + break; case TW_MR_SLA_NACK: // address sent, nack received twi_stop(); break; diff --git a/libraries/Wire/utility/twi.h b/libraries/Wire/utility/twi.h index 831b9282a..652659339 100755 --- a/libraries/Wire/utility/twi.h +++ b/libraries/Wire/utility/twi.h @@ -40,8 +40,8 @@ void twi_init(void); void twi_setAddress(uint8_t); - 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_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_attachSlaveTxEvent( void (*)(void) );