Library for HopeRF RFM22 / RFM22B transceiver module ported to mbed. Original Software from Mike McCauley (mikem@open.com.au) . See http://www.open.com.au/mikem/arduino/RF22/

Dependents:   RF22_MAX_test_Send Geofence_receiver Geofence_sender Geofence_sender ... more

More Info about RFM22-modules like connecting and a demo-program see RF22-Notebook

Files at this revision

API Documentation at this revision

Comitter:
charly
Date:
Sat Mar 02 20:49:07 2013 +0000
Parent:
4:f0bf38bb0ff8
Child:
6:468dc5b3942f
Commit message:
Updated to Revision 1.25 of original package

Changed in this revision

RF22.cpp Show annotated file Show diff for this revision Revisions of this file
RF22.h Show annotated file Show diff for this revision Revisions of this file
RF22Datagram.cpp Show annotated file Show diff for this revision Revisions of this file
RF22Datagram.h Show annotated file Show diff for this revision Revisions of this file
RF22Mesh.cpp Show annotated file Show diff for this revision Revisions of this file
RF22Mesh.h Show annotated file Show diff for this revision Revisions of this file
RF22ReliableDatagram.cpp Show annotated file Show diff for this revision Revisions of this file
RF22ReliableDatagram.h Show annotated file Show diff for this revision Revisions of this file
RF22Router.cpp Show annotated file Show diff for this revision Revisions of this file
RF22Router.h Show annotated file Show diff for this revision Revisions of this file
--- a/RF22.cpp	Sun Feb 19 21:12:10 2012 +0000
+++ b/RF22.cpp	Sat Mar 02 20:49:07 2013 +0000
@@ -1,7 +1,7 @@
 // RF22.cpp
 //
 // Copyright (C) 2011 Mike McCauley
-// $Id: RF22.cpp,v 1.13 2011/10/09 21:22:24 mikem Exp mikem $
+// $Id: RF22.cpp,v 1.17 2013/02/06 21:33:56 mikem Exp mikem $
 // ported to mbed by Karl Zweimueller
 
 
@@ -17,13 +17,14 @@
 
 // These are indexed by the values of ModemConfigChoice
 // Canned modem configurations generated with 
-// 'http://www.hoperf.com/upfile/RF22B 23B 31B 42B 43B Register Settings_RevB1-v5.xls'
+// http://www.hoperf.com/upload/rf/RF22B%2023B%2031B%2042B%2043B%20Register%20Settings_RevB1-v5.xls
 // Stored in flash (program) memory to save SRAM
 /*PROGMEM */ static const RF22::ModemConfig MODEM_CONFIG_TABLE[] =
 {
     { 0x2b, 0x03, 0xf4, 0x20, 0x41, 0x89, 0x00, 0x36, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x10, 0x62, 0x2c, 0x00, 0x08 }, // Unmodulated carrier
     { 0x2b, 0x03, 0xf4, 0x20, 0x41, 0x89, 0x00, 0x36, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x10, 0x62, 0x2c, 0x33, 0x08 }, // FSK, PN9 random modulation, 2, 5
 
+    // All the following enable FIFO with reg 71
     //  1c,   1f,   20,   21,   22,   23,   24,   25,   2c,   2d,   2e,   58,   69,   6e,   6f,   70,   71,   72
     // FSK, No Manchester, Max Rb err <1%, Xtal Tol 20ppm
     { 0x2b, 0x03, 0xf4, 0x20, 0x41, 0x89, 0x00, 0x36, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x10, 0x62, 0x2c, 0x22, 0x08 }, // 2, 5
@@ -167,9 +168,8 @@
     spiWrite(RF22_REG_05_INTERRUPT_ENABLE1, RF22_ENTXFFAEM | RF22_ENRXFFAFULL | RF22_ENPKSENT | RF22_ENPKVALID | RF22_ENCRCERROR | RF22_ENFFERR);
     spiWrite(RF22_REG_06_INTERRUPT_ENABLE2, RF22_ENPREAVAL);
 
-    // Set some defaults. An innocuous ISM frequency
-    setFrequency(868.0);
-//    setFrequency(434.0);
+    // Set some defaults. An innocuous ISM frequency, and reasonable pull-in
+    setFrequency(434.0, 0.05);
 //    setFrequency(900.0);
     // Some slow, reliable default speed and modulation
     setModemConfig(FSK_Rb2_4Fd36);
@@ -181,7 +181,7 @@
 // Set the AFC for receiver to max. 0,1MHz
 // Other AFC-Registers have PowerOnValues which enable AFC
 // RF22_AFC_LIMIT                          0x50   =0,1MHz
-   spiWrite(RF22_REG_2A_AFC_LIMITER, RF22_AFC_LIMIT);  // POR=0x00 = OFF
+//   spiWrite(RF22_REG_2A_AFC_LIMITER, RF22_AFC_LIMIT);  // POR=0x00 = OFF
 
     return true;
 }
@@ -197,7 +197,8 @@
     spiBurstRead(RF22_REG_03_INTERRUPT_STATUS1, _lastInterruptFlags, 2);
 
 #if 0
-    pc.print("interrupt ");
+    // Caution: Serial printing in this interrupt routine can cause mysterious crashes
+    Serial.print("interrupt ");
     Serial.print(_lastInterruptFlags[0], HEX);
     Serial.print(" ");
     Serial.println(_lastInterruptFlags[1], HEX);
@@ -205,7 +206,7 @@
     Serial.println("FUNNY: no interrupt!");
 #endif
 
-/*
+#if 0
     // TESTING: fake an RF22_IFFERROR
     static int counter = 0;
     if (_lastInterruptFlags[0] & RF22_IPKSENT && counter++ == 10)
@@ -213,7 +214,7 @@
     _lastInterruptFlags[0] = RF22_IFFERROR;
     counter = 0;
     }
-*/
+#endif
 
     if (_lastInterruptFlags[0] & RF22_IFFERROR)
     {
@@ -229,7 +230,7 @@
     {
     // See if more data has to be loaded into the Tx FIFO 
     sendNextFragment();
-//    Serial.println("TXFFAEM");  
+//  Serial.println("ITXFFAEM");  
     }
     if (_lastInterruptFlags[0] & RF22_IRXFFAFULL)
     {
@@ -252,28 +253,42 @@
     }
     if (_lastInterruptFlags[0] & RF22_IPKSENT)
     {
-//    Serial.println("PKSENT");   
+//  Serial.println("IPKSENT");   
     _txGood++; 
     led4 = !led4;
     // Transmission does not automatically clear the tx buffer.
     // Could retransmit if we wanted
-    _txPacketSent = true;
     // RF22 transitions automatically to Idle
     _mode = RF22_MODE_IDLE;
     }
     if (_lastInterruptFlags[0] & RF22_IPKVALID)
     {
-//    Serial.println("IPKVALID");    
     uint8_t len = spiRead(RF22_REG_4B_RECEIVED_PACKET_LENGTH);
+//  Serial.println("IPKVALID");   
+//  Serial.println(len);   
+//  Serial.println(_bufLen);   
+
     // May have already read one or more fragments
     // Get any remaining unread octets, based on the expected length
-    len -= _bufLen;
-    spiBurstRead(RF22_REG_7F_FIFO_ACCESS, _buf + _bufLen, len);
+    // First make sure we dont overflow the buffer in the case of a stupid length
+    // or partial bad receives
+    if (   len >  RF22_MAX_MESSAGE_LEN
+        || len < _bufLen)
+    {
+        _rxBad++;
+        _mode = RF22_MODE_IDLE;
+        clearRxBuf();
+        return; // Hmmm receiver buffer overflow. 
+    }
+
+    spiBurstRead(RF22_REG_7F_FIFO_ACCESS, _buf + _bufLen, len - _bufLen);
     _rxGood++;
-    led3 = !led3;
-    _bufLen += len;
+    _bufLen = len;
     _mode = RF22_MODE_IDLE;
     _rxBufValid = true;
+
+    led3 = !led3;
+
     }
     if (_lastInterruptFlags[0] & RF22_ICRCERROR)
     {
@@ -287,7 +302,7 @@
     }
     if (_lastInterruptFlags[1] & RF22_IPREAVAL)
     {
-//    Serial.println("ENPREAVAL");  
+//  Serial.println("IPREAVAL");  
     _lastRssi = spiRead(RF22_REG_26_RSSI);
     clearRxBuf();
     }
@@ -350,7 +365,7 @@
     _slaveSelectPin = 1;
 }
 
