MakingThings
  • Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

xbee.c

00001 /*********************************************************************************
00002 
00003  Copyright 2006-2008 MakingThings
00004 
00005  Licensed under the Apache License, 
00006  Version 2.0 (the "License"); you may not use this file except in compliance 
00007  with the License. You may obtain a copy of the License at
00008 
00009  http://www.apache.org/licenses/LICENSE-2.0 
00010  
00011  Unless required by applicable law or agreed to in writing, software distributed
00012  under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
00013  CONDITIONS OF ANY KIND, either express or implied. See the License for
00014  the specific language governing permissions and limitations under the License.
00015 
00016 *********************************************************************************/
00017 #include "config.h"
00018 
00019 #include "stdlib.h"
00020 #include <stdio.h>
00021 #include "string.h"
00022 #include "xbee.h"
00023 
00024 static bool XBee_GetIOValues( XBeePacket* packet, int *inputs );
00025 void XBeeTask( void* p );
00026 #define XBEEPACKET_Q_SIZE 5
00027 #define XBEE_OSC_RX_TIMEOUT 500
00028 
00029 typedef struct
00030 {
00031   XBeePacket* currentPkt;
00032   int packetIndex;
00033   #ifdef OSC
00034   bool autosend;
00035   #endif
00036   bool waitingForConfirm;
00037 } XBeeSubsystem;
00038 
00039 XBeeSubsystem* XBee;
00040 
00041 /** \defgroup XBee XBee
00042   Communicate with XBee (Zigbee) wireless modules via the Make Controller's serial port.
00043   
00044   XBee modules from \b MaxStream are small, cheap ($19 each), wireless \b RF (radio frequency) modules that
00045   can easily be used with the Make Controller Kit to create projects that require wireless communication.  Check
00046   http://www.maxstream.net/products/xbee/xbee-oem-rf-module-zigbee.php for more info.
00047   
00048   \section Overview
00049   XBee modules are <b>ZigBee/IEEE 802.15.4</b> compliant and can operate in several modes:
00050   - Transparent serial port.  Messages in one side magically end up at the other endpoint.  Great for enabling wireless
00051   communication between 2 Make Controllers.
00052   - AT command mode.  Send traditional AT commands to configure the module itself (as opposed to having
00053   the data go straight through via serial mode.
00054   - Packet (API) mode.  Lower level communication that doesn't have to wait for the module to be in
00055   AT command mode.  Check the \ref XBeePacketTypes for a description of how these packets are laid out.  
00056   Be sure to call XBeeConfig_SetPacketApiMode before trying to do anything in this mode.
00057 
00058   The general idea is that you have one XBee module connected directly to your Make Controller Kit, and then
00059   any number of other XBee modules that can communicate with it in order to get information to and from the
00060   Make Controller.  Or, several Make Controllers can each have an XBee module connected in order to
00061   communicate wirelessly among themselves.
00062 
00063   XBee modules also have some digital and analog I/O right on them, which means you can directly connect
00064   sensors to the XBee modules which will both read the values and send them wirelessly.  Check the XBee doc
00065   for the appropriate commands to send in order to set this up.
00066 
00067   \section API
00068   The Make Controller API for working with the XBee modules makes use of the XBee Packet API.  If you simply want to make use
00069   of the transparent serial port functionality, you can use the following functions:
00070     XBee_SetActive( )
00071     XBee_Write(  );
00072     XBee_Read( );
00073     XBee_GetReadable( );
00074 
00075   Or if you want to handle setup etc. yourself, you don't need to deal with these - just hook up the module to your 
00076   Make Controller and start reading and writing over the serial port.
00077 
00078   Bytes sent in this way are broadcast to all XBee modules on the same chanel and with the same PAN ID.  All similarly
00079   configured modules will receive all bytes sent.  However, because these bytes are broadcast, there is no message
00080   reliability, so there's no guarantee that the messages will actually get there.
00081 
00082   The XBee Packet API allows for much more flexible and powerful communication with the modules.  With the Packet API
00083   you can send messages to a specific module, detect where messages came from, check signal strength, and most importantly
00084   packets are sent with a send / acknowledges / retry scheme which greatly increases message reliability.
00085   
00086   Packet API uses commands to configure the XBee module itself, and then a handful of Zigbee specified packet types can be sent and received.  
00087   See \ref XBeePacketTypes for details on these packet types.  
00088   
00089   The \b XBeeConfig_ functions are convenient wrappers around some of the most common AT commands you might want to send.  For
00090   any of the other AT commands, check the XBee documentation and create them using XBee_CreateATCommandPacket( ).  These will always 
00091   be sent to the XBee module attached to the Make Controller.  The \b XBee_ functions deal with sending and receiving 
00092   messages to other XBee modules not connected to the Make Controller.
00093 
00094   \ingroup Libraries
00095   @{
00096 */
00097 
00098 /** 
00099   Controls the active state of the \b XBee subsystem
00100   @param state Whether this subsystem is active or not
00101   @return Zero on success.
00102 */
00103 int XBee_SetActive( int state )
00104 {
00105   if( state ) 
00106   { 
00107     if( XBee == NULL )
00108     {
00109       if( CONTROLLER_OK != Serial_SetActive( SERIAL_0, 1 ) )
00110         return CONTROLLER_ERROR_SUBSYSTEM_INACTIVE;
00111       
00112       // Configure the serial port
00113       Serial_SetBaud( SERIAL_0, 9600 );
00114       Serial_SetBits( SERIAL_0, 8 );
00115       Serial_SetParity( SERIAL_0, 0 );
00116       Serial_SetStopBits( SERIAL_0, 1 );
00117 
00118       XBee = MallocWait( sizeof( XBeeSubsystem ), 100 );
00119       XBee->packetIndex = 0;
00120       #ifdef OSC
00121         XBee->autosend = XBee_GetAutoSend( true );
00122       #endif
00123       XBee->currentPkt = MallocWait( sizeof( XBeePacket ), 100 );
00124       XBee_ResetPacket( XBee->currentPkt );
00125       XBee->waitingForConfirm = false;
00126     }
00127   }
00128   else
00129   {
00130     Serial_SetActive( SERIAL_0, 0 );
00131 
00132     if( XBee )
00133     {
00134       Free( XBee );
00135       Free( XBee->currentPkt );
00136       XBee = NULL;
00137     }
00138   }
00139   return CONTROLLER_OK;
00140 }
00141 
00142 /** 
00143   Read the active state of the \b XBee subsystem
00144   @return An integer specifying the active state - 1 (active) or 0 (inactive).
00145 */
00146 int XBee_GetActive( )
00147 {
00148   return Serial_GetActive( SERIAL_0 );
00149 }
00150 
00151 
00152 /** 
00153   Write the specified number of bytes into the XBee unit.  It is
00154   assumed that the unit is in TRANSPARENT, not in PACKET API mode.  To write to the 
00155   unit using packets first set packet mode (using XBeeConfig_SetPacketApiMode) then use
00156   XBee_CreateXXXPacket() followed by XBee_SendPacket().
00157   @param buffer The block of bytes to write
00158   @param count The number of bytes to write
00159   @param timeout The time in ms to linger waiting to succeed (0 for no wait)
00160   @return status
00161 */
00162 int XBee_Write( uchar *buffer, int count, int timeout )
00163 {
00164   return Serial_Write( SERIAL_0, buffer, count, timeout );
00165 }
00166 
00167 /** 
00168   Read data from the Xbee unit waiting for the specified time. Use XBee_GetReadable() to 
00169   determine how many bytes are waiting to avoid waiting.    It is
00170   assumed that the unit is in TRANSPARENT, not in PACKET API mode.  To write to the 
00171   unit using packets first set packet mode (using XBeeConfig_SetPacketApiMode) then use
00172   XBee_CreateXXXPacket() followed by XBee_SendPacket().
00173   @param buffer A pointer to the buffer to read into.
00174   @param count An integer specifying the maximum number of bytes to read.
00175   @param timeout Time in milliseconds to block waiting for the specified number of bytes. 0 means don't wait.
00176   @return number of bytes read (>=0) or error <0 .
00177 */
00178 int XBee_Read( uchar* buffer, int count, int timeout )
00179 {
00180   return Serial_Read( SERIAL_0, buffer, count, timeout );
00181 }
00182 
00183 /** 
00184   Returns the number of bytes in the queue waiting to be read.
00185   @return bytes in the receive queue.
00186 */
00187 int XBee_GetReadable( void );
00188 
00189 /** 
00190   Receive an incoming XBee packet.
00191   A single call to this will continue to read from the serial port as long as there are characters 
00192   to read or until it times out.  If a packet has not been completely received, call it repeatedly
00193   with the same packet.
00194 
00195   Clear out a packet before reading into it with a call to XBee_ResetPacket( )
00196   @param packet The XBeePacket to receive into.
00197   @param timeout The number of milliseconds to wait for a packet to arrive.  Set this to 0 to return as
00198   soon as there are no characters left to process.
00199   @return 1 if a complete packet has been received, 0 if not.
00200   @see XBeeConfig_SetPacketApiMode( )
00201   @todo Probably need some way to reset the parser if there are no bytes for a while
00202 
00203   \par Example
00204   \code
00205   // we're inside a task here...
00206   XBeePacket myPacket;
00207   XBee_ResetPacket( &myPacket );
00208   while( 1 )
00209   {
00210     if( XBee_GetPacket( &myPacket, 100 ) )
00211     {
00212       // process the new packet
00213       XBee_ResetPacket( &myPacket ); // then clear it out before reading again
00214     }
00215     Sleep( 10 );
00216   }
00217   \endcode
00218 */
00219 int XBee_GetPacket( XBeePacket* packet, int timeout )
00220 {
00221   if( CONTROLLER_OK != XBee_SetActive( 1 ) )
00222     return CONTROLLER_ERROR_SUBSYSTEM_INACTIVE;
00223 
00224   int time = TaskGetTickCount( );
00225 
00226   do
00227   {
00228     Serial_ClearErrors( SERIAL_0 );
00229     while( Serial_GetReadable( SERIAL_0 ) )
00230     {
00231       int newChar = Serial_GetChar( SERIAL_0 );
00232       if( newChar == -1 )
00233         break;
00234   
00235       switch( packet->rxState )
00236       {
00237         case XBEE_PACKET_RX_START:
00238           if( newChar == XBEE_PACKET_STARTBYTE )
00239             packet->rxState = XBEE_PACKET_RX_LENGTH_1;
00240           break;
00241         case XBEE_PACKET_RX_LENGTH_1:
00242           packet->length = newChar;
00243           packet->length <<= 8;
00244           packet->rxState = XBEE_PACKET_RX_LENGTH_2;
00245           break;
00246         case XBEE_PACKET_RX_LENGTH_2:
00247           packet->length += newChar;
00248           if( packet->length > XBEE_MAX_PACKET_SIZE ) // in case we somehow get some garbage
00249             packet->rxState = XBEE_PACKET_RX_START;
00250           else
00251             packet->rxState = XBEE_PACKET_RX_PAYLOAD;
00252           packet->crc = 0;
00253           break;
00254         case XBEE_PACKET_RX_PAYLOAD:
00255           *packet->dataPtr++ = newChar;
00256           if( ++packet->index >= packet->length )
00257             packet->rxState = XBEE_PACKET_RX_CRC;
00258           packet->crc += newChar;
00259           break;
00260         case XBEE_PACKET_RX_CRC:
00261           packet->crc += newChar;
00262           packet->rxState = XBEE_PACKET_RX_START;
00263           if( packet->crc == 0xFF )
00264             return 1;
00265           else
00266           {
00267             XBee_ResetPacket( packet );
00268             return 0;
00269           }
00270       }
00271     }
00272     if ( timeout > 0 )
00273       Sleep( 1 );
00274   } while( ( TaskGetTickCount( ) - time ) < timeout );
00275   return 0;
00276 }
00277 
00278 /** 
00279   Send an XBee packet.
00280   Use the following functions to create packets to be sent:
00281   - XBee_CreateTX16Packet( ) - create a data packet to be sent out wirelessly with a 16-bit address
00282   - XBee_CreateTX64Packet( ) - create a data packet to be sent out wirelessly with a 64-bit address
00283   - XBee_CreateATCommandPacket( ) - create an AT command to configure an attached XBee module
00284   @param packet The XBeePacket to send.
00285   @param datalength The length of the actual data being sent (not including headers, options, etc.)
00286   @return Zero on success.
00287   @see XBeeConfig_SetPacketApiMode( )
00288 
00289   \par Example
00290   \code
00291   XBeePacket txPacket;
00292   uint8 data[] = "ABC"; // 3 bytes of data
00293   XBee_CreateTX16Packet( &txPacket, 0, 0, 0, data, 3 );
00294   XBee_SendPacket( &txPacket, 3 );
00295   \endcode
00296 */
00297 int XBee_SendPacket( XBeePacket* packet, int datalength )
00298 {
00299   if( CONTROLLER_OK != XBee_SetActive( 1 ) )
00300     return CONTROLLER_ERROR_SUBSYSTEM_INACTIVE;
00301   
00302   Serial_SetChar( SERIAL_0, XBEE_PACKET_STARTBYTE );
00303   int size = datalength;
00304   switch( packet->apiId )
00305   {
00306     case XBEE_TX64: //account for apiId, frameId, 8 bytes destination, and options
00307       size += 11;
00308       break;
00309     case XBEE_TX16: //account for apiId, frameId, 2 bytes destination, and options
00310       size += 5; 
00311       break;
00312     case XBEE_ATCOMMAND: // length = API ID + Frame ID, + AT Command (+ Parameter Value)
00313       size = (datalength > 0) ? 8 : 4; // if we're writing, there are 4 bytes of data, otherwise, just the length above
00314       break;
00315     default:
00316       size = 0;
00317       break;
00318   }
00319 
00320   Serial_SetChar( SERIAL_0, (size >> 8) & 0xFF ); // send the most significant bit
00321   Serial_SetChar( SERIAL_0, size & 0xFF ); // then the LSB
00322   packet->crc = 0; // just in case it hasn't been initialized.
00323   uint8* p = (uint8*)packet;
00324   while( size-- )
00325   {
00326     Serial_SetChar( SERIAL_0, *p );
00327     packet->crc += *p++;
00328   }
00329   //uint8 test = 0xFF - packet->crc;
00330   Serial_SetChar( SERIAL_0, 0xFF - packet->crc );
00331   return CONTROLLER_OK;
00332 }
00333 
00334 /** 
00335   Initialize a packet before reading into it.
00336   @param packet The XBeePacket to initialize.
00337   @see XBee_GetPacket( )
00338 */
00339 void XBee_ResetPacket( XBeePacket* packet )
00340 {
00341   packet->dataPtr = (uint8*)packet;
00342   packet->crc = 0;
00343   packet->rxState = XBEE_PACKET_RX_START;
00344   packet->length = 0;
00345   packet->index = 0;
00346   packet->apiId = 0;
00347   memset( packet->payload, 0, 100 );
00348 }
00349 
00350 /** 
00351   Checks to see if a packet is receiving a message
00352   @param packet The XBeePacket to check
00353   @returns true if the packet is busy, false if it's free
00354 */
00355 int XBee_IsBusyPacket( XBeePacket* packet )
00356 {
00357   return ( packet->rxState != XBEE_PACKET_RX_START );
00358 }
00359 
00360 /** 
00361   Set a module into packet API mode.  
00362   XBee modules are in transparent serial port mode by default.  This allows you to work with them
00363   via the packet API.
00364 
00365   When setting this on, the XBee module needs to wait 1 second after sending the command sequence before it's 
00366   ready to receive any AT commands - this function will block for that amount of time.  Once you turn it off,
00367   you won't get any responses to packets you send the module until you turn packet mode on again.
00368   @param value 1 to turn packet mode on, 0 to turn it off.
00369   
00370   \par Example
00371   \code
00372   MyTask( void * p )
00373   {
00374     XBeeConfig_SetPacketApiMode( 1 ); // initialize the module to be in API mode
00375     while( 1 )
00376     {
00377       // your task here.
00378     }
00379   }
00380   \endcode
00381 */
00382 void XBeeConfig_SetPacketApiMode( int value )
00383 {
00384   if( CONTROLLER_OK != XBee_SetActive( 1 ) )
00385     return;
00386   
00387   if( value )
00388   {
00389     char buf[50];
00390     sprintf( buf, "+++" ); // enter command mode
00391     Serial_Write( SERIAL_0, (uchar*)buf, strlen(buf), 0 );
00392     Sleep( 1025 ); // have to wait one second after +++ to actually get set to receive in AT mode
00393     sprintf( buf, "ATAP1,CN\r" ); // turn API mode on, and leave command mode
00394     Serial_Write( SERIAL_0, (uchar*)buf, strlen(buf), 0 );
00395     Sleep(50);
00396     Serial_Flush( SERIAL_0 ); // rip the OKs out of there
00397   }
00398   else
00399   {
00400     XBeePacket xbp;
00401     uint8 params[4];
00402     memset( params, 0, 4 );
00403     XBee_CreateATCommandPacket( &xbp, 0, "AP", params, 4 );
00404     XBee_SendPacket( &xbp, 4 );
00405   }
00406 }
00407 
00408 /** 
00409   Query whether the module is in API mode.
00410   This will block for up to a 1/2 second waiting for a response from the XBee module.
00411   @return 0 if off, 1 if enabled, 2 if enabled with escape characters.
00412   
00413   \par Example
00414   \code
00415   int mode = XBeeConfig_RequestPacketApiMode( );
00416   if( mode >= 0 )
00417   {
00418     // then we have our mode
00419   }
00420   \endcode
00421 */
00422 int XBeeConfig_RequestPacketApiMode( )
00423 {
00424   XBeePacket xbp;
00425   XBee_CreateATCommandPacket( &xbp, 0x52, "AP", NULL, 0 );
00426   XBee_SendPacket( &xbp, 0 );
00427   return CONTROLLER_OK;
00428 }
00429 
00430 /** 
00431   A convenience function for creating an AT command packet.
00432   As per the XBee spec, AT Command packets that want to set/write a value must have 4 bytes of data.  
00433   Packets that query the value of an AT parameter send 0 bytes of data.  Note that multi-byte
00434   data must be sent \b big-endian (most significant byte first) - see XBee_IntToBigEndianArray( ).
00435   
00436   Make sure you're in API mode before creating & sending packets - see XBeeConfig_SetPacketApiMode( ).
00437   See the XBee documentation for the official list of AT commands that the XBee modules understand.
00438   @param packet The XBeePacket to create.
00439   @param frameID The frame ID for this packet that subsequent response/status messages can refer to.
00440   @param cmd The 2-character AT command.
00441   @param params A pointer to the buffer containing the data to be sent.
00442   @param datalength The number of bytes to send from the params buffer.
00443   
00444   \par Example - Writing
00445   \code
00446   XBeePacket txPacket;
00447   uint8 params[4];
00448   XBee_IntToBigEndianArray( 1000, params ); // set our sampling rate to 1000
00449   XBee_CreateATCommandPacket( &txPacket, 0, "IR", &params, 4 ); // set the sampling rate of the IO pins
00450   XBee_SendPacket( &txPacket, 4 );
00451   \endcode
00452 
00453   \par Example - Reading
00454   \code
00455   XBeePacket txPacket;
00456   XBee_CreateATCommandPacket( &txPacket, 0, "IR", NULL, 0 ); // query the sampling rate of the IO pins
00457   XBee_SendPacket( &txPacket, 0 );
00458   // then we'll receive a response packet
00459   \endcode
00460 */
00461 void XBee_CreateATCommandPacket( XBeePacket* packet, uint8 frameID, char* cmd, uint8* params, uint8 datalength )
00462 {
00463   packet->apiId = XBEE_ATCOMMAND;
00464   packet->atCommand.frameID = frameID;
00465   uint8* p = packet->atCommand.command;
00466   *p++ = *cmd++;
00467   *p++ = *cmd;
00468   p = packet->atCommand.parameters;
00469   while( datalength-- )
00470     *p++ = *params++;
00471 }
00472 
00473 /** 
00474   Query the address of the module.
00475   This will block for up to a 1/2 second waiting for a response from the XBee module.
00476   @return An integer corresponding to the address of the module, or negative number on failure.
00477   
00478   \par Example
00479   \code
00480   int address = XBeeConfig_RequestAddress( );
00481   if( address >= 0 )
00482   {
00483     // then we have our address
00484   }
00485   \endcode
00486 */
00487 int XBeeConfig_RequestATResponse( char* cmd )
00488 {
00489   XBeePacket xbp;
00490   XBee_CreateATCommandPacket( &xbp, 0x52, cmd, NULL, 0 );
00491   XBee_SendPacket( &xbp, 0 );
00492   return CONTROLLER_OK;
00493 }
00494 
00495 /** 
00496   Configure the IO settings on an XBee module.
00497   IO pins can have one of 5 values:
00498   - \b XBEE_IO_DISABLED
00499   - \b XBEE_IO_ANALOGIN - Analog input (10-bit)
00500   - \b XBEE_IO_DIGITALIN - Digital input
00501   - \b XBEE_IO_DIGOUT_HIGH - Digital out high
00502   - \b XBEE_IO_DIGOUT_LOW - Digital out low
00503   @param pin An integer specifying which pin to configure. There are 9 IO pins (numbered 0-8) on the XBee modules.  
00504   Only channels 0-7 can be analog inputs - channel 8 can only operate as a digital in or out.
00505   @param value An int specifying the behavior of this pin (options shown above).
00506   \par Example
00507   \code
00508   // set channel 0 to analog in
00509   XBeeConfig_SetIO( 0, XBEE_IO_ANALOGIN );
00510   \endcode
00511 */
00512 void XBeeConfig_SetIO( int pin, int value )
00513 {
00514   XBeePacket packet;
00515   XBee_ResetPacket( &packet );
00516   uint8 params[4];
00517   char cmd[2];
00518   sprintf( cmd, "D%d", pin );
00519   XBee_IntToBigEndianArray( value, params );
00520   XBee_CreateATCommandPacket( &packet, 0, cmd, params, 4 );
00521   XBee_SendPacket( &packet, 4 );
00522 }
00523 
00524 /** 
00525   Query the configuration of an IO pin.
00526   See XBeeConfig_SetIO( ) for the possible return values.
00527   This will block for up to a 1/2 second waiting for a response from the XBee module.
00528   @return An integer corresponding to the config of the requested pin, or negative number on failure.
00529   
00530   \par Example
00531   \code
00532   int pin = XBeeConfig_RequestIO( 0 ); // request the configuration of pin 0
00533   if( pin >= 0 )
00534   {
00535     // then we have our pin config
00536   }
00537   \endcode
00538 */
00539 int XBeeConfig_RequestIO( int pin )
00540 {
00541   XBeePacket xbp;
00542   char cmd[2];
00543   sprintf( cmd, "D%d", pin );
00544   XBee_CreateATCommandPacket( &xbp, 0x52, cmd, NULL, 0 );
00545   XBee_SendPacket( &xbp, 0 );
00546   return CONTROLLER_OK;
00547 }
00548 
00549 /** 
00550   Create a packet to be transmitted with a 16-bit address.
00551   If the \b frameID is 0, you won't receive a TX Status message in response.
00552 
00553   @param xbp The XBeePacket to create.
00554   @param frameID The frame ID for this packet that subsequent response/status messages can refer to.  Set to 0 for no response.
00555   @param destination The destination address for this packet.  Broadcast Address: 0xFFFF.
00556   @param options The XBee options for this packet (0 if none).
00557   @param data A pointer to the data to be sent in this packet.  Up to 100 bytes.
00558   @param datalength The number of bytes of data to be sent. Maximum 100 bytes.
00559   @return True on success, false on failure.
00560   
00561   \par Example
00562   \code
00563   XBeePacket txPacket;
00564   uint8 data[] = "ABC";
00565   XBee_CreateTX16Packet( &txPacket, 0x52, 0, 0, data, 3 );
00566   XBee_SendPacket( &txPacket, 3 );
00567   \endcode
00568 */
00569 bool XBee_CreateTX16Packet( XBeePacket* xbp, uint8 frameID, uint16 destination, uint8 options, uint8* data, uint8 datalength )
00570 {
00571   xbp->apiId = XBEE_TX16;
00572   xbp->tx16.frameID = frameID;
00573   xbp->tx16.destination[0] = destination >> 8;
00574   xbp->tx16.destination[1] = destination & 0xFF;
00575   xbp->tx16.options = options;
00576   xbp->length = datalength + 5;
00577   uint8* p = xbp->tx16.data;
00578   while( datalength-- )
00579     *p++ = *data++;
00580   return true;
00581 }
00582 
00583 /** 
00584   Create a packet to be transmitted with a 64-bit address.
00585 
00586   @param xbp The XBeePacket to create.
00587   @param frameID The frame ID for this packet that subsequent response/status messages can refer to.  Set to 0 for no response.
00588   @param destination The destination address for this packet.  Broadcast Address: 0xFFFF (same as 16b broadcast address)
00589   @param options The XBee options for this packet (0 if none).
00590   @param data A pointer to the data to be sent in this packet.  Up to 100 bytes.
00591   @param datalength The number of bytes of data to be sent. Maximum 100 bytes.
00592   @return True on success, false on failure.
00593   
00594   \par Example
00595   \code
00596   XBeePacket txPacket;
00597   uint8 data[] = "ABCDE";
00598   XBee_CreateTX16Packet( &txPacket, 0, 0, 0, data, 5 );
00599   XBee_SendPacket( &txPacket, 5 );
00600   \endcode
00601 */
00602 bool XBee_CreateTX64Packet( XBeePacket* xbp, uint8 frameID, uint64 destination, uint8 options, uint8* data, uint8 datalength )
00603 {
00604   uint8* p;
00605   int i;
00606   xbp->apiId = XBEE_TX64;
00607   xbp->tx64.frameID = frameID;
00608   for( i = 0; i < 8; i++ )
00609     xbp->tx64.destination[i] = (destination >> 8*i) & (0xFF * i); // ????????
00610   xbp->tx64.options = options;
00611   xbp->length = datalength + 5;
00612   p = xbp->tx64.data;
00613   while( datalength-- )
00614     *p++ = *data++;
00615   return true;
00616 }
00617 
00618 /** 
00619   Unpack the info from an incoming packet with a 16-bit address.
00620   Pass \b NULL into any of the parameters you don't care about.
00621   @param xbp The XBeePacket to read from.
00622   @param srcAddress The 16-bit address of this packet.
00623   @param sigstrength The signal strength of this packet.
00624   @param options The XBee options for this packet.
00625   @param data A pointer that will be set to the data of this packet.
00626   @param datalength The length of data in this packet.
00627   @return True on success, false on failure.
00628   
00629   \par Example
00630   \code
00631   XBeePacket rxPacket;
00632   if( XBee_GetPacket( &rxPacket, 0 ) )
00633   {
00634     uint16 src;
00635     uint8 sigstrength;
00636     uint8* data;
00637     uint8 datalength;
00638     if( XBee_ReadRX16Packet( &rxPacket, &src, &sigstrength, NULL, &data, &datalength ) )
00639     {
00640       // then process the new packet here
00641       XBee_ResetPacket( &rxPacket ); // and clear it out before reading again
00642     }
00643   }
00644   \endcode
00645 */
00646 bool XBee_ReadRX16Packet( XBeePacket* xbp, uint16* srcAddress, uint8* sigstrength, uint8* options, uint8** data, uint8* datalength )
00647 {
00648   if( xbp->apiId != XBEE_RX16 )
00649     return false;
00650 
00651   if( srcAddress )
00652   {
00653     *srcAddress = xbp->rx16.source[0];
00654     *srcAddress <<= 8;
00655     *srcAddress += xbp->rx16.source[1];
00656   }
00657   if( sigstrength )
00658     *sigstrength = xbp->rx16.rssi;
00659   if( options )
00660     *options = xbp->rx16.options;
00661   if( data )
00662     *data = xbp->rx16.data;
00663   if( datalength )
00664     *datalength = xbp->length - 5;
00665   return true;
00666 }
00667 
00668 /** 
00669   Unpack the info from an incoming packet with a 64-bit address.
00670   Pass \b NULL into any of the parameters you don't care about.
00671   @param xbp The XBeePacket to read from.
00672   @param srcAddress The 64-bit address of this packet.
00673   @param sigstrength The signal strength of this packet.
00674   @param options The XBee options for this packet.
00675   @param data A pointer that will be set to the data of this packet.
00676   @param datalength The length of data in this packet.
00677   @return True on success, false on failure.
00678   
00679   \par Example
00680   \code
00681   XBeePacket rxPacket;
00682   if( XBee_GetPacket( &rxPacket, 0 ) )
00683   {
00684     uint64 src;
00685     uint8 sigstrength;
00686     uint8* data;
00687     uint8 datalength;
00688     if( XBee_ReadRX64Packet( &rxPacket, &src, &sigstrength, NULL, &data, &datalength ) )
00689     {
00690       // then process the new packet here
00691       XBee_ResetPacket( &rxPacket ); // and clear it out before reading again
00692     }
00693   }
00694   \endcode
00695 */
00696 bool XBee_ReadRX64Packet( XBeePacket* xbp, uint64* srcAddress, uint8* sigstrength, uint8* options, uint8** data, uint8* datalength )
00697 {
00698   if( xbp->apiId != XBEE_RX64 )
00699     return false;
00700 
00701   int i;
00702   if( srcAddress )
00703   {
00704     for( i = 0; i < 8; i++ )
00705     {
00706       *srcAddress <<= i*8;
00707       *srcAddress += xbp->rx64.source[i];
00708     }
00709   }
00710   if( sigstrength )
00711     *sigstrength = xbp->rx64.rssi;
00712   if( options )
00713     *options = xbp->rx64.options;
00714   if( data )
00715     *data = xbp->rx64.data;
00716   if( datalength )
00717     *datalength = xbp->length - 11;
00718   return true;
00719 }
00720 
00721 /** 
00722   Unpack the info from an incoming IO packet with a 16-bit address.
00723   When an XBee module has been given a sample rate, it will sample its IO pins according to their current configuration
00724   and send an IO packet with the sample data.  This function will extract the sample info into an array of ints for you.
00725   There are 9 IO pins on the XBee modules, so be sure that the array you pass in has room for 9 ints.
00726 
00727   Pass \b NULL into any of the parameters you don't care about.
00728   @param xbp The XBeePacket to read from.
00729   @param srcAddress A pointer to a uint16 that will be filled up with the 16-bit address of this packet.
00730   @param sigstrength A pointer to a uint8 that will be filled up with the signal strength of this packet.
00731   @param options A pointer to a uint8 that will be filled up with the XBee options for this packet.
00732   @param samples A pointer to an array of ints that will be filled up with the sample values from this packet.
00733   @return True on success, false on failure.
00734   @see XBeeConfig_SetSampleRate( ), XBeeConfig_SetIOs( )
00735   
00736   \par Example
00737   \code
00738   XBeePacket rxPacket;
00739   if( XBee_GetPacket( &rxPacket, 0 ) )
00740   {
00741     uint16 src;
00742     uint8 sigstrength;
00743     int samples[9];
00744     if( XBee_ReadIO16Packet( &rxPacket, &src, &sigstrength, NULL, samples ) )
00745     {
00746       // then process the new packet here
00747       XBee_ResetPacket( &rxPacket ); // and clear it out before reading again
00748     }
00749   }
00750   \endcode
00751 */
00752 bool XBee_ReadIO16Packet( XBeePacket* xbp, uint16* srcAddress, uint8* sigstrength, uint8* options, int* samples )
00753 {
00754   if( xbp->apiId != XBEE_IO16 )
00755     return false;
00756   if( srcAddress )
00757   {
00758     *srcAddress = xbp->io16.source[0];
00759     *srcAddress <<= 8;
00760     *srcAddress += xbp->io16.source[1];
00761   }
00762   if( sigstrength )
00763     *sigstrength = xbp->io16.rssi;
00764   if( options )
00765     *options = xbp->io16.options;
00766   if( samples )
00767   {
00768     if( !XBee_GetIOValues( xbp, samples ) )
00769       return false;
00770   }
00771   return true;
00772 }
00773 
00774 /** 
00775   Unpack the info from an incoming IO packet with a 64-bit address.
00776   When an XBee module has been given a sample rate, it will sample its IO pins according to their current configuration
00777   and send an IO packet with the sample data.  This function will extract the sample info into an array of ints for you.
00778   There are 9 IO pins on the XBee modules, so be sure that the array you pass in has room for 9 ints.
00779 
00780   Pass \b NULL into any of the parameters you don't care about.
00781   @param xbp The XBeePacket to read from.
00782   @param srcAddress A pointer to a uint64 that will be filled up with the 16-bit address of this packet.
00783   @param sigstrength A pointer to a uint8 that will be filled up with the signal strength of this packet.
00784   @param options A pointer to a uint8 that will be filled up with the XBee options for this packet.
00785   @param samples A pointer to an array of ints that will be filled up with the sample values from this packet.
00786   @return True on success, false on failure.
00787   @see XBeeConfig_SetSampleRate( ), XBeeConfig_SetIOs( )
00788   
00789   \par Example
00790   \code
00791   XBeePacket rxPacket;
00792   if( XBee_GetPacket( &rxPacket, 0 ) )
00793   {
00794     uint64 src;
00795     uint8 sigstrength;
00796     int samples[9];
00797     if( XBee_ReadIO16Packet( &rxPacket, &src, &sigstrength, NULL, samples ) )
00798     {
00799       // then process the new packet here
00800       XBee_ResetPacket( &rxPacket ); // and clear it out before reading again
00801     }
00802   }
00803   \endcode
00804 */
00805 bool XBee_ReadIO64Packet( XBeePacket* xbp, uint64* srcAddress, uint8* sigstrength, uint8* options, int* samples )
00806 {
00807   if( xbp->apiId != XBEE_RX64 )
00808     return false;
00809   if( srcAddress )
00810   {
00811     int i;
00812     for( i = 0; i < 8; i++ )
00813     {
00814       *srcAddress <<= i*8;
00815       *srcAddress += xbp->io64.source[i];
00816     }
00817   }
00818   if( sigstrength )
00819     *sigstrength = xbp->io64.rssi;
00820   if( options )
00821     *options = xbp->io64.options;
00822   if( samples )
00823   {
00824     if( !XBee_GetIOValues( xbp, samples ) )
00825       return false;
00826   }
00827   return true;
00828 }
00829 
00830 /** 
00831   Unpack the info from an incoming AT Command Response packet.
00832   In response to a previous AT Command message, the module will send an AT Command Response message.
00833 
00834   Pass \b NULL into any of the parameters you don't care about.
00835   @param xbp The XBeePacket to read from.
00836   @param frameID A pointer to a uint64 that will be filled up with the 16-bit address of this packet.
00837   @param command A pointer to a uint8 that will be filled up with the signal strength of this packet.
00838   @param status A pointer to a uint8 that will be filled up with the XBee options for this packet.
00839   @param datavalue The value of the requested command.
00840   @return True on success, false on failure.
00841   
00842   \par Example
00843   \code
00844   XBeePacket rxPacket;
00845   if( XBee_GetPacket( &rxPacket, 0 ) )
00846   {
00847     uint8 frameID;
00848     char* command;
00849     uint8 status;
00850     int value = -1;
00851     if( XBee_ReadAtResponsePacket( &rxPacket, &frameID, command, &status, &value ) )
00852     {
00853       // then process the new packet here
00854       XBee_ResetPacket( &rxPacket ); // and clear it out before reading again
00855     }
00856   }
00857   \endcode
00858 */
00859 bool XBee_ReadAtResponsePacket( XBeePacket* xbp, uint8* frameID, char** command, uint8* status, int* datavalue )
00860 {
00861   if( xbp->apiId != XBEE_ATCOMMANDRESPONSE )
00862     return false;
00863   if( frameID )
00864     *frameID = xbp->atResponse.frameID;
00865   if( command )
00866     *command = (char*)xbp->atResponse.command;
00867   if( status )
00868     *status = xbp->atResponse.status;
00869   if( datavalue )
00870   {
00871     uint8 *dataPtr = xbp->atResponse.value;
00872     int i;
00873     int datalength = xbp->length - 5; // data comes after apiID, frameID, 2-bytes of cmd, and 1-byte status
00874     *datavalue = 0;
00875     for( i = 0; i < datalength; i++ )
00876     {
00877       *datavalue <<= 8;
00878       *datavalue += *dataPtr++;
00879     }
00880   }
00881   return true;
00882 }
00883 
00884 /** 
00885   Unpack the info from TX Status packet.
00886   When a TX is completed, the modules esnds a TX Status message.  This indicates whether the packet was transmitted
00887   successfully or not.  If the message you sent had a frameID of 0, a TX status message will not be generated.
00888 
00889   Pass \b NULL into any of the parameters you don't care about.
00890   @param xbp The XBeePacket to read from.
00891   @param frameID A pointer to a uint8 that will be filled up with the frame ID of this packet.
00892   @param status A pointer to a uint8 that will be filled up with the status of this packet.
00893   @return True on success, false on failure.
00894   
00895   \par Example
00896   \code
00897   XBeePacket rxPacket;
00898   if( XBee_GetPacket( &rxPacket, 0 ) )
00899   {
00900     uint8 frameID;
00901     uint8 status;
00902     if( XBee_ReadTXStatusPacket( &rxPacket, &frameID, &status ) )
00903     {
00904       // then process the new packet here
00905       XBee_ResetPacket( &rxPacket ); // and clear it out before reading again
00906     }
00907   }
00908   \endcode
00909 */
00910 bool XBee_ReadTXStatusPacket( XBeePacket* xbp, uint8* frameID, uint8* status )
00911 {
00912   if( xbp->apiId != XBEE_TXSTATUS )
00913     return false;
00914   if( frameID )
00915     *frameID = xbp->txStatus.frameID;
00916   if( status )
00917     *status = xbp->txStatus.status;
00918   return true;
00919 }
00920 
00921 /** 
00922   Save the configuration changes you've made on the module to memory.
00923   When you make configuration changes - setting the module to API mode, or configuring the sample rate, for example - 
00924   those changes will be lost when the module restarts.  Call this function to save the current state to non-volatile memory.
00925 
00926   As with the other \b XBeeConfig functions, make sure you're in API mode before trying to use this function.
00927   @return True on success, false on failure.
00928   @see XBeeConfig_SetPacketApiMode( )
00929   
00930   \par Example
00931   \code
00932   XBeeConfig_SetPacketApiMode( );
00933   XBeeConfig_SetSampleRate( 100 );
00934   XBeeConfig_WriteStateToMemory( );
00935   \endcode
00936 */
00937 void XBeeConfig_WriteStateToMemory( void )
00938 {
00939   XBeePacket xbp;
00940   uint8 params[4];
00941   memset( params, 0, 4 );
00942   XBee_CreateATCommandPacket( &xbp, 0, "WR", params, 4 );
00943   XBee_SendPacket( &xbp, 4 );
00944 }
00945 
00946 /** 
00947   Set this module's address.
00948 
00949   As with the other \b XBeeConfig functions, make sure you're in API mode before trying to use this function.
00950   @param address An integer specifying the module's address.
00951   @return True on success, false on failure.
00952   @see XBeeConfig_SetPacketApiMode( )
00953   
00954   \par Example
00955   \code
00956   XBeeConfig_SetPacketApiMode( );
00957   XBeeConfig_SetAddress( 100 );
00958   XBeeConfig_WriteStateToMemory( );
00959   \endcode
00960 */
00961 void XBeeConfig_SetAddress( uint16 address )
00962 {
00963   XBeePacket xbp;
00964   uint8 params[4]; // big endian - most significant bit first
00965   XBee_IntToBigEndianArray( address, params );
00966   XBee_CreateATCommandPacket( &xbp, 0, "MY", params, 4 );
00967   XBee_SendPacket( &xbp, 4 );
00968 }
00969 
00970 /** 
00971   Query the address of the module.
00972   This will block for up to a 1/2 second waiting for a response from the XBee module.
00973   @return An integer corresponding to the address of the module, or negative number on failure.
00974   
00975   \par Example
00976   \code
00977   int address = XBeeConfig_RequestAddress( );
00978   if( address >= 0 )
00979   {
00980     // then we have our address
00981   }
00982   \endcode
00983 */
00984 int XBeeConfig_RequestAddress( )
00985 {
00986   XBeePacket xbp;
00987   XBee_CreateATCommandPacket( &xbp, 0x52, "MY", NULL, 0 );
00988   XBee_SendPacket( &xbp, 0 );
00989   return CONTROLLER_OK;
00990 }
00991 
00992 /** 
00993   Set this PAN (Personal Area Network) ID.
00994   Only modules with matching PAN IDs can communicate with each other.  Unique PAN IDs enable control of which
00995   RF packets are received by a module.  Default is \b 0x3332.
00996 
00997   As with the other \b XBeeConfig functions, make sure you're in API mode before trying to use this function.
00998   @param id A uint16 specifying the PAN ID.
00999   @return True on success, false on failure.
01000   @see XBeeConfig_SetPacketApiMode( )
01001   
01002   \par Example
01003   \code
01004   XBeeConfig_SetPacketApiMode( );
01005   XBeeConfig_SetPanID( 0x1234 );
01006   \endcode
01007 */
01008 void XBeeConfig_SetPanID( uint16 id )
01009 {
01010   XBeePacket xbp;
01011   uint8 params[4]; // big endian - most significant bit first
01012   XBee_IntToBigEndianArray( id, params );
01013   XBee_CreateATCommandPacket( &xbp, 0, "ID", params, 4 );
01014   XBee_SendPacket( &xbp, 4 );
01015 }
01016 
01017 /** 
01018   Query the PAN ID of the module.
01019   This will block for up to a 1/2 second waiting for a response from the XBee module.
01020   @return An integer corresponding to the PAN ID of the module, or negative number on failure.
01021   
01022   \par Example
01023   \code
01024   int panid = XBeeConfig_RequestPanID( );
01025   if( panid >= 0 )
01026   {
01027     // then we have our pan id
01028   }
01029   \endcode
01030 */
01031 int XBeeConfig_RequestPanID( )
01032 {
01033   XBeePacket xbp;
01034   XBee_CreateATCommandPacket( &xbp, 0x52, "ID", NULL, 0 );
01035   XBee_SendPacket( &xbp, 0 );
01036   return CONTROLLER_OK;
01037 }
01038 
01039 /** 
01040   Set the module's channel.
01041   The channel is one of 3 addressing options available to the module - the others are the PAN ID and the
01042   destination address.  In order for modules to communicate with each other, the modules must share the same
01043   channel number.  Default is \b 0x0C.
01044 
01045   This value can have the range \b 0x0B - \b 0x1A for XBee modules, and \b 0x0C - \b 0x17 for XBee-Pro modules.
01046 
01047   As with the other \b XBeeConfig functions, make sure you're in API mode before trying to use this function.
01048   @param channel A uint8 specifying the channel.
01049   @return True on success, false on failure.
01050   @see XBeeConfig_SetPacketApiMode( )
01051   
01052   \par Example
01053   \code
01054   XBeeConfig_SetPacketApiMode( );
01055   XBeeConfig_SetChannel( 0x0D );
01056   \endcode
01057 */
01058 void XBeeConfig_SetChannel( uint8 channel )
01059 {
01060   XBeePacket xbp;
01061   uint8 params[4];
01062   XBee_IntToBigEndianArray( channel, params );
01063   XBee_CreateATCommandPacket( &xbp, 0, "CH", params, 4 );
01064   XBee_SendPacket( &xbp, 4 );
01065 }
01066 
01067 /** 
01068   Query the channel of the module.
01069   This will block for up to a 1/2 second waiting for a response from the XBee module.
01070   @return An integer corresponding to the channel of the module, or negative number on failure.
01071   
01072   \par Example
01073   \code
01074   int chan = XBeeConfig_RequestChannel( );
01075   if( chan >= 0 )
01076   {
01077     // then we have our channel
01078   }
01079   \endcode
01080 */
01081 int XBeeConfig_RequestChannel( )
01082 {
01083   XBeePacket xbp;
01084   XBee_CreateATCommandPacket( &xbp, 0x52, "CH", NULL, 0 );
01085   XBee_SendPacket( &xbp, 0 );
01086   return CONTROLLER_OK;
01087 }
01088 
01089 /** 
01090   Set the rate at which the module will sample its IO pins.
01091   When the sample rate is set, the module will sample all its IO pins according to its current IO configuration and send
01092   a packet with the sample data.  If this is set too low and the IO configuration is sampling too many channels, 
01093   the RF module won't be able to keep up.  You can also adjust how many samples are gathered before a packet is sent.
01094 
01095   As with the other \b XBeeConfig functions, make sure you're in API mode before trying to use this function.
01096   @param rate A uint16 specifying the sample rate in milliseconds.
01097   @return True on success, false on failure.
01098   @see XBeeConfig_SetIOs( ), XBeeConfig_SetPacketApiMode( )
01099   
01100   \par Example
01101   \code
01102   XBeeConfig_SetPacketApiMode( );
01103   XBeeConfig_SetSampleRate( 0x14 );
01104   \endcode
01105 */
01106 void XBeeConfig_SetSampleRate( uint16 rate )
01107 {
01108   XBeePacket xbp;
01109   uint8 params[4]; // big endian - most significant bit first
01110   XBee_IntToBigEndianArray( rate, params );
01111   XBee_CreateATCommandPacket( &xbp, 0, "IR", params, 4 );
01112   XBee_SendPacket( &xbp, 4 );
01113 }
01114 
01115 /** 
01116   Query the sample rate of the module.
01117   This will block for up to a 1/2 second waiting for a response from the XBee module.
01118   @return An integer corresponding to the sample rate of the module, or negative number on failure.
01119   
01120   \par Example
01121   \code
01122   int rate = XBeeConfig_RequestSampleRate( );
01123   if( rate >= 0 )
01124   {
01125     // then we have our rate
01126   }
01127   \endcode
01128 */
01129 int XBeeConfig_RequestSampleRate( )
01130 {
01131   XBeePacket xbp;
01132   XBee_CreateATCommandPacket( &xbp, 0x52, "IR", NULL, 0 );
01133   XBee_SendPacket( &xbp, 0 );
01134   return CONTROLLER_OK;
01135 }
01136 
01137 /** 
01138   Convert a 32-bit integer into a big endian array of 4 unsigned 8-bit integers.
01139   This is mostly useful for sending AT Command packets.
01140   @param value The value to convert.
01141   @param array An array of 4 unsigned 8-bit integers (uint8).  Be sure you have 4.
01142   \par Example
01143   see XBee_CreateATCommandPacket( ) for an example.
01144 */
01145 void XBee_IntToBigEndianArray( int value, uint8* array )
01146 {
01147   array[0] = (value >> 24) & 0xFF;
01148   array[1] = (value >> 16) & 0xFF;
01149   array[2] = (value >> 8) & 0xFF;
01150   array[3] = value & 0xFF;
01151 }
01152 
01153 /** @}
01154 */
01155 
01156 /** 
01157   Unpack IO values from an incoming packet.
01158   @param packet The XBeePacket to read from.
01159   @param inputs An array of at least 9 integers, which will be populated with the values of the 9 input lines on the XBee module.
01160   @return 1 if IO values were successfully retrieved, otherwise zero.
01161   
01162   \par Example
01163   \code
01164   XBeePacket rxPacket;
01165   if( XBee_GetPacket( &rxPacket, 0 ) )
01166   {
01167     int inputs[9];
01168     if( XBee_GetIOValues( &rxPacket, inputs ) )
01169     {
01170       // process new input values here
01171     }
01172   }
01173   \endcode
01174 */
01175 static bool XBee_GetIOValues( XBeePacket* packet, int *inputs )
01176 {
01177   if( packet->apiId == XBEE_IO16 || packet->apiId == XBEE_IO64 )
01178   {
01179     int i;
01180     static bool enabled;
01181     int digitalins = 0;
01182     uint8* p;
01183     int channelIndicators;
01184     if( packet->apiId == XBEE_IO16 )
01185     {
01186       p = packet->io16.data;
01187       channelIndicators = (packet->io16.channelIndicators[0] << 0x08) | packet->io16.channelIndicators[1];
01188     }
01189     else // packet->apiId == XBEE_IO64
01190     {
01191       p = packet->io64.data;
01192       channelIndicators = (packet->io64.channelIndicators[0] << 0x08) | packet->io64.channelIndicators[1];
01193     }
01194 
01195     for( i = 0; i < XBEE_INPUTS; i++ )
01196     {
01197       enabled = channelIndicators & 1;
01198       channelIndicators >>= 1;
01199       if( i < 9 ) // digital ins
01200       {
01201         inputs[i] = 0; // zero out the 9 inputs beforehand
01202         if( enabled )
01203         {
01204           if( !digitalins )
01205           {
01206             int dig0 = *p++ << 0x08;
01207             digitalins = dig0 | *p++;
01208           }
01209           inputs[i] = ((digitalins >> i) & 1) * 1023;
01210         }
01211       }
01212       else // analog ins
01213       {
01214         if( enabled )
01215         {
01216           int ain_msb = *p++ << 0x08;
01217           inputs[i-9] = ain_msb | *p++;
01218         }
01219       }
01220     }
01221     return true;
01222   }
01223   else
01224     return false;
01225 }
01226 
01227 #ifdef OSC
01228 #include "osc.h"
01229 
01230 /** \defgroup XBeeOSC XBee - OSC
01231   Communicate with XBee modules with the Make Controller Kit via OSC.
01232   \ingroup OSC
01233   
01234   \section devices Devices
01235   There can only be one XBee board connected to the Make Controller Kit's serial port at a time,
01236   so there is not a device index in XBee OSC messages.
01237   
01238   \section properties Properties
01239   The XBee system has the following properties:
01240   - autosend
01241   - io16
01242   - io64
01243   - rx16
01244   - rx64
01245   - tx16
01246   - tx64
01247   - tx-status
01248   - active
01249   
01250   \par Autosend
01251   The \b autosend property corresponds to whether the Make Controller will automatically send out 
01252   messages it receives from a connected XBee module.  By default, this is turned off.
01253   To turn this on, send the message
01254   \verbatim /xbee/autosend 1 \endverbatim
01255   and to turn it off, send
01256   \verbatim /xbee/autosend 0 \endverbatim
01257   All autosend messages send at the same interval.  You can set this interval, in 
01258   milliseconds, by sending the message
01259   \verbatim /system/autosend-interval 10 \endverbatim
01260   so that messages will be sent every 10 milliseconds.  This can be anywhere from 1 to 5000 milliseconds.
01261   \par
01262   You also need to select whether the board should send to you over USB or Ethernet.  Send
01263   \verbatim /system/autosend-usb 1 \endverbatim
01264   to send via USB, and 
01265   \verbatim /system/autosend-udp 1 \endverbatim
01266   to send via Ethernet.  Via Ethernet, the board will send messages to the last address it received a message from.
01267   
01268   \par io16
01269   The \b io16 property corresponds to an incoming message from an XBee module with samples
01270   from its IO pins.  The best way to use this is to turn the XBee system's autosend property
01271   on - then the Make Controller can relay io16 messages as soon as they're received.
01272   \par
01273   Once you've turned on autosend, if there are boards on your network that are sending IO packets, 
01274   you'll receive messages like
01275   \verbatim /xbee/io16 1234 28 12 0 0 1023 1023 0 512 0 1023 \endverbatim
01276   The first two numbers are:
01277   -# the address of the module that sent the message (1234 in the example above)
01278   -# signal strength (28 above) 
01279   \par
01280   The next 9 numbers are the values from the 9 IO pins on the XBee module.
01281   
01282   \par io64
01283   The \b io64 property corresponds to an incoming message from an XBee module with samples from its IO
01284   pins.  This message is just like the \b io16 message, except it's coming from a board with a 64-bit
01285   address, rather than a 16-bit address.  The structure of the message is the same (see above).
01286   
01287   \par rx16
01288   The \b rx16 property corresponds to an incoming message from a 16-bit address XBee module with arbitrary data.  
01289   The best way to use this is to turn the XBee system's autosend property
01290   on - then the Make Controller can relay rx16 messages as soon as they're received.
01291   \par
01292   Once you've turned on autosend, if there are boards on your network that are sending IO packets, 
01293   you'll receive messages like
01294   \verbatim /xbee/rx16 1234 28 0 [43 44 45 32 46 47 48] \endverbatim
01295   The first three numbers are:
01296   -# the address of the module that sent the message (1234 in the example above)
01297   -# signal strength (28 above)
01298   -# the options byte (0 above), respectively. 
01299   \par
01300   Following those is an OSC blob with the data (enclosed in square brackets above).  These are the hex values for each byte of data.
01301   
01302   \par rx64
01303   The \b rx64 property corresponds to an incoming message from an XBee module with samples from its IO
01304   pins.  This message is just like the \b io16 message, except it's coming from a board with a 64-bit
01305   address, rather than a 16-bit address.  The structure of the message is the same (see above).
01306 
01307   \par Transmit Status
01308   The \b tx-status property gives you the status of a previously sent message.  It tells you the frameID of the message
01309   that was sent and its status, which can be one of:
01310   - \b Success.  Message was successfully transmitted and received.
01311   - <b> No acknowledgement received</b>.  The message was successfully sent, but not successfully received on the other end.
01312   - <b> CCA Failure</b>.
01313   - \b Purged.
01314   \par
01315   If you don't include a frameID for the message that you sent, a tx-status message will not be generated.  An example
01316   tx-status message will look like
01317   \verbatim /xbee/tx-status 52 Success \endverbatim
01318   where 52 is the frameID and "Success" is the status.
01319   
01320   \par Active
01321   The \b active property corresponds to the active state of the XBee system.
01322   If you're not seeing appropriate responses to your messages to the XBee system, 
01323   check whether it's active by sending the message
01324   \verbatim /xbee/active \endverbatim
01325   \par
01326   You can set the active flag by sending
01327   \verbatim /xbee/active 1 \endverbatim
01328 */
01329 
01330 
01331 bool XBee_GetAutoSend( bool init )
01332 {
01333   XBee_SetActive( 1 );
01334   if( init )
01335   {
01336     int autosend;
01337     Eeprom_Read( EEPROM_XBEE_AUTOSEND, (uchar*)&autosend, 4 );
01338     XBee->autosend = (autosend == 1 ) ? 1 : 0;
01339   }
01340   return XBee->autosend;
01341 }
01342 
01343 void XBee_SetAutoSend( int onoff )
01344 {
01345   XBee_SetActive( 1 );  
01346   if( XBee->autosend != onoff )
01347   {
01348     XBee->autosend = onoff;
01349     Eeprom_Write( EEPROM_XBEE_AUTOSEND, (uchar*)&onoff, 4 );
01350   }
01351 }
01352 
01353 static char* XBeeOsc_Name = "xbee";
01354 static char* XBeeOsc_PropertyNames[] = { "active", "io16", "rx16", "autosend", "get-message", 0 }; // must have a trailing 0
01355 
01356 int XBeeOsc_PropertySet( int property, char* typedata, int channel );
01357 int XBeeOsc_PropertyGet( int property, int channel );
01358 
01359 const char* XBeeOsc_GetName( void )
01360 {
01361   return XBeeOsc_Name;
01362 }
01363 
01364 int XBeeOsc_ReceiveMessage( int channel, char* message, int length )
01365 {
01366   XBee_SetActive( 1 );
01367   int status = Osc_GeneralReceiverHelper( channel, message, length, 
01368                                 XBeeOsc_Name,
01369                                 XBeeOsc_PropertySet, XBeeOsc_PropertyGet, 
01370                                 XBeeOsc_PropertyNames );
01371 
01372   if ( status != CONTROLLER_OK )
01373     return Osc_SendError( channel, XBeeOsc_Name, status );
01374 
01375   return CONTROLLER_OK;
01376 }
01377 
01378 int XBeeOsc_PropertySet( int property, char* typedata, int channel )
01379 {
01380   switch ( property )
01381   {
01382     case 0: // active
01383     {
01384       int value;
01385       int count = Osc_ExtractData( typedata, "i", &value );
01386       if ( count != 1 )
01387         return Osc_SubsystemError( channel, XBeeOsc_Name, "Incorrect data - need an int" );
01388 
01389       XBee_SetActive( value );
01390       break;
01391     }
01392     case 1: // io16
01393     case 2: // rx16
01394       return Osc_SubsystemError( channel, XBeeOsc_Name, "Property is read-only" );
01395     case 3: // autosend
01396     {
01397       int value;
01398       int count = Osc_ExtractData( typedata, "i", &value );
01399       if ( count != 1 )
01400         return Osc_SubsystemError( channel, XBeeOsc_Name, "Incorrect data - need an int" );
01401 
01402       XBee_SetAutoSend( value );
01403       break;
01404     }
01405   }
01406   return CONTROLLER_OK;
01407 }
01408 
01409 int XBeeOsc_PropertyGet( int property, int channel )
01410 {
01411   switch ( property )
01412   {
01413     case 0: // active
01414     {
01415       char address[ OSC_SCRATCH_SIZE ];
01416       int value = XBee_GetActive( );
01417       snprintf( address, OSC_SCRATCH_SIZE, "/%s/%s", XBeeOsc_Name, XBeeOsc_PropertyNames[ property ] ); 
01418       Osc_CreateMessage( channel, address, ",i", value );
01419       break;
01420     }
01421     case 1: // io16
01422     case 2: // rx16
01423       return Osc_SubsystemError( channel, XBeeOsc_Name, "Can't get specific messages - use /xbee/get-message instead." );
01424     case 3: // autosend
01425     {
01426       char address[ OSC_SCRATCH_SIZE ];
01427       int value = XBee_GetAutoSend( false );
01428       snprintf( address, OSC_SCRATCH_SIZE, "/%s/%s", XBeeOsc_Name, XBeeOsc_PropertyNames[ property ] ); 
01429       Osc_CreateMessage( channel, address, ",i", value );
01430       break;
01431     } 
01432     case 4: // get-message
01433     {
01434       XBeePacket xbp;
01435       if( XBee_GetPacket( &xbp, XBEE_OSC_RX_TIMEOUT ) )
01436         XBeeOsc_HandleNewPacket( XBee->currentPkt, channel );
01437       break;
01438     }
01439   }
01440   return CONTROLLER_OK;
01441 }
01442 
01443 /** \defgroup XBeeConfigOSC XBee Configuration - OSC
01444   Configure an XBee module connected to your Make Controller Kit via OSC.
01445   \ingroup OSC
01446   
01447   \section devices Devices
01448   There can only be one XBee board connected to the Make Controller Kit's serial port at a time,
01449   so there is not a device index in XBee Config OSC messages.
01450   
01451   \section properties Properties
01452   The XBee Config system has the following properties:
01453   - write
01454   - get-message
01455   - packet-mode
01456   - samplerate
01457   - address
01458   - panid
01459   - channel
01460   - at-command
01461   - io
01462   - active
01463 
01464   Reading values from the XBee Config system is a bit different than the other systems.  Because we need to see any messages
01465   that arrive at the XBee module and not just the one we're requesting at a given moment, to get any message back you need to 
01466   use the \b get-message property.  Imagine the case where we want to ask the module its address, but another module is busy 
01467   sending us sensor values.  If we waited for the address message, we'd miss all the sensor values.  
01468 
01469   So to read a value, first send the request then call \b get-message until you get the response you're looking for.
01470   If you have autosend turned on, it will get messages for you, so you just need to send the request - this is much
01471   easier.
01472   
01473   \par Write
01474   When you change any of the paramters of your XBee module, it will by default revert back to its previous settings
01475   when it gets powered down.  The \b write property sets the current values (all of them) into memory.
01476   \par
01477   For example, to set the sample rate to 100 milliseconds, and save it permanently, send the messages
01478   \verbatim 
01479   /xbeeconfig/samplerate 100
01480   /xbeeconfig/write 1 \endverbatim
01481 
01482   \par Get Message
01483   The \b get-message property fetches the most recent message received by the XBee module.  If you have autosend
01484   turned on, you don't need to use get-message and, in fact, it won't have any effect.
01485   To get a message from your XBee module, send the message
01486   \verbatim /xbeeconfig/get-message\endverbatim
01487   and the board will send one back if there were any available.
01488   
01489   \par Sample Rate
01490   The \b samplerate property corresponds to how often the XBee module will sample its IO pins and send a message
01491   with those values.  If it's set to 0, the module will not sample its IO pins.  The maximum sample rate is 65535.
01492   When the sample rate is set very low, the XBee module cannot guarantee that it will be able to keep up with all
01493   the samples requested of it.
01494   \par
01495   To set the sample rate to once a second (every 1000 milliseconds), send the message
01496   \verbatim /xbeeconfig/samplerate 1000\endverbatim
01497   To read the sample rate, send the message
01498   \verbatim /xbeeconfig/samplerate \endverbatim
01499 
01500   \par Address
01501   The \b address property corresponds to the address of the XBee module.  Valid ranges for the address are
01502   from 0 - 65535.
01503   \par
01504   To set the address to 1234, send the message
01505   \verbatim /xbeeconfig/address 1234\endverbatim
01506   To read the address, send the message
01507   \verbatim /xbeeconfig/address \endverbatim
01508 
01509   \par Channel
01510   The \b channel property corresponds to the channel of the XBee module.  Valid ranges for the address are
01511   from 11 - 26 for XBee modules and 12 - 23 for XBee Pro modules.
01512   \par
01513   To set the channel to 15, send the message
01514   \verbatim /xbeeconfig/channel 15\endverbatim
01515   To read the channel, send the message
01516   \verbatim /xbeeconfig/channel \endverbatim
01517   
01518   \par AT Command
01519   The \b at-command property allows you to read/write AT commands to your XBee module via OSC.  The most common
01520   commands are included - samplerate, channel, address, etc. but this is helpful if you need to send any of the
01521   other commands to your module.  To write a command, specify the 2-letter command and then the value to set.  
01522   To enable encryption, for example, send the message
01523   \verbatim /xbeeconfig/at-command EE 1\endverbatim
01524   \par
01525   To read a value back via an AT command, simply send the 2-letter command you'd like to get the value for.
01526   To read back the hardware version, send the message
01527   \verbatim /xbeeconfig/at-command HV\endverbatim
01528   Check the XBee documentation for a complete list of commands the boards will respond to.
01529 
01530   \par PAN ID
01531   The \b panid property corresponds to the Personal Area Network ID of the XBee module.  Valid ranges for the address are
01532   from 0 - 65535.  The default value is 13106.
01533   \par
01534   To set the PAN ID to 512, send the message
01535   \verbatim /xbeeconfig/panid 512\endverbatim
01536   To read the PAN ID, send the message
01537   \verbatim /xbeeconfig/panid \endverbatim
01538   
01539   \par Input/Output Pins
01540   There are several \b io properties that allow you to configure each of the 9 IO pins on the XBee module.  
01541   Pins can be set to one of 5 values:
01542   - \b 0 - disabled
01543   - \b 2 - analogin
01544   - \b 3 - digital in
01545   - \b 4 - digital out high
01546   - \b 5 - digital out low
01547   
01548   \par
01549   There are 9 IO pins on the XBee module, numbered 0 - 8. Send messages to them by specifying \b io + their number.  
01550   Pin 8 cannot be an analogin - it can only be a digital in or out.
01551   For example,  to set IO 0 to analogin, send the message
01552   \verbatim /xbeeconfig/io0 2\endverbatim
01553   To set IO 6 to a digital in, send the message
01554   \verbatim /xbeeconfig/io6 3\endverbatim
01555   To read the configuration of pin 5, send the message
01556   \verbatim /xbeeconfig/io5 \endverbatim
01557   
01558   \par Active
01559   The \b active property corresponds to the active state of the XBee system.
01560   If you're not seeing appropriate responses to your messages to the XBee system, 
01561   check whether it's active by sending the message
01562   \verbatim /xbee/active \endverbatim
01563   \par
01564   You can set the active flag by sending
01565   \verbatim /xbee/active 1 \endverbatim
01566 */
01567 
01568 static char* XBeeConfigOsc_Name = "xbeeconfig";
01569 static char* XBeeConfigOsc_PropertyNames[] = { "active", "address", "panid", "channel", "samplerate", 
01570                                                 "write", "io0", "io1", "io2", "io3", "io4", 
01571                                                 "io5", "io6", "io7", "io8", "packet-mode", "at-command", 
01572                                                 "get-message", "write-command", "confirm", 0 }; // must have a trailing 0
01573 
01574 int XBeeConfigOsc_PropertySet( int property, char* typedata, int channel );
01575 int XBeeConfigOsc_PropertyGet( int property, int channel );
01576 
01577 const char* XBeeConfigOsc_GetName( void )
01578 {
01579   return XBeeConfigOsc_Name;
01580 }
01581 
01582 int XBeeConfigOsc_PropertySet( int property, char* typedata, int channel )
01583 {
01584   int value = -1;
01585   int count;
01586   switch ( property )
01587   {
01588     case 0: // active
01589       count = Osc_ExtractData( typedata, "i", &value );
01590       if ( count != 1 )
01591         return Osc_SubsystemError( channel, XBeeConfigOsc_Name, "Incorrect data - need an int" );
01592       XBee_SetActive( value );
01593       break;
01594     case 1: // address
01595       count = Osc_ExtractData( typedata, "i", &value );
01596       if ( count != 1 )
01597         return Osc_SubsystemError( channel, XBeeConfigOsc_Name, "Incorrect data - need an int" );
01598       XBeeConfig_SetAddress( value );
01599       break;
01600     case 2: // panid
01601       count = Osc_ExtractData( typedata, "i", &value );
01602       if ( count != 1 )
01603         return Osc_SubsystemError( channel, XBeeConfigOsc_Name, "Incorrect data - need an int" );
01604       XBeeConfig_SetPanID( value );
01605       break;
01606     case 3: // channel
01607       count = Osc_ExtractData( typedata, "i", &value );
01608       if ( count != 1 )
01609         return Osc_SubsystemError( channel, XBeeConfigOsc_Name, "Incorrect data - need an int" );
01610       XBeeConfig_SetChannel( value );
01611       break;
01612     case 4: // samplerate
01613       count = Osc_ExtractData( typedata, "i", &value );
01614       if ( count != 1 )
01615         return Osc_SubsystemError( channel, XBeeConfigOsc_Name, "Incorrect data - need an int" );
01616       XBeeConfig_SetSampleRate( value );
01617       break;
01618     case 5: // write
01619       count = Osc_ExtractData( typedata, "i", &value );
01620       if ( count != 1 )
01621         return Osc_SubsystemError( channel, XBeeConfigOsc_Name, "Incorrect data - need an int" );
01622       XBeeConfig_WriteStateToMemory( );
01623       break;
01624     case 6: // io0
01625     case 7: // io1
01626     case 8: // io2
01627     case 9: // io3
01628     case 10: // io4
01629     case 11: // io5
01630     case 12: // io6
01631     case 13: // io7
01632     case 14: // io8
01633       count = Osc_ExtractData( typedata, "i", &value );
01634       if ( count != 1 )
01635         return Osc_SubsystemError( channel, XBeeConfigOsc_Name, "Incorrect data - need an int" );
01636       XBeeConfig_SetIO( property - 6, value );
01637       break;
01638     case 15: // packet-mode
01639       count = Osc_ExtractData( typedata, "i", &value );
01640       if ( count != 1 )
01641         return Osc_SubsystemError( channel, XBeeConfigOsc_Name, "Incorrect data - need an int" );
01642       XBeeConfig_SetPacketApiMode( value );
01643       break;
01644     case 16: // at-command
01645     {
01646       char* cmd;
01647       count = Osc_ExtractData( typedata, "si", &cmd, &value );
01648       if ( count != 2 && count != 1 )
01649         return Osc_SubsystemError( channel, XBeeConfigOsc_Name, "Incorrect data - need a string, optionally followed by an int" );
01650       
01651       if( count == 2 )
01652       {
01653         XBeePacket xbp;
01654         uint8 params[4]; // big endian - most significant bit first
01655         XBee_IntToBigEndianArray( value, params );
01656         XBee_CreateATCommandPacket( &xbp, 0, cmd, params, 4 );
01657         XBee_SendPacket( &xbp, 4 );
01658       }
01659       if( count == 1 ) // this is a little wonky, but this is actually a read.
01660         value = XBeeConfig_RequestATResponse( cmd );
01661       break;
01662     }
01663     case 18: // write-command
01664     {
01665       char* cmd;
01666       count = Osc_ExtractData( typedata, "si", &cmd, &value );
01667       if ( count != 2 )
01668         return Osc_SubsystemError( channel, XBeeConfigOsc_Name, "Incorrect data - need a string and an int" );
01669       XBeePacket xbp;
01670       uint8 params[4]; // big endian - most significant bit first
01671       XBee_IntToBigEndianArray( value, params );
01672       XBee_CreateATCommandPacket( &xbp, 0, cmd, params, 4 );
01673       XBee_SendPacket( &xbp, 4 );
01674       XBee_ResetPacket( &xbp );
01675       XBee_CreateATCommandPacket( &xbp, 0, "WR", NULL, 0 );
01676       XBee_SendPacket( &xbp, 0 ); 
01677       break;
01678     }
01679     case 19: // confirm
01680     {
01681       char* cmd;
01682       count = Osc_ExtractData( typedata, "si", &cmd, &value );
01683       if ( count != 2 )
01684         return Osc_SubsystemError( channel, XBeeConfigOsc_Name, "Incorrect data - need a string and an int" );
01685       XBeePacket xbp;
01686       uint8 params[4]; // big endian - most significant bit first
01687       XBee_IntToBigEndianArray( value, params );
01688 
01689       XBee->waitingForConfirm = true;
01690       Sleep( System_GetAutoSendInterval( ) + 1 ); // make sure autosend isn't grabbing packets if it's on
01691       XBee_ResetPacket( XBee->currentPkt );
01692       while( true )
01693       {
01694         // send the setter
01695         XBee_CreateATCommandPacket( &xbp, 0x53, cmd, params, 4 );
01696         XBee_SendPacket( &xbp, 4 );
01697         XBee_ResetPacket( &xbp );
01698         // then the getter
01699         XBee_CreateATCommandPacket( &xbp, 0x52, cmd, NULL, 0 );
01700         XBee_SendPacket( &xbp, 0 );
01701         XBee_ResetPacket( &xbp );
01702         // and try to get it
01703         if( XBee_GetPacket( XBee->currentPkt, 5 ) )
01704         {
01705           XBeeOsc_HandleNewPacket( XBee->currentPkt, channel );
01706           break;
01707         }
01708         Sleep( 1 );
01709       }
01710       XBee->waitingForConfirm = false;
01711       break;
01712     }
01713   }
01714   return CONTROLLER_OK;
01715 }
01716 
01717 int XBeeConfigOsc_PropertyGet( int property, int channel )
01718 {
01719   char address[ OSC_SCRATCH_SIZE ];
01720   switch ( property )
01721   {
01722     case 0: // active
01723     {
01724       int value = XBee_GetActive( );
01725       snprintf( address, OSC_SCRATCH_SIZE, "/%s/%s", XBeeConfigOsc_Name, XBeeConfigOsc_PropertyNames[ property ] ); 
01726       Osc_CreateMessage( channel, address, ",i", value );
01727       break;
01728     }
01729     case 1: // address
01730       XBeeConfig_RequestAddress( );
01731       break;
01732     case 2: // panid
01733       XBeeConfig_RequestPanID( );
01734       break;
01735     case 3: // channel
01736       XBeeConfig_RequestChannel( );
01737       break;
01738     case 4: // samplerate
01739       XBeeConfig_RequestSampleRate( );
01740       break;
01741     case 6: // ios
01742     case 7:
01743     case 8:
01744     case 9:
01745     case 10:
01746     case 11:
01747     case 12:
01748     case 13:
01749     case 14:
01750       XBeeConfig_RequestIO( property - 6 ); // send the query
01751       break;
01752     case 15: // packet-mode
01753       XBeeConfig_RequestPacketApiMode( ); // send the query
01754       break;
01755     case 17: // get-message
01756     {
01757       XBeePacket xbp;
01758       if( XBee_GetPacket( &xbp, XBEE_OSC_RX_TIMEOUT ) )
01759         XBeeOsc_HandleNewPacket( XBee->currentPkt, channel );
01760       break;
01761     }
01762   }
01763   return CONTROLLER_OK;
01764 }
01765 
01766 int XBeeConfigOsc_ReceiveMessage( int channel, char* message, int length )
01767 {
01768   XBee_SetActive( 1 );
01769   int status = Osc_GeneralReceiverHelper( channel, message, length, 
01770                                 XBeeConfigOsc_Name,
01771                                 XBeeConfigOsc_PropertySet, XBeeConfigOsc_PropertyGet, 
01772                                 XBeeConfigOsc_PropertyNames );
01773 
01774   if ( status != CONTROLLER_OK )
01775     return Osc_SendError( channel, XBeeConfigOsc_Name, status );
01776 
01777   return CONTROLLER_OK;
01778 }
01779 
01780 int XBeeOsc_HandleNewPacket( XBeePacket* xbp, int channel )
01781 {
01782   char address[OSC_SCRATCH_SIZE];
01783   int retval = xbp->apiId;
01784   switch( xbp->apiId )
01785   {
01786     case XBEE_RX16:
01787     {
01788       uint16 srcAddr;
01789       uint8 sigStrength;
01790       uint8 opts;
01791       uint8* data;
01792       uint8 datalen;
01793       if( XBee_ReadRX16Packet( xbp, &srcAddr, &sigStrength, &opts, &data, &datalen ) )
01794       {
01795         snprintf( address, OSC_SCRATCH_SIZE, "/%s/rx16", XBeeOsc_Name );
01796         Osc_CreateMessage( channel, address, ",iiib", srcAddr, sigStrength, opts, data, datalen );
01797       }
01798       break;
01799     }
01800     case XBEE_RX64:
01801     {
01802       uint64 srcAddr;
01803       uint8 sigStrength;
01804       uint8 opts;
01805       uint8* data;
01806       uint8 datalen;
01807       if( XBee_ReadRX64Packet( xbp, &srcAddr, &sigStrength, &opts, &data, &datalen ) )
01808       {
01809         snprintf( address, OSC_SCRATCH_SIZE, "/%s/rx64", XBeeOsc_Name );
01810         Osc_CreateMessage( channel, address, ",iiib", srcAddr, sigStrength, opts, data, datalen );
01811       }
01812       break;
01813     }
01814     case XBEE_IO16:
01815     {
01816       int in[9];
01817       uint16 src;
01818       uint8 sigstrength;
01819       if( XBee_ReadIO16Packet( xbp, &src, &sigstrength, NULL, in ) )
01820       {
01821         snprintf( address, OSC_SCRATCH_SIZE, "/%s/io16", XBeeOsc_Name );
01822         Osc_CreateMessage( channel, address, ",iiiiiiiiiii", src, sigstrength, 
01823                             in[0], in[1], in[2], in[3], in[4], in[5], in[6], in[7], in[8] );
01824       }
01825       break;
01826     }
01827     case XBEE_IO64:
01828     {
01829       int in[9];
01830       uint64 src;
01831       uint8 sigstrength;
01832       if( XBee_ReadIO64Packet( xbp, &src, &sigstrength, NULL, in ) )
01833       {
01834         snprintf( address, OSC_SCRATCH_SIZE, "/%s/io64", XBeeOsc_Name );
01835         Osc_CreateMessage( channel, address, ",iiiiiiiiiii", src, sigstrength, 
01836                             in[0], in[1], in[2], in[3], in[4], in[5], in[6], in[7], in[8] );
01837       }
01838       break;
01839     }
01840     case XBEE_TXSTATUS:
01841     {
01842       uint8 frameID;
01843       uint8 status;
01844       if( XBee_ReadTXStatusPacket( xbp, &frameID, &status ) )
01845       {
01846         snprintf( address, OSC_SCRATCH_SIZE, "/%s/tx-status", XBeeOsc_Name );
01847         char* statusText = "No status received";
01848         switch( status )
01849         {
01850           case 0:
01851             statusText = "Success";
01852             break;
01853           case 1:
01854             statusText = "No acknowledgement received";
01855             break;
01856           case 2:
01857             statusText = "CCA Failure";
01858             break;
01859           case 3:
01860             statusText = "Purged";
01861             break;
01862         }
01863         Osc_CreateMessage( channel, address, ",is", frameID, statusText );
01864       }
01865       break;
01866     }
01867     case XBEE_ATCOMMANDRESPONSE:
01868     {
01869       uint8 frameID;
01870       char* command;
01871       uint8 status;
01872       int value;
01873       if( XBee_ReadAtResponsePacket( xbp, &frameID, &command, &status, &value ) )
01874       {
01875         char cmd[3];
01876         cmd[0] = *command;
01877         cmd[1] = *(command+1);
01878         cmd[2] = '\0';
01879         if( strcmp( cmd, "IR" ) == 0 )
01880         {
01881           snprintf( address, OSC_SCRATCH_SIZE, "/%s/samplerate", XBeeConfigOsc_Name );
01882           Osc_CreateMessage( channel, address, ",i", value );
01883         }
01884         else if( strcmp( cmd, "MY" ) == 0 )
01885         {
01886           snprintf( address, OSC_SCRATCH_SIZE, "/%s/address", XBeeConfigOsc_Name );
01887           Osc_CreateMessage( channel, address, ",i", value );
01888         }
01889         else if( strcmp( cmd, "CH" ) == 0 )
01890         {
01891           snprintf( address, OSC_SCRATCH_SIZE, "/%s/channel", XBeeConfigOsc_Name );
01892           Osc_CreateMessage( channel, address, ",i", value );
01893         }
01894         else if( strcmp( cmd, "ID" ) == 0 )
01895         {
01896           snprintf( address, OSC_SCRATCH_SIZE, "/%s/panid", XBeeConfigOsc_Name );
01897           Osc_CreateMessage( channel, address, ",i", value );
01898         }
01899         else
01900         {
01901           snprintf( address, OSC_SCRATCH_SIZE, "/%s/at-command", XBeeConfigOsc_Name );
01902           Osc_CreateMessage( channel, address, ",si", cmd, value );
01903         }
01904       }
01905       break;
01906     }
01907   }
01908   XBee_ResetPacket( xbp );
01909   return retval;
01910 }
01911 
01912 int XBeeOsc_Async( int channel )
01913 {
01914   XBee_SetActive( 1 );
01915   int newMsgs = 0;
01916 
01917   if( !XBee_GetAutoSend( false ) || XBee->waitingForConfirm )
01918     return newMsgs;
01919 
01920   while( XBee_GetPacket( XBee->currentPkt, 0 ) )
01921   {
01922     XBeeOsc_HandleNewPacket( XBee->currentPkt, channel );
01923     newMsgs++;
01924   }
01925   return newMsgs;
01926 }
01927 
01928 #endif // OSC
01929 
01930 

The Make Controller Kit is an open source project maintained by MakingThings.
MakingThings code is released under the Apache 2.0 license.
Bug tracker, development wiki and status can be found at http://dev.makingthings.com.
This document was last updated on 18 May 2009.