- 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.