-void RF22::spiBurstWrite(uint8_t reg, uint8_t* src, uint8_t len)
+void RF22::spiBurstWrite(uint8_t reg, const uint8_t* src, uint8_t len)
 {
     //digitalWrite(_slaveSelectPin, LOW);
     _slaveSelectPin = 0;
@@ -409,17 +424,27 @@
 }
 
 // Returns true if centre + (fhch * fhs) is within limits
-// Caution, different versions of the RF22 suport different max freq
+// Caution, different versions of the RF22 support different max freq
 // so YMMV
-boolean RF22::setFrequency(float centre)
+boolean RF22::setFrequency(float centre, float afcPullInRange)
 {
     uint8_t fbsel = RF22_SBSEL;
+    uint8_t afclimiter;
     if (centre < 240.0 || centre > 960.0) // 930.0 for early silicon
     return false;
     if (centre >= 480.0)
     {
+    if (afcPullInRange < 0.0 || afcPullInRange > 0.318750)
+        return false;
     centre /= 2;
     fbsel |= RF22_HBSEL;
+    afclimiter = afcPullInRange * 1000000.0 / 1250.0;
+    }
+    else
+    {
+    if (afcPullInRange < 0.0 || afcPullInRange > 0.159375)
+        return false;
+    afclimiter = afcPullInRange * 1000000.0 / 625.0;
     }
     centre /= 10.0;
     float integerPart = floor(centre);
@@ -433,6 +458,7 @@
     spiWrite(RF22_REG_75_FREQUENCY_BAND_SELECT, fbsel);
     spiWrite(RF22_REG_76_NOMINAL_CARRIER_FREQUENCY1, fc >> 8);
     spiWrite(RF22_REG_77_NOMINAL_CARRIER_FREQUENCY0, fc & 0xff);
+    spiWrite(RF22_REG_2A_AFC_LIMITER, afclimiter);
     return !(statusRead() & RF22_FREQERR);
 }
 
@@ -491,7 +517,17 @@
     {
     setMode(_idleMode | RF22_TXON);
     _mode = RF22_MODE_TX;
+    // Hmmm, if you dont clear the RX FIFO here, then it appears that going
+    // to transmit mode in the middle of a receive can corrupt the
+    // RX FIFO
+    resetRxFifo();
+    clearRxBuf();
     }
+    }
+
+uint8_t  RF22::mode()
+{
+    return _mode;
 }
 
 void RF22::setTxPower(uint8_t power)
@@ -500,7 +536,7 @@
 }
 
 // Sets registers from a canned modem configuration structure
-void RF22::setModemRegisters(ModemConfig* config)
+void RF22::setModemRegisters(const ModemConfig* config)
 {
     spiWrite(RF22_REG_1C_IF_FILTER_BANDWIDTH,                    config->reg_1c);
     spiWrite(RF22_REG_1F_CLOCK_RECOVERY_GEARSHIFT_OVERRIDE,      config->reg_1f);
@@ -532,7 +568,7 @@
 }
 
 // Caution doesnt set sync word len in Header Control 2 0x33
-void RF22::setSyncWords(uint8_t* syncWords, uint8_t len)
+void RF22::setSyncWords(const uint8_t* syncWords, uint8_t len)
 {
     spiBurstWrite(RF22_REG_36_SYNC_WORD3, syncWords, len);
 }
@@ -545,7 +581,8 @@
 
 boolean RF22::available()
 {
-    setModeRx();
+    if (!_rxBufValid)
+    setModeRx(); // Make sure we are receiving
     return _rxBufValid;
 }
 
@@ -571,8 +608,29 @@
 
 void RF22::waitPacketSent()
 {
-    while (!_txPacketSent)
-    ;
+    while (_mode == RF22_MODE_TX)
+    ; // Wait for any previous transmit to finish
+}
+
+// Diagnostic help
+void RF22::printBuffer(const char* prompt, const uint8_t* buf, uint8_t len)
+{
+#ifdef RF22_HAVE_SERIAL
+    uint8_t i;
+
+    Serial.println(prompt);
+    for (i = 0; i < len; i++)
+    {
+    if (i % 16 == 15)
+        Serial.println(buf[i], HEX);
+    else
+    {
+        Serial.print(buf[i], HEX);
+        Serial.print(' ');
+    }
+    }
+    Serial.println(' ');
+#endif
 }
 
 boolean RF22::recv(uint8_t* buf, uint8_t* len)
@@ -583,6 +641,8 @@
     *len = _bufLen;
     memcpy(buf, _buf, *len);
     clearRxBuf();
+//    printBuffer("recv:", buf, *len);
+//    }
     return true;
 }
 
@@ -600,36 +660,44 @@
     setModeTx(); // Start the transmitter, turns off the receiver
 }
 
-// Restart the trasnmission of a packet that had a problem
+// Restart the transmission of a packet that had a problem
 void RF22::restartTransmit()
 {
     _mode = RF22_MODE_IDLE;
     _txBufSentIndex = 0;
-    _txPacketSent = false;
 //        Serial.println("Restart");
     startTransmit();
 }
 
-boolean RF22::send(uint8_t* data, uint8_t len)
+boolean RF22::send(const uint8_t* data, uint8_t len)
 {
-    setModeIdle();
-    fillTxBuf(data, len);
+    waitPacketSent();
+//    ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+    {
+    if (!fillTxBuf(data, len))
+        return false;
     startTransmit();
+    }
+//    printBuffer("send:", data, len);
     return true;
 }
 
-boolean RF22::fillTxBuf(uint8_t* data, uint8_t len)
+boolean RF22::fillTxBuf(const uint8_t* data, uint8_t len)
 {
     clearTxBuf();
+    if (!len)
+    return false; 
     return appendTxBuf(data, len);
 }
 
-boolean RF22::appendTxBuf(uint8_t* data, uint8_t len)
+boolean RF22::appendTxBuf(const uint8_t* data, uint8_t len)
 {
     if (((uint16_t)_bufLen + len) > RF22_MAX_MESSAGE_LEN)
     return false;
     memcpy(_buf + _bufLen, data, len);
     _bufLen += len;
+    
+//    printBuffer("txbuf:", _buf, _bufLen);
     return true;
 }
 
@@ -638,7 +706,7 @@
 {
     if (_txBufSentIndex < _bufLen)
     {
-    // Some left to send
+    // Some left to send?
     uint8_t len = _bufLen - _txBufSentIndex;
     // But dont send too much
     if (len > (RF22_FIFO_SIZE - RF22_TXFFAEM_THRESHOLD - 1))
@@ -649,14 +717,12 @@
 }
 
 // Assumption: there are at least RF22_RXFFAFULL_THRESHOLD in the RX FIFO
-// That means it should only be called after a RXAFULL interrupt
+// That means it should only be called after a RXFFAFULL interrupt
 void RF22::readNextFragment()
 {
     if (((uint16_t)_bufLen + RF22_RXFFAFULL_THRESHOLD) > RF22_MAX_MESSAGE_LEN)
-    {
-    // Hmmm receiver overflow. Should never occur
-    return;
-    }
+    return; // Hmmm receiver overflow. Should never occur
+
     // Read the RF22_RXFFAFULL_THRESHOLD octets that should be there
     spiBurstRead(RF22_REG_7F_FIFO_ACCESS, _buf + _bufLen, RF22_RXFFAFULL_THRESHOLD);
     _bufLen += RF22_RXFFAFULL_THRESHOLD;
--- a/RF22.h	Sun Feb 19 21:12:10 2012 +0000
+++ b/RF22.h	Sat Mar 02 20:49:07 2013 +0000
@@ -1,15 +1,17 @@
 // RF22.h
 // Author: Mike McCauley (mikem@open.com.au)
 // Copyright (C) 2011 Mike McCauley
-// $Id: RF22.h,v 1.19 2011/10/09 21:22:24 mikem Exp mikem $
+// $Id: RF22.h,v 1.23 2013/02/06 21:33:56 mikem Exp mikem $
+//
 // ported to mbed by Karl Zweimueller
-//
 /// \mainpage RF22 library for Arduino
 ///
 /// This is the Arduino RF22 library.
 /// It provides an object-oriented interface for sending and receiving data messages with Hope-RF
-/// RF22B based radio modules, and compatible chips and modules, including the RFM22B transceiver module such as 
-/// this one: http://www.sparkfun.com/products/10153
+/// RF22B based radio modules, and compatible chips and modules, 
+/// including the RFM22B transceiver module such as 
+/// this bare module: http://www.sparkfun.com/products/10153
+/// and this shield: https://www.sparkfun.com/products/11018
 ///
 /// RF22 also supports some of the features of ZigBee and XBee, 
 /// (such as mesh routing and automatic route discovery), 
@@ -48,9 +50,13 @@
 /// Example Arduino programs are included to show the main modes of use.
 ///
 /// The version of the package that this documentation refers to can be downloaded 
-/// from http://www.open.com.au/mikem/arduino/RF22/RF22-1.10.zip
+/// from http://www.open.com.au/mikem/arduino/RF22/RF22-1.25.zip
 /// You can find the latest version at http://www.open.com.au/mikem/arduino/RF22
 ///
+/// You can also find online help and disussion at http://groups.google.com/group/rf22-arduino
+/// Please use that group for all questions and discussions on this topic. 
+/// Do not contact the author directly, unless it is to discuss commercial licensing.
+///
 /// Tested on Arduino Diecimila and Mega with arduino-0021 
 /// on OpenSuSE 11.1 and avr-libc-1.6.1-1.15,
 /// cross-avr-binutils-2.19-9.1, cross-avr-gcc-4.1.3_20080612-26.5.
@@ -75,6 +81,11 @@
 /// 'Virtual Wire' http://www.open.com.au/mikem/arduino/VirtualWire.pdf also from the same author.
 ///
 /// \par Connecting RFM-22 to Arduino
+///
+/// If you have the Sparkfun RFM22 Shield (https://www.sparkfun.com/products/11018)
+/// the connections described below are done for you on the shield, no changes required, 
+/// just add headers and plug it in to an Arduino (but not and Arduino Mega, see below)
+///
 /// The physical connection between the RF22B and the Arduino require 3.3V, the 3 x SPI pins (SCK, SDI, SDO), 
 /// a Slave Select pin and an interrupt pin.
 /// Note also that on the RFF22B, it is required to control the TX_ANT and X_ANT pins of the RFM22 in order to enable the
@@ -105,7 +116,7 @@
 ///                              SDN-/ (shutdown in)
 ///                 3V3----------VCC   (3.3V in)
 /// interrupt 0 pin D2-----------NIRQ  (interrupt request out)
-///          SS pin D10----------NSEL  (chip select in)
+///          SS pin D53----------NSEL  (chip select in)
 ///         SCK pin D52----------SCK   (SPI clock in)
 ///        MOSI pin D51----------SDI   (SPI Data in)
 ///        MISO pin D50----------SDO   (SPI data out)
@@ -116,27 +127,37 @@
 /// \endcode
 /// and you can then use the default constructor RF22(). 
 /// You can override the default settings for the SS pin and the interrupt 
-/// in the RF22 constructor if you wish to connect the slave select SS to other than pin D10 
+/// in the RF22 constructor if you wish to connect the slave select SS to other than the normal one for your 
+/// Arduino (D10 for Diecimila, Uno etc and D53 for Mega)
 /// or the interrupt request to other than pin D2.
+///
 /// It is possible to have 2 radios conected to one arduino, provided each radio has its own 
 /// SS and interrupt line (SCK, SDI and SDO are common to both radios)
 ///
-/// \par Example programs
+/// Caution: on some Arduinos such as the Mega 2560, if you set the slave select pin to be other than the usual SS 
+/// pin (D53 on  Mega 2560), you may need to set the usual SS pin to be an output to force the Arduino into SPI 
+/// master mode.
 ///
-/// The following example programs are provided:
-/// - rf22_client, rf22_server: Simple client/server pair using RF22 class
-/// - rf22_datagram_client, rf22_datagram_server: Simple client/server pair using RF22Datagram class
-/// - rf22_reliable_datagram_client, rf22_reliable_datagram_server:
-///   Simple client/server pair using RF22ReliableDatagram class
-/// - rf22_router_client, rf22_router_server1, rf22_router_server2, rf22_router_server3: 
-///   Simple RF22Router network. Requires Arduino Mega.
-/// - rf22_mesh_client, rf22_mesh_server1, rf22_mesh_server2, rf22_mesh_server3: 
-///   Simple RF22Mesh network. Requires Arduino Mega.
-/// - rf22_test: Some test code used during development, shows how to call some support functions
-/// - rf22_snoop: Dumps in ASCII the contents of all RF22 messages received
-/// - rf22_specan: Simple spectrum analyser using the RSSI measurements of the RF22
-///   (see <a href="specan1.png">Sample output</a> showing a plot from 395.0MHz to 396.0MHz of a 
-///   signal generator at 395.5MHz amplitude modulated at 100% 1kHz)
+/// Caution: Power supply requirements of the RF22 module may be relevant in some circumstances: 
+/// RF22 modules are capable of pulling 80mA+ at full power, where Arduino's 3.3V line can
+/// give 50mA. You may need to make provision for alternate power supply for
+/// the RF22, especially if you wish to use full transmit power, and/or you have
+/// other shields demanding power. Inadequate power for the RF22 is reported to cause symptoms such as:
+/// - reset's/bootups terminate with "init failed" messages
+///  -random termination of communication after 5-30 packets sent/received
+///  -"fake ok" state, where initialization passes fluently, but communication doesn't happen
+/// -shields hang Arduino boards, especially during the flashing
+///
+///
+/// \par Interrupts
+///
+/// The RF22 library uses interrupts to react to events in the RF22 module, 
+/// such as the reception of a new packet, or the completion of transmission of a packet. 
+/// The RF22 library interrupt service routine reads status from and writes data
+/// to the the RF22 module via the SPI interface. It is very important therefore,
+/// that if you are using the RF22 library with another SPI based deviced, that you
+/// disable interrupts while you transfer data to and from that other device.
+/// Use cli() to disable interrupts and sei() to reenable them.
 ///
 /// \par Memory
 ///
@@ -160,7 +181,35 @@
 /// 
 /// With an Arduino Mega, with 8 kbytes of SRAM, there is much more RAM headroom for 
 /// your own elaborate programs. 
-/// This library is reported not to work with Arduino Pro Mini and Arduino UNO, but these have not been tested here.
+/// This library is reported to work with Arduino Pro Mini, but that has not been tested by me.
+///
+/// The Arduino UNO is now known to work with RF22. 
+///
+/// \par Automatic Frequency Control (AFC)
+///
+/// The RF22M modules use an inexpensive crystal to control the frequency synthesizer, and therfore you can expect 
+/// the transmitter and receiver frequencies to be subject to the usual inaccuracies of such crystals. The RF22
+/// contains an AFC circuit to compensate for differences in transmitter and receiver frequencies. 
+/// It does this by altering the receiver frequency during reception by up to the pull-in frequency range. 
+/// This RF22 library enables the AFC and by default sets the pull-in frequency range to
+/// 0.05MHz, which should be sufficient to handle most situations. However, if you observe unexplained packet losses
+/// or failure to operate correctly all the time it may be because your modules have a wider frequency difference, and
+/// you may need to set the afcPullInRange to a differentvalue, using setFrequency();
+///
+/// \par Performance
+///
+/// Some simple speed performance tests have been conducted.
+/// In general packet transmission rate will be limited by the modulation scheme.
+/// Also, if your code does any slow operations like Serial printing it will also limit performance. 
+/// We disabled any printing in the tests below.
+/// We tested with RF22::GFSK_Rb125Fd125, which is probably the fastest scheme available.
+/// We tested with a 13 octet message length, over a very short distance of 10cm.
+///
+/// Transmission (no reply) tests with modulation RF22::GFSK_Rb125Fd125 and a 
+/// 13 octet message show about 330 messages per second transmitted.
+///
+/// Transmit-and-wait-for-a-reply tests with modulation RF22::GFSK_Rb125Fd125 and a 
+/// 13 octet message (send and receive) show about 160 round trips per second.
 ///
 /// \par Installation
 ///
@@ -213,8 +262,62 @@
 /// \version 1.9 Fixed typos in RF22_REG_21_CLOCk*. Reported by Steffan Woltjer.
 /// \version 1.10 Fixed a problem where a IFFERR during transmission could cause an infinite loop and a hang. 
 ///              Reported by Raymond Gilbert.
+/// \version 1.11 Fixed an innocuous typo in RF22::handleInterrupt. Reported by Zhentao.
 ///
+/// \version 1.12 Improvements to RF22::init from Guy Molinari to improve compatibility with some 
+/// Arduinos. Now reported to be working with official Mega 2560 and Uno.
+/// Updated so compiles on Arduino 1.0.
 ///
+/// \version 1.13 Announce google support group
+///
+/// \version 1.14 Added definitions for bits and masks in RF22_REG_1D_AFC_LOOP_GEARSHIFT_OVERRIDE 
+/// and RF22_REG_1E_AFC_TIMING_CONTROL  
+///
+/// \version 1.15 Small alterations to initialisation code so that SS pin is not set to output: may cause 
+/// interference with other devices connected to the Arduino. Testing with Uno: OK.
+///
+/// \version 1.16 Fixed a problem that prevented building with arduino 0021
+///
+/// \version 1.17 Added optional AFC pull-in frequency range argument to setFrequency(). 
+/// Default AFC pull-in range set to 0.05MHz
+///
+/// \version 1.18 Changed default value for slave slect pin in constructor to be SS, ie the normal one for 
+/// the compiled Arduino (D10 for Diecimila, Uno etc and D53 for Mega). This is because some Arduinos such as Mega 2560
+/// reportedly use the type of the SS pin to determine whether to run in slave or master mode. Therfore it
+/// is preferred that the slave select pin actually be the normal SS pin.
+///
+/// \version 1.19 Added new mode() function.
+///  Fixed a potential race condition in RF22Datagram::recvfrom which might cause corrupt from, to, id or flags
+///  under extreme circumstances. Improvements to interrupt hygeine by adding cli()_/sei() around all 
+///  RF22 register acceses. Found that 0 length transmit packets confuses the RF22, so they are now forbidden.
+///  Added IPGateway example, which routes UDP messages from an internet connection using an 
+///  Ethernet Shield and sends them
+///  to a radio whose ID is based on the UDP port. Replies are sent back to the originating UDP
+///  address and port.
+///
+///  \version 1.20 _mode is now volatile.
+///  RF22::send() now waits until any previous transmission is complete before sending.
+///  RF22::waitPacketSent() now waits for the RF22 to not be in _mode == RF22_MODE_TX
+///  _txPacketSent member is now redundant and removed.
+///  Improvements to interrupt handling and blocking. Now use ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+///  to prevent reenabling interrupts too soon. Thanks to Roland Mieslinger for this suggestion.
+///  Added some performance measurements to documentation.
+///
+///  \version 1.21 Fixed a case where a receiver buffer overflow could occur. Reported by Joe Tuttle.
+///
+///  \version 1.22 Added documentation after testing with Sparkfun RFM22 Shield DEV-11018.
+///                Fixed incorrect link to register calculator excel file, reported by Joey Morin.
+///
+///  \version 1.23 Added support for alternative SPI interfaces, with default implementation for the standard 
+///                Arduino hardware SPI interface. Contributed by Joanna Rutkowska.
+///
+///  \version 1.24 Fixed a problem that could cause corrupted receive messages if a transmit interrupted
+///                a partial receive (as was common with eg ReliableDatagram with poor reception. 
+///                Also fixed possible receive buffer overrun.
+///  \version 1.25 More rigorous use of const, additional register defines (RF22_CRCHDRS RF22_VARPKLEN)
+///                and two methods (setPreambleLength() 
+///                and setSyncWords())made public. Patch provided by 
+///                Matthijs Kooijman.
 /// \author  Mike McCauley (mikem@open.com.au)
 
 #ifndef RF22_h
@@ -232,12 +335,14 @@
 #define RF22_SPI_WRITE_MASK 0x80
 
 // This is the maximum message length that can be supported by this library. Limited by
-// the message length octet in the header. Yes, 255 is correct even though the FIFO size in the RF22 is only
-// 64 octets. We use interrupts to refil the Tx FIFO during transmission and to empty the
-// Rx FIF during reception
+// the single message length octet in the header. 
+// Yes, 255 is correct even though the FIFO size in the RF22 is only
+// 64 octets. We use interrupts to refill the Tx FIFO during transmission and to empty the
+// Rx FIFO during reception
 // Can be pre-defined to a smaller size (to save SRAM) prior to including this header
 #ifndef RF22_MAX_MESSAGE_LEN
-#define RF22_MAX_MESSAGE_LEN 255
+//#define RF22_MAX_MESSAGE_LEN 255
+#define RF22_MAX_MESSAGE_LEN 50
 #endif
 
 // Max number of octets the RF22 Rx and Tx FIFOs can hold
@@ -495,17 +600,21 @@
 #define RF22_WTD                                0x03
 
 //  RF22_REG_1D_AFC_LOOP_GEARSHIFT_OVERRIDE     0x1d
-#define RF22_AFC_EN                             0x40
+#define RF22_AFBCD                              0x80
+#define RF22_ENAFC                              0x40
+#define RF22_AFCGEARH                           0x38
+#define RF22_AFCGEARL                           0x07
 
-// Reg  RF22_REG_1E_AFC_TIMING_CONTROL          0x1e
-#define RF22_AFC_TC                             0x0a
-
-// Reg RF22_REG_2A_AFC_LIMITER                  0x2a
-#define RF22_AFC_LIMIT                          0x50
+// RF22_REG_1E_AFC_TIMING_CONTROL               0x1e
+#define RF22_SWAIT_TIMER                        0xc0
+#define RF22_SHWAIT                             0x38
+#define RF22_ANWAIT                             0x07
 
 // RF22_REG_30_DATA_ACCESS_CONTROL              0x30
 #define RF22_ENPACRX                            0x80
+#define RF22_MSBFRST                            0x00
 #define RF22_LSBFRST                            0x40
+#define RF22_CRCHDRS                            0x00
 #define RF22_CRCDONLY                           0x20
 #define RF22_ENPACTX                            0x08
 #define RF22_ENCRC                              0x04
@@ -536,6 +645,7 @@
 #define RF22_HDLEN_2                            0x20
 #define RF22_HDLEN_3                            0x30
 #define RF22_HDLEN_4                            0x40
+#define RF22_VARPKLEN                           0x00
 #define RF22_FIXPKLEN                           0x08
 #define RF22_SYNCLEN                            0x06
 #define RF22_SYNCLEN_1                          0x00
@@ -582,6 +692,11 @@
 #define RF22_HBSEL                              0x20
 #define RF22_FB                                 0x1f
 
+// Define this to include Serial printing in diagnostic routines
+//#define RF22_HAVE_SERIAL
+
+//#include <GenericSPI.h>
+//#include <HardwareSPI.h>
 /////////////////////////////////////////////////////////////////////
 /// \class RF22 RF22.h <RF22.h>
 /// \brief Send and receive unaddressed, unreliable datagrams.
@@ -613,7 +728,7 @@
     /// setModemConfig() writes the register values to the appropriate RF22 registers
     /// to set the desired modulation type, data rate and deviation/bandwidth.
     /// Suitable values for these registers can be computed using the register calculator at
-    /// "http://www.hoperf.com/upfile/RF22B 23B 31B 42B 43B Register Settings_RevB1-v5.xls"
+    /// http://www.hoperf.com/upload/rf/RF22B%2023B%2031B%2042B%2043B%20Register%20Settings_RevB1-v5.xls
     typedef struct
     {
     uint8_t    reg_1c;   ///< Value for register RF22_REG_1C_IF_FILTER_BANDWIDTH
@@ -637,8 +752,7 @@
     } ModemConfig;
   
     /// Choices for setModemConfig() for a selected subset of common modulation types,
-    /// and data rates. If you need another configuration, use the register calculator at
-    /// "http://www.hoperf.com/upfile/RF22B 23B 31B 42B 43B Register Settings_RevB1-v5.xls"
+    /// and data rates. If you need another configuration, use the register calculator.
     /// and call setModemRegisters() with your desired settings
     /// These are indexes into _modemConfig
     typedef enum
@@ -677,7 +791,7 @@
     /// interrupt and slave select pin. After constructing, you must call init() to initialise the intnerface
     /// and the radio module
     /// \param[in] slaveSelectPin the Arduino pin number of the output to use to select the RF22 before
-    /// accessing it
+    /// accessing it. Defaults to the normal SS pin for your Arduino (D10 for Diecimila, Uno etc, D53 for Mega)
     /// \param[in] interrupt The interrupt number to use. Default is interrupt 0 (Arduino input pin 2)
     RF22(PinName slaveSelectPin , PinName mosi, PinName miso, PinName sclk, PinName interrupt );
   
@@ -717,7 +831,7 @@
     /// \param[in] reg Register number of the first register, one of RF22_REG_*
     /// \param[in] src Array of new register values to write. Must be at least len bytes
     /// \param[in] len Number of bytes to write
-    void           spiBurstWrite(uint8_t reg, uint8_t* src, uint8_t len);
+    void           spiBurstWrite(uint8_t reg, const uint8_t* src, uint8_t len);
 
     /// Reads and returns the device status register RF22_REG_02_DEVICE_STATUS
     /// \return The value of the device status register
@@ -749,7 +863,7 @@
     uint16_t       wutRead();
 
     /// Sets the wakeup timer period registers RF22_REG_14_WAKEUP_TIMER_PERIOD1,
-    /// RF22_REG_15_WAKEUP_TIMER_PERIOD2 and RF22_REG_16_WAKEUP_TIMER_PERIOD3
+    /// RF22_REG_15_WAKEUP_TIMER_PERIOD2 and RF22_R<EG_16_WAKEUP_TIMER_PERIOD3
     /// \param[in] wtm Wakeup timer mantissa value
     /// \param[in] wtr Wakeup timer exponent R value
     /// \param[in] wtd Wakeup timer exponent D value
@@ -758,8 +872,10 @@
     /// Sets the transmitter and receiver centre frequency
     /// \param[in] centre Frequency in MHz. 240.0 to 960.0. Caution, some versions of RF22 and derivatives 
     /// implemented more restricted frequency ranges.
-    /// \return true if the selected frquency centre + (fhch * fhs) is within range
-    boolean        setFrequency(float centre);
+    /// \param[in] afcPullInRange Sets the AF Pull In Range in MHz. Defaults to 0.05MHz (50kHz). Range is 0.0 to 0.159375
+    /// for frequencies 240.0 to 480MHz, and 0.0 to 0.318750MHz for  frequencies 480.0 to 960MHz, 
+    /// \return true if the selected frquency centre + (fhch * fhs) is within range and the afcPullInRange is within range
+    boolean        setFrequency(float centre, float afcPullInRange = 0.05);
 
     /// Sets the frequency hopping step size.
     /// \param[in] fhs Frequency Hopping step size in 10kHz increments
@@ -771,7 +887,8 @@
     /// \return true if the selected frquency centre + (fhch * fhs) is within range
     boolean        setFHChannel(uint8_t fhch);
 
-    /// Reads and returns the current RSSI value from register RF22_REG_26_RSSI
+    /// Reads and returns the current RSSI value from register RF22_REG_26_RSSI. If you want to find the RSSI
+    /// of the last received message, use lastRssi() instead.
     /// \return The current RSSI value 
     uint8_t        rssiRead();
 
@@ -780,9 +897,9 @@
     uint8_t        ezmacStatusRead();
 
     /// Sets the parameters for the RF22 Idle mode in register RF22_REG_07_OPERATING_MODE. 
-    /// Idle mode is the mode the RF22 wil be in when not transmitting or receiving. The default idle mode 
+    /// Idle mode is the mode the RF22 will be in when not transmitting or receiving. The default idle mode 
     /// is RF22_XTON ie READY mode. 
-    /// \param[in] mode MAsk of mode bits, using RF22_SWRES, RF22_ENLBD, RF22_ENWT, 
+    /// \param[in] mode Mask of mode bits, using RF22_SWRES, RF22_ENLBD, RF22_ENWT, 
     /// RF22_X32KSEL, RF22_PLLON, RF22_XTON.
     void           setMode(uint8_t mode);
 
@@ -798,6 +915,10 @@
     /// Starts the transmitter in the RF22.
     void           setModeTx();
 
+    /// Returns the operating mode of the library.
+    /// \return the current mode, one of RF22_MODE_*
+    uint8_t        mode();
+
     /// Sets the transmitter power output level in register RF22_REG_6D_TX_POWER.
     /// Be a good neighbour and set the lowest power level you need.
     /// After init(), the power wil be set to RF22_TXPOW_8DBM.
@@ -810,7 +931,7 @@
     /// bandwidths etc. You cas use this to configure the modem with custom configuraitons if none of the 
     /// canned configurations in ModemConfigChoice suit you.
     /// \param[in] config A ModemConfig structure containing values for the modem configuration registers.
-    void           setModemRegisters(ModemConfig* config);
+    void           setModemRegisters(const ModemConfig* config);
 
     /// Select one of the predefined modem configurations. If you need a modem configuration not provided 
     /// here, use setModemRegisters() with your own ModemConfig.
@@ -844,15 +965,16 @@
     /// \return true if a valid message was copied to buf
     boolean        recv(uint8_t* buf, uint8_t* len);
 
-    /// Loads a message into the transmitter and starts the transmitter. Note that a message length
-    /// of 0 is permitted, in which case data may be NULL.
+    /// Waits until any previous transmit packet is finished being transmitted with waitPacketSent().
+    /// Then loads a message into the transmitter and starts the transmitter. Note that a message length
+    /// of 0 is NOT permitted. 
     /// \param[in] data Array of data to be sent
-    /// \param[in] len Number of bytes of data to send.
-    /// \return true
-    boolean        send(uint8_t* data, uint8_t len);
+    /// \param[in] len Number of bytes of data to send (> 0)
+    /// \return true if the message length was valid and it was correctly queued for transmit
+    boolean        send(const uint8_t* data, uint8_t len);
 
-    /// Blocks until the current message 
-    /// (if any) has been completely sent
+    /// Blocks until the RF22 is not in mode RF22_MODE_TX (ie until the RF22 is not transmitting).
+    /// This effectively waits until any previous transmit packet is finished being transmitted.
     void           waitPacketSent();
   
     /// Tells the receiver to accept messages with any TO address, not just messages
@@ -866,17 +988,14 @@
 
     /// Returns the FROM header of the last received message
     /// \return The FROM header
-    /// \return
     uint8_t        headerFrom();
 
     /// Returns the ID header of the last received message
     /// \return The ID header
-    /// \return
     uint8_t        headerId();
 
     /// Returns the FLAGS header of the last received message
     /// \return The FLAGS header
-    /// \return
     uint8_t        headerFlags();
 
     /// Returns the RSSI (Receiver Signal Strength Indicator)
@@ -885,17 +1004,30 @@
     /// \return The RSSI
     uint8_t        lastRssi();
 
-protected:
+    /// Prints a data buffer in HEX.
+    /// For diagnostic use
+    /// \param[in] prompt string to preface the print
+    /// \param[in] buf Location of the buffer to print
+    /// \param[in] len Length of the buffer in octets.
+    static void           printBuffer(const char* prompt, const uint8_t* buf, uint8_t len);
+
+    /// Sets the length of the preamble
+    /// in 4-bit nibbles. 
+    /// Caution: this should be set to the same 
+    /// value on all nodes in your network. Default is 8.
     /// Sets the message preamble length in RF22_REG_34_PREAMBLE_LENGTH
     /// \param[in] nibbles Preamble length in nibbles of 4 bits each.  
     void           setPreambleLength(uint8_t nibbles);
 
     /// Sets the sync words for transmit and receive in registers RF22_REG_36_SYNC_WORD3 
     /// to RF22_REG_39_SYNC_WORD0
+    /// Caution: this should be set to the same 
+    /// value on all nodes in your network. Default is { 0x2d, 0xd4 }
     /// \param[in] syncWords Array of sync words
     /// \param[in] len Number of sync words to set
-    void           setSyncWords(uint8_t* syncWords, uint8_t len);
+    void           setSyncWords(const uint8_t* syncWords, uint8_t len);
 
+protected:
     /// This is a low level function to handle the interrupts for one instance of RF22.
     /// Called automatically by isr0() and isr1()
     /// Should not need to be called.
@@ -910,16 +1042,16 @@
     void           clearTxBuf();
 
     /// Fills the transmitter buffer with the data of a mesage to be sent
-    /// \param[in] data Array of data bytes to be sent (0 to 255)
-    /// \param[in] len Number of data bytes in data
-    /// \return true
-    boolean           fillTxBuf(uint8_t* data, uint8_t len);
+    /// \param[in] data Array of data bytes to be sent (1 to 255)
+    /// \param[in] len Number of data bytes in data (> 0)
+    /// \return true if the message length is valid
+    boolean           fillTxBuf(const uint8_t* data, uint8_t len);
 
     /// Appends the transmitter buffer with the data of a mesage to be sent
     /// \param[in] data Array of data bytes to be sent (0 to 255)
     /// \param[in] len Number of data bytes in data
     /// \return false if the resulting message would exceed RF22_MAX_MESSAGE_LEN, else true
-    boolean           appendTxBuf(uint8_t* data, uint8_t len);
+    boolean           appendTxBuf(const uint8_t* data, uint8_t len);
 
     /// Internal function to load the next fragment of 
     /// the current message into the transmitter FIFO
@@ -978,19 +1110,21 @@
     /// of the Tx buffer after a atransmission failure
     void           restartTransmit();
 
-//private:
+protected:
+    //GenericSPIClass*    _spi;
+
     /// Low level interrupt service routine for RF22 connected to interrupt 0
     //static void         isr0();
     void         isr0();
 
     /// Low level interrupt service routine for RF22 connected to interrupt 1
     //static void         isr1();
-private:
+//private:
     /// Array of instances connected to interrupts 0 and 1
     //static RF22*        _RF22ForInterrupt[];
     
    
-    uint8_t             _mode; // One of RF22_MODE_*
+    volatile uint8_t    _mode; // One of RF22_MODE_*
 
     uint8_t             _idleMode;
     DigitalOut          _slaveSelectPin;
@@ -1004,8 +1138,8 @@
     DigitalOut           led4;
 
     // These volatile members may get changed in the interrupt service routine
+    volatile uint8_t    _bufLen;
     uint8_t             _buf[RF22_MAX_MESSAGE_LEN];
-    volatile uint8_t    _bufLen;
 
     volatile boolean    _rxBufValid;
 
@@ -1017,8 +1151,67 @@
     volatile uint16_t   _txGood;
 
     volatile uint8_t    _lastRssi;
-    
 };
 
+/// @example rf22_client.pde
+/// Client side of simple client/server pair using RF22 class
+
+/// @example rf22_server.pde
+/// Server side of simple client/server pair using RF22 class
+
+/// @example rf22_datagram_client.pde
+/// Client side of simple client/server pair using RF22Datagram class
+
+/// @example rf22_datagram_server.pde
+/// Server side of simple client/server pair using RF22Datagram class
+
+/// @example rf22_reliable_datagram_client.pde
+/// Client side of simple client/server pair using RF22ReliableDatagram class
+
+/// @example rf22_reliable_datagram_server.pde
+/// Server side of simple client/server pair using RF22ReliableDatagram class
+
+/// @example rf22_router_client.pde
+/// Client side of RF22Router network chain
+
+/// @example rf22_router_server1.pde
+/// Server node for RF22Router network chain
+
+/// @example rf22_router_server2.pde
+/// Server node for RF22Router network chain
+
+/// @example rf22_router_server3.pde
+/// Server node for RF22Router network chain
+
+/// @example rf22_mesh_client.pde
+/// Client side of RF22Mesh network chain
+
+/// @example rf22_mesh_server1.pde
+/// Server node for RF22Mesh network chain
+
+/// @example rf22_mesh_server2.pde
+/// Server node for RF22Mesh network chain
+
+/// @example rf22_mesh_server3.pde
+/// Server node for RF22Mesh network chain
+
+/// @example rf22_test.pde
+/// Test suite for RF22 library
+
+/// @example rf22_snoop.pde
+/// Capture and print RF22 packet from the air
+
+/// @example rf22_specan.pde
+/// Simple spectrum analyser using the RSSI measurements of the RF22
+///   (see <a href="specan1.png">Sample output</a> showing a plot from 395.0MHz to 396.0MHz of a 
+///   signal generator at 395.5MHz amplitude modulated at 100% 1kHz)
+///
+
+/// @example IPGateway.pde
+/// Sketch to provide an IP gateway for a set of RF22 radios (Datagram, ReliableDatagram, Router or Mesh)
+/// Routes UDP messages from an internet connection using an Ethernet Shield and sends them
+/// to a radio whose ID is based on the UDP port. Replies are sent back to the originating UDP
+/// address and port
+
 
 #endif 
--- a/RF22Datagram.cpp	Sun Feb 19 21:12:10 2012 +0000
+++ b/RF22Datagram.cpp	Sat Mar 02 20:49:07 2013 +0000
@@ -1,7 +1,7 @@
 // RF22Datagram.cpp
 //
 // Copyright (C) 2011 Mike McCauley
-// $Id: RF22Datagram.cpp,v 1.2 2011/02/09 22:26:09 mikem Exp $
+// $Id: RF22Datagram.cpp,v 1.3 2012/05/30 01:50:21 mikem Exp $
 // ported to mbed by Karl Zweimueller
 
 #include <RF22Datagram.h>
@@ -40,12 +40,16 @@
 
 boolean RF22Datagram::recvfrom(uint8_t* buf, uint8_t* len, uint8_t* from, uint8_t* to, uint8_t* id, uint8_t* flags)
 {
+    if (recv(buf, len))
+    {
+
     if (from)  *from =  headerFrom();
     if (to)    *to =    headerTo();
     if (id)    *id =    headerId();
     if (flags) *flags = headerFlags();
-    return recv(buf, len);
+    return true;
+    }
+    return false;
 }
 
 
-
--- a/RF22Datagram.h	Sun Feb 19 21:12:10 2012 +0000
+++ b/RF22Datagram.h	Sat Mar 02 20:49:07 2013 +0000
@@ -1,7 +1,7 @@
 // RF22Datagram.h
 // Author: Mike McCauley (mikem@open.com.au)
 // Copyright (C) 2011 Mike McCauley
-// $Id: RF22Datagram.h,v 1.3 2011/02/15 01:18:03 mikem Exp $
+// $Id: RF22Datagram.h,v 1.4 2012/05/30 01:50:21 mikem Exp $
 // ported to mbed by Karl Zweimueller
 
 #ifndef RF22Datagram_h
@@ -26,9 +26,9 @@
     /// Constructor. 
     /// \param[in] thisAddress The address to assign to this node. Defaults to 0
     /// \param[in] slaveSelectPin the Arduino pin number of the output to use to select the RF22 before
-    /// accessing it
+    /// accessing it. Defaults to the normal SS pin for your Arduino (D10 for Diecimila, Uno etc, D53 for Mega)
     /// \param[in] interrupt The interrupt number to use. Default is interrupt 0 (Arduino input pin 2)
-    RF22Datagram(uint8_t thisAddress ,PinName slaveSelectPin , PinName mosi, PinName miso, PinName sclk, PinName interrupt );
+    RF22Datagram(uint8_t thisAddress , PinName slaveSelectPin , PinName mosi, PinName miso, PinName sclk, PinName interrupt );
     
     /// Initialises this instance and the radio module connected to it.
     /// Overrides the init() function in RF22
@@ -46,7 +46,7 @@
     /// RF22_BROADCAST_ADDRESS is a valid address which will cause the message
     /// to be accepted by all RF22Datagram nodes within range.
     /// \param[in] buf Pointer to the binary message to send
-    /// \param[in] len Number of octets to send
+    /// \param[in] len Number of octets to send (> 0)
     /// \param[in] address The address to send the message to.
     /// \return true if the message was transmitted.
     boolean sendto(uint8_t* buf, uint8_t len, uint8_t address);
--- a/RF22Mesh.cpp	Sun Feb 19 21:12:10 2012 +0000
+++ b/RF22Mesh.cpp	Sat Mar 02 20:49:07 2013 +0000
@@ -238,4 +238,3 @@
 }
 
 
-
--- a/RF22Mesh.h	Sun Feb 19 21:12:10 2012 +0000
+++ b/RF22Mesh.h	Sat Mar 02 20:49:07 2013 +0000
@@ -2,7 +2,7 @@
 //
 // Author: Mike McCauley (mikem@open.com.au)
 // Copyright (C) 2011 Mike McCauley
-// $Id: RF22Mesh.h,v 1.3 2011/02/15 04:51:59 mikem Exp $
+// $Id: RF22Mesh.h,v 1.4 2012/05/30 01:51:25 mikem Exp $
 // ported to mbed by Karl Zweimueller
 
 #ifndef RF22Mesh_h
@@ -120,7 +120,7 @@
     typedef struct
     {
     MeshMessageHeader   header; ///< msgType = RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_*
-    uint8_t             destlen; ///< Reserved. Must be 1.
+    uint8_t             destlen; ///< Reserved. Must be 1.g
     uint8_t             dest;   ///< The address of the destination node whose route is being sought
     uint8_t             route[RF22_MESH_MAX_MESSAGE_LEN - 1]; ///< List of node addresses visited so far. Length is implcit
     } MeshRouteDiscoveryMessage;
@@ -135,9 +135,9 @@
     /// Constructor. 
     /// \param[in] thisAddress The address to assign to this node. Defaults to 0
     /// \param[in] slaveSelectPin the Arduino pin number of the output to use to select the RF22 before
-    /// accessing it
+    /// accessing it. Defaults to the normal SS pin for your Arduino (D10 for Diecimila, Uno etc, D53 for Mega)
     /// \param[in] interrupt The interrupt number to use. Default is interrupt 0 (Arduino input pin 2)
-    RF22Mesh(uint8_t thisAddress ,PinName slaveSelectPin , PinName mosi, PinName miso, PinName sclk, PinName interrupt );
+    RF22Mesh(uint8_t thisAddress , PinName slaveSelectPin , PinName mosi, PinName miso, PinName sclk, PinName interrupt );
 
     /// Sends a message to the destination node. Initialises the RF22Router message header 
     /// (the SOURCE address is set to the address of this node, HOPS to 0) and calls 
@@ -235,4 +235,3 @@
 };
 
 #endif
-
--- a/RF22ReliableDatagram.cpp	Sun Feb 19 21:12:10 2012 +0000
+++ b/RF22ReliableDatagram.cpp	Sat Mar 02 20:49:07 2013 +0000
@@ -28,24 +28,28 @@
 
 ////////////////////////////////////////////////////////////////////
 // Public methods
-void RF22ReliableDatagram::setTimeout(uint16_t timeout) {
+void RF22ReliableDatagram::setTimeout(uint16_t timeout)
+{
     _timeout = timeout;
 }
 
 ////////////////////////////////////////////////////////////////////
-void RF22ReliableDatagram::setRetries(uint8_t retries) {
+void RF22ReliableDatagram::setRetries(uint8_t retries)
+{
     _retries = retries;
 }
 
 ////////////////////////////////////////////////////////////////////
-boolean RF22ReliableDatagram::sendtoWait(uint8_t* buf, uint8_t len, uint8_t address) {
+boolean RF22ReliableDatagram::sendtoWait(uint8_t* buf, uint8_t len, uint8_t address)
+{
     // Assemble the message
     uint8_t thisSequenceNumber = ++_lastSequenceNumber;
 
     Timer t;
 
     uint8_t retries = 0;
-    while (retries++ <= _retries) {
+    while (retries++ <= _retries)
+    {
         setHeaderId(thisSequenceNumber);
         setHeaderFlags(0);
         sendto(buf, len, address);
@@ -62,10 +66,11 @@
 
 
         // Compute a new timeout, random between _timeout and _timeout*2
-        // This is to prevent collissions on every retransmit
+    // This is to prevent collisions on every retransmit
         // if 2 nodes try to transmit at the same time
         uint16_t timeout = _timeout + (_timeout * (rand() % 100) / 100);
-        while (t.read_ms() < (thisSendTime + timeout)) {
+        while (t.read_ms() < (thisSendTime + timeout)) 
+        {
             if (available()) {
                 clearRxBuf(); // Not using recv, so clear it ourselves
                 uint8_t from = headerFrom();
@@ -76,11 +81,14 @@
                 if (   from == address
                         && to == _thisAddress
                         && (flags & RF22_FLAGS_ACK)
-                        && (id == thisSequenceNumber)) {
+            && (id == thisSequenceNumber))
+        {
                     // Its the ACK we are waiting for
                     return true;
-                } else if (   !(flags & RF22_FLAGS_ACK)
-                              && (id == _seenIds[from])) {
+        }
+        else if (   !(flags & RF22_FLAGS_ACK)
+             && (id == _seenIds[from]))
+        {
                     // This is a request we have already received. ACK it again
                     acknowledge(id, from);
                 }
@@ -94,23 +102,28 @@
 }
 
 ////////////////////////////////////////////////////////////////////
-boolean RF22ReliableDatagram::recvfromAck(uint8_t* buf, uint8_t* len, uint8_t* from, uint8_t* to, uint8_t* id, uint8_t* flags) {
+boolean RF22ReliableDatagram::recvfromAck(uint8_t* buf, uint8_t* len, uint8_t* from, uint8_t* to, uint8_t* id, uint8_t* flags)
+{  
     uint8_t _from;
     uint8_t _to;
     uint8_t _id;
     uint8_t _flags;
     // Get the message before its clobbered by the ACK (shared rx anfd tx buffer in RF22
-    if (available() && recvfrom(buf, len, &_from, &_to, &_id, &_flags)) {
+    if (available() && recvfrom(buf, len, &_from, &_to, &_id, &_flags))
+    {
         // Never ACK an ACK
-        if (!(_flags & RF22_FLAGS_ACK)) {
+    if (!(_flags & RF22_FLAGS_ACK))
+    {
             // Its a normal message for this node, not an ACK
-            if (_to != RF22_BROADCAST_ADDRESS) {
+        if (_to != RF22_BROADCAST_ADDRESS)
+        {
                 // Its not a broadcast, so ACK it
                 // Acknowledge message with ACK set in flags and ID set to received ID
                 acknowledge(_id, _from);
             }
             // If we have not seen this message before, then we are interested in it
-            if (_id != _seenIds[_from]) {
+        if (_id != _seenIds[_from])
+        {
                 if (from)  *from =  _from;
                 if (to)    *to =    _to;
                 if (id)    *id =    _id;
@@ -134,11 +147,13 @@
     return false;
 }
 
-uint16_t RF22ReliableDatagram::retransmissions() {
+uint16_t RF22ReliableDatagram::retransmissions()
+{
     return _retransmissions;
 }
 
-void RF22ReliableDatagram::acknowledge(uint8_t id, uint8_t from) {
+void RF22ReliableDatagram::acknowledge(uint8_t id, uint8_t from)
+{
     setHeaderId(id);
     setHeaderFlags(RF22_FLAGS_ACK);
     // We would prefer to send a zero length ACK,
@@ -150,4 +165,3 @@
     sendto(&ack, sizeof(ack), from);
     waitPacketSent();
 }
-
--- a/RF22ReliableDatagram.h	Sun Feb 19 21:12:10 2012 +0000
+++ b/RF22ReliableDatagram.h	Sat Mar 02 20:49:07 2013 +0000
@@ -2,7 +2,7 @@
 //
 // Author: Mike McCauley (mikem@open.com.au)
 // Copyright (C) 2011 Mike McCauley
-// $Id: RF22ReliableDatagram.h,v 1.6 2011/02/15 01:18:03 mikem Exp $
+// $Id: RF22ReliableDatagram.h,v 1.7 2012/05/30 01:51:25 mikem Exp $
 // ported to mbed by Karl Zweimueller
 
 #ifndef RF22ReliableDatagram_h
@@ -45,7 +45,7 @@
     /// Constructor. 
     /// \param[in] thisAddress The address to assign to this node. Defaults to 0
     /// \param[in] slaveSelectPin the Arduino pin number of the output to use to select the RF22 before
-    /// accessing it
+    /// accessing it. Defaults to the normal SS pin for your Arduino (D10 for Diecimila, Uno etc, D53 for Mega)
     /// \param[in] interrupt The interrupt number to use. Default is interrupt 0 (Arduino input pin 2)
     RF22ReliableDatagram(uint8_t thisAddress ,PinName slaveSelectPin , PinName mosi, PinName miso, PinName sclk, PinName interrupt );
 
@@ -53,7 +53,8 @@
     /// longer than this time (in milliseconds), 
     /// it will retransmit the message. Defaults to 200ms. The timeout is measured from the end of
     /// transmission of the message. It must be at least longer than the the transmit 
-    /// time of the acknowledgement (6 octets) plus the latency/poll time of the receiver. 
+    /// time of the acknowledgement (preamble+6 octets) plus the latency/poll time of the receiver. 
+    /// For fast modulation schemes you can considerably shorten this time.
     /// The actual timeout is randomly varied between timeout and timeout*2.
     /// \param[in] timeout The new timeout period in milliseconds
     void setTimeout(uint16_t timeout);
@@ -148,4 +149,3 @@
 };
 
 #endif
-
--- a/RF22Router.cpp	Sun Feb 19 21:12:10 2012 +0000
+++ b/RF22Router.cpp	Sat Mar 02 20:49:07 2013 +0000
@@ -9,7 +9,7 @@
 //
 // Author: Mike McCauley (mikem@open.com.au)
 // Copyright (C) 2011 Mike McCauley
-// $Id: RF22Router.cpp,v 1.6 2011/02/15 01:18:03 mikem Exp $
+// $Id: RF22Router.cpp,v 1.7 2012/05/30 01:51:25 mikem Exp $
 // ported to mbed by Karl Zweimueller
 
 #include <mbed.h>
@@ -106,10 +106,10 @@
     _routes[RF22_ROUTING_TABLE_SIZE - 1].state = Invalid;
 }
 
-#ifdef RF22_HAVE_SERIAL
 ////////////////////////////////////////////////////////////////////
 void RF22Router::printRoutingTable()
 {
+#ifdef RF22_HAVE_SERIAL
     uint8_t i;
     for (i = 0; i < RF22_ROUTING_TABLE_SIZE; i++)
     {
@@ -121,8 +121,8 @@
     Serial.print(" State: ");
     Serial.println(_routes[i].state, DEC);
     }
+#endif
 }
-#endif
 
 ////////////////////////////////////////////////////////////////////
 boolean RF22Router::deleteRouteTo(uint8_t dest)
@@ -305,4 +305,3 @@
     }
     return false;
 }
-
--- a/RF22Router.h	Sun Feb 19 21:12:10 2012 +0000
+++ b/RF22Router.h	Sat Mar 02 20:49:07 2013 +0000
@@ -2,7 +2,7 @@
 //
 // Author: Mike McCauley (mikem@open.com.au)
 // Copyright (C) 2011 Mike McCauley
-// $Id: RF22Router.h,v 1.7 2011/02/15 01:18:03 mikem Exp $
+// $Id: RF22Router.h,v 1.8 2012/05/30 01:51:25 mikem Exp $
 // ported to mbed by Karl Zweimueller
 
 #ifndef RF22Router_h
@@ -172,7 +172,7 @@
     /// Constructor. 
     /// \param[in] thisAddress The address to assign to this node. Defaults to 0
     /// \param[in] slaveSelectPin the Arduino pin number of the output to use to select the RF22 before
-    /// accessing it
+    /// accessing it. Defaults to the normal SS pin for your Arduino (D10 for Diecimila, Uno etc, D53 for Mega)
     /// \param[in] interrupt The interrupt number to use. Default is interrupt 0 (Arduino input pin 2)
     //RF22Router(uint8_t thisAddress = 0, uint8_t slaveSelectPin = 10, uint8_t interrupt = 0);
     RF22Router(uint8_t thisAddress ,PinName slaveSelectPin , PinName mosi, PinName miso, PinName sclk, PinName interrupt );
@@ -213,11 +213,9 @@
     /// local routing table
     void clearRoutingTable();
 
-#ifdef RF22_HAVE_SERIAL
     /// If RF22_HAVE_SERIAL is defined, this will print out the contents of the local 
     /// routing table using Serial
     void printRoutingTable();
-#endif
 
     /// Sends a message to the destination node. Initialises the RF22Router message header 
     /// (the SOURCE address is set to the address of this node, HOPS to 0) and calls 
@@ -323,4 +321,3 @@
 };
 
 #endif
-