API for communicating with XBee devices.

Dependencies:   CircularBuffer FixedLengthList

Dependents:   XBeeApiTest XBeeApiSimpleATCmdsExample XBeeApiBroadcastExample XBeeApiBroadcastExampleRTOS ... more

Overview

XBeeApi is intended to be a library for providing a high-level API interface to the XBee - for example getChannel() and setChannel(2) methods rather than needing to send( "ATCH" ) and send( "ATCH 2" ) - and then de-code the responses.

See the notebook page here for a description of how the API works & some details on the various classes.

Features:

  • Support for transmission & reception of data packets
  • Support for reading & changing settings
  • Support for "Remote AT" interface to access settings & I/O channels on remote XBees
  • XBeeApi should work if you're using mbed-rtos, though it is not currently threadsafe. Take a look at the XBeeApiBroadcastExampleRTOS example if you're including mbed-rtos.

Example Programs

There are also example programs available:

Transmit

Import programXBeeApiSimpleBroadcastExample

Simple example of how to use XBeeApi - set up the XBee, configure P2P networking then transmit a frame.

Import programXBeeApiBroadcastExample

Example for XBeeAPI; a little more involved than XBeeApiSimpleBroadcastExample with report on failure to set up the XBee and on the transmit status of the message.

Import programXBeeApiBroadcastExampleRTOS

Example of using the XBeeApi library to broadcast a message, based on XBeeApiBroadcastExample. This example shows how to use the library when using mbed-rtos. Before compiling you must open "XbeeApi\Config\XBeeApiCfg.hpp" and change the '#if 0' to '#if 1' on the line above the comment reading "Use RTOS features to make XBeeApi threadsafe"

Settings/Status

Import programXBeeApiSimpleATCmdsExample

Simple example of using XBeeApi to send AT-style commands to the XBee

Import programXBeeApiRemoteATCmdsExample

Example of using the XBeeApi library to send AT commands to remote XBee devices in order to read/write settings

Receive

Import programXBeeApiSimpleReceiveExample

Simple example of using XBeeApi to receive data packets via wireless

Import programXBeeApiReceiveCallbackExample

Example of using the XBeeApi library to receive a message via a callback method

Import programXBeeApiReceiveCallbackExampleRTOS

Example of using the XBeeApi library to receive a message via a callback method. This example shows how to use the library when using mbed-rtos. See the comment at the top of main.cpp

Remote I/O

Import programXBeeApiRemoteIOExample

Example of using the XBeeApi library to read inputs on a remote XBee

If you have 2 mbed connected XBees available then you can use XBeeApiSimpleReceiveExample and XBeeApiSimpleBroadcastExample as a pair.

Note that this is still a work in progress! XBeeApiTodoList tracks some of the functionality still to be added.

Committer:
johnb
Date:
Thu Feb 06 21:25:17 2014 +0000
Revision:
29:c6d037cceb02
Parent:
16:8095c43a2a6e
Child:
33:eccf4725930c
Infrastructure for supporting different XBee models; Change XBeeApiCmdAt constructor to allown an XBeeDevice to be passed

Who changed what in which revision?

UserRevisionLine numberNew contents of line
johnb 5:b40a6fd3a334 1 /**
johnb 5:b40a6fd3a334 2
johnb 5:b40a6fd3a334 3 Copyright 2014 John Bailey
johnb 5:b40a6fd3a334 4
johnb 5:b40a6fd3a334 5 Licensed under the Apache License, Version 2.0 (the "License");
johnb 5:b40a6fd3a334 6 you may not use this file except in compliance with the License.
johnb 5:b40a6fd3a334 7 You may obtain a copy of the License at
johnb 5:b40a6fd3a334 8
johnb 5:b40a6fd3a334 9 http://www.apache.org/licenses/LICENSE-2.0
johnb 5:b40a6fd3a334 10
johnb 5:b40a6fd3a334 11 Unless required by applicable law or agreed to in writing, software
johnb 5:b40a6fd3a334 12 distributed under the License is distributed on an "AS IS" BASIS,
johnb 5:b40a6fd3a334 13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
johnb 5:b40a6fd3a334 14 See the License for the specific language governing permissions and
johnb 5:b40a6fd3a334 15 limitations under the License.
johnb 5:b40a6fd3a334 16
johnb 5:b40a6fd3a334 17 */
johnb 5:b40a6fd3a334 18
johnb 5:b40a6fd3a334 19 #include "XBeeDevice.hpp"
johnb 16:8095c43a2a6e 20 #include "XBeeApiCfg.hpp"
johnb 5:b40a6fd3a334 21
johnb 5:b40a6fd3a334 22 /** Number of bytes we need to 'peek' into the receive buffer in order to retrieve the
johnb 5:b40a6fd3a334 23 payload length */
johnb 5:b40a6fd3a334 24 #define INITIAL_PEEK_LEN (3U)
johnb 5:b40a6fd3a334 25
johnb 5:b40a6fd3a334 26 /** Enum of bytes with a special meaning when communicating with the XBee in API
johnb 5:b40a6fd3a334 27 mode. In escaped mode, these are the bytes that need to be escaped */
johnb 5:b40a6fd3a334 28 typedef enum
johnb 5:b40a6fd3a334 29 {
johnb 5:b40a6fd3a334 30 XBEE_SB_XON = 0x11,
johnb 5:b40a6fd3a334 31 XBEE_SB_XOFF = 0x13,
johnb 5:b40a6fd3a334 32 XBEE_SB_FRAME_DELIMITER = 0x7E,
johnb 5:b40a6fd3a334 33 XBEE_SB_ESCAPE = 0x7D
johnb 5:b40a6fd3a334 34 } XBeeSerialSpecialBytes_e;
johnb 5:b40a6fd3a334 35
johnb 5:b40a6fd3a334 36 /** ASCII command to the XBee to request API mode 2 */
johnb 5:b40a6fd3a334 37 const char api_mode2_cmd[] = { 'A', 'T', 'A', 'P', ' ', '2', '\r' };
johnb 5:b40a6fd3a334 38
johnb 5:b40a6fd3a334 39 /** ASCII command to the XBee to request that it exit command mode */
johnb 5:b40a6fd3a334 40 const char exit_cmd_mode_cmd[] = { 'A', 'T', 'C', 'N', '\r' };
johnb 5:b40a6fd3a334 41
johnb 29:c6d037cceb02 42 XBeeDevice::XBeeDevice( PinName p_tx, PinName p_rx, PinName p_rts, PinName p_cts ): m_model( XBeeDevice::XBEEDEVICE_S1 ), m_if( p_tx, p_rx )
johnb 5:b40a6fd3a334 43 {
johnb 5:b40a6fd3a334 44 m_escape = true;
johnb 5:b40a6fd3a334 45 m_inAtCmdMode = false;
johnb 5:b40a6fd3a334 46 m_rxMsgLastWasEsc = false;
johnb 5:b40a6fd3a334 47
johnb 5:b40a6fd3a334 48 /* Can only do flow control on devices which support it */
johnb 5:b40a6fd3a334 49 #if defined ( DEVICE_SERIAL_FC )
johnb 5:b40a6fd3a334 50 /* TODO: need rts and cts both set? */
johnb 5:b40a6fd3a334 51 m_if.set_flow_control( mbed::SerialBase::Flow.RTSCTS, p_rts, p_cts );
johnb 5:b40a6fd3a334 52 #endif
johnb 5:b40a6fd3a334 53
johnb 5:b40a6fd3a334 54 /* Attach RX call-back to the serial interface */
johnb 5:b40a6fd3a334 55 m_if.attach( this, &XBeeDevice::if_rx, Serial::RxIrq);
johnb 5:b40a6fd3a334 56 }
johnb 5:b40a6fd3a334 57
johnb 5:b40a6fd3a334 58 XBeeDevice::~XBeeDevice( void )
johnb 5:b40a6fd3a334 59 {
johnb 5:b40a6fd3a334 60 /* Iterate all of the decoders and un-register them */
johnb 5:b40a6fd3a334 61 for( FixedLengthList<XBeeApiFrameDecoder*, XBEEAPI_CONFIG_DECODER_LIST_SIZE>::iterator it = m_decoders.begin() ;
johnb 5:b40a6fd3a334 62 it != m_decoders.end();
johnb 5:b40a6fd3a334 63 ++it ) {
johnb 5:b40a6fd3a334 64 (*it)->unregisterCallback();
johnb 5:b40a6fd3a334 65 }
johnb 5:b40a6fd3a334 66 }
johnb 5:b40a6fd3a334 67
johnb 29:c6d037cceb02 68 XBeeDevice::XBeeDeviceModel_t XBeeDevice::getXBeeModel() const
johnb 29:c6d037cceb02 69 {
johnb 29:c6d037cceb02 70 return m_model;
johnb 29:c6d037cceb02 71 }
johnb 29:c6d037cceb02 72
johnb 29:c6d037cceb02 73 void XBeeDevice::setXBeeModel( const XBeeDevice::XBeeDeviceModel_t p_model )
johnb 29:c6d037cceb02 74 {
johnb 29:c6d037cceb02 75 m_model = p_model;
johnb 29:c6d037cceb02 76 }
johnb 29:c6d037cceb02 77
johnb 5:b40a6fd3a334 78 void XBeeDevice::if_rx( void )
johnb 5:b40a6fd3a334 79 {
johnb 5:b40a6fd3a334 80 /* Keep going while there are bytes to be read */
johnb 5:b40a6fd3a334 81 while(m_if.readable()) {
johnb 5:b40a6fd3a334 82
johnb 5:b40a6fd3a334 83 uint8_t c = m_if.getc();
johnb 5:b40a6fd3a334 84
johnb 5:b40a6fd3a334 85 /* Sanity check that if we're starting from an empty buffer the byte that we're
johnb 5:b40a6fd3a334 86 receiving is a frame delimiter */
johnb 5:b40a6fd3a334 87 if(( m_inAtCmdMode ) ||
johnb 5:b40a6fd3a334 88 (( c == XBEE_SB_FRAME_DELIMITER ) ||
johnb 5:b40a6fd3a334 89 ( m_rxBuff.getSize() )))
johnb 5:b40a6fd3a334 90 {
johnb 5:b40a6fd3a334 91 /* If it's an escape character we want to de-code the escape, so flag
johnb 5:b40a6fd3a334 92 that we have a pending escape but don't modify the rx buffer */
johnb 5:b40a6fd3a334 93 if( m_escape &&
johnb 5:b40a6fd3a334 94 ( c == XBEE_SB_ESCAPE ))
johnb 5:b40a6fd3a334 95 {
johnb 5:b40a6fd3a334 96 m_rxMsgLastWasEsc = true;
johnb 5:b40a6fd3a334 97 }
johnb 5:b40a6fd3a334 98 else
johnb 5:b40a6fd3a334 99 {
johnb 5:b40a6fd3a334 100 if( m_rxMsgLastWasEsc ) {
johnb 5:b40a6fd3a334 101 c = c ^ 0x20;
johnb 5:b40a6fd3a334 102 m_rxMsgLastWasEsc = false;
johnb 5:b40a6fd3a334 103 }
johnb 5:b40a6fd3a334 104 m_rxBuff.write( &c, 1 );
johnb 5:b40a6fd3a334 105 }
johnb 5:b40a6fd3a334 106 } else {
johnb 5:b40a6fd3a334 107 /* TODO */
johnb 5:b40a6fd3a334 108 }
johnb 5:b40a6fd3a334 109 }
johnb 5:b40a6fd3a334 110
johnb 5:b40a6fd3a334 111 if( m_inAtCmdMode )
johnb 5:b40a6fd3a334 112 {
johnb 7:2f1e157cdd1c 113 /* Safeguard - if we're in cmd mode, clear out status associated with API mode */
johnb 5:b40a6fd3a334 114 m_rxMsgLastWasEsc = false;
johnb 5:b40a6fd3a334 115 }
johnb 7:2f1e157cdd1c 116 else
johnb 7:2f1e157cdd1c 117 {
johnb 7:2f1e157cdd1c 118 /* Check to see if there's API data to decode */
johnb 7:2f1e157cdd1c 119 checkRxDecode();
johnb 7:2f1e157cdd1c 120 }
johnb 5:b40a6fd3a334 121 }
johnb 5:b40a6fd3a334 122
johnb 5:b40a6fd3a334 123 void XBeeDevice::checkRxDecode( void )
johnb 5:b40a6fd3a334 124 {
johnb 5:b40a6fd3a334 125 uint8_t buff[INITIAL_PEEK_LEN];
johnb 7:2f1e157cdd1c 126 bool cont = false;
johnb 5:b40a6fd3a334 127
johnb 7:2f1e157cdd1c 128 /* Ensure that we're delimiter aligned - this should allow recovery in the case that
johnb 7:2f1e157cdd1c 129 we've missed bytes and somehow become unaligned */
johnb 7:2f1e157cdd1c 130 while( m_rxBuff.getSize() &&
johnb 7:2f1e157cdd1c 131 ( m_rxBuff[0] != XBEE_SB_FRAME_DELIMITER ))
johnb 5:b40a6fd3a334 132 {
johnb 7:2f1e157cdd1c 133 m_rxBuff.chomp( 1 );
johnb 7:2f1e157cdd1c 134 }
johnb 7:2f1e157cdd1c 135
johnb 7:2f1e157cdd1c 136 do {
johnb 7:2f1e157cdd1c 137 /* Get an initial portion of data from the read buffer so that the message length can be determined */
johnb 7:2f1e157cdd1c 138 uint16_t len = m_rxBuff.peek( buff, INITIAL_PEEK_LEN );
johnb 7:2f1e157cdd1c 139 cont = false;
johnb 7:2f1e157cdd1c 140
johnb 7:2f1e157cdd1c 141 /* Ensure that sufficient data was received - already know that we should be delimiter aligned based on the above */
johnb 7:2f1e157cdd1c 142 if( len >= INITIAL_PEEK_LEN )
johnb 5:b40a6fd3a334 143 {
johnb 7:2f1e157cdd1c 144 /* Try and get enough data to cover the whole message */
johnb 7:2f1e157cdd1c 145 const uint16_t cmdLen = MSG_LEN_IN_BUFFER( buff ) + XBEE_API_FRAME_OVERHEAD;
johnb 7:2f1e157cdd1c 146 uint8_t cmdBuff[cmdLen];
johnb 7:2f1e157cdd1c 147 uint16_t len = m_rxBuff.peek( cmdBuff, cmdLen );
johnb 7:2f1e157cdd1c 148
johnb 7:2f1e157cdd1c 149 /* Check that we've received the entire frame */
johnb 7:2f1e157cdd1c 150 if( len >= cmdLen )
johnb 7:2f1e157cdd1c 151 {
johnb 7:2f1e157cdd1c 152 /* TODO: Verify checksum */
johnb 7:2f1e157cdd1c 153
johnb 7:2f1e157cdd1c 154 /* Iterate all of the decoders */
johnb 7:2f1e157cdd1c 155 for( FixedLengthList<XBeeApiFrameDecoder*, XBEEAPI_CONFIG_DECODER_LIST_SIZE>::iterator it = m_decoders.begin() ;
johnb 7:2f1e157cdd1c 156 it != m_decoders.end();
johnb 7:2f1e157cdd1c 157 ++it ) {
johnb 7:2f1e157cdd1c 158
johnb 7:2f1e157cdd1c 159 bool processed = (*it)->decodeCallback( cmdBuff, cmdLen );
johnb 7:2f1e157cdd1c 160 if( processed )
johnb 7:2f1e157cdd1c 161 {
johnb 7:2f1e157cdd1c 162 break;
johnb 7:2f1e157cdd1c 163 }
johnb 7:2f1e157cdd1c 164 }
johnb 7:2f1e157cdd1c 165 /* Remove the data from the receive buffer - either it was decoded (all well and good)
johnb 7:2f1e157cdd1c 166 or it wasn't, in which case we need to get rid of it to prevent it from jamming
johnb 7:2f1e157cdd1c 167 up the message queue */
johnb 7:2f1e157cdd1c 168 m_rxBuff.chomp( cmdLen );
johnb 5:b40a6fd3a334 169
johnb 7:2f1e157cdd1c 170 /* Successfully decoded 1 message ... there may be more waiting in the buffer! */
johnb 7:2f1e157cdd1c 171 cont = true;
johnb 7:2f1e157cdd1c 172 }
johnb 5:b40a6fd3a334 173 }
johnb 7:2f1e157cdd1c 174 } while( cont );
johnb 5:b40a6fd3a334 175 }
johnb 5:b40a6fd3a334 176
johnb 5:b40a6fd3a334 177 bool XBeeDevice::registerDecoder( XBeeApiFrameDecoder* const p_decoder )
johnb 5:b40a6fd3a334 178 {
johnb 5:b40a6fd3a334 179 bool ret_val = false;
johnb 5:b40a6fd3a334 180 if( p_decoder != NULL )
johnb 5:b40a6fd3a334 181 {
johnb 7:2f1e157cdd1c 182 /* Check if decoder already registered */
johnb 7:2f1e157cdd1c 183 if( !m_decoders.inList( p_decoder ) )
johnb 7:2f1e157cdd1c 184 {
johnb 5:b40a6fd3a334 185 m_decoders.push( p_decoder );
johnb 5:b40a6fd3a334 186 p_decoder->registerCallback( this );
johnb 5:b40a6fd3a334 187 ret_val = true;
johnb 5:b40a6fd3a334 188 }
johnb 5:b40a6fd3a334 189 }
johnb 5:b40a6fd3a334 190 return ret_val;
johnb 5:b40a6fd3a334 191 }
johnb 5:b40a6fd3a334 192
johnb 5:b40a6fd3a334 193 bool XBeeDevice::unregisterDecoder( XBeeApiFrameDecoder* const p_decoder )
johnb 5:b40a6fd3a334 194 {
johnb 5:b40a6fd3a334 195 bool ret_val = false;
johnb 5:b40a6fd3a334 196 if( p_decoder != NULL )
johnb 5:b40a6fd3a334 197 {
johnb 7:2f1e157cdd1c 198 if( m_decoders.remove( p_decoder ) )
johnb 7:2f1e157cdd1c 199 {
johnb 7:2f1e157cdd1c 200 p_decoder->unregisterCallback();
johnb 7:2f1e157cdd1c 201 ret_val = true;
johnb 5:b40a6fd3a334 202 }
johnb 5:b40a6fd3a334 203 }
johnb 5:b40a6fd3a334 204 return ret_val;
johnb 5:b40a6fd3a334 205 }
johnb 5:b40a6fd3a334 206
johnb 16:8095c43a2a6e 207 void XBeeDevice::SendFrame( XBeeApiFrame* const p_cmd )
johnb 5:b40a6fd3a334 208 {
johnb 5:b40a6fd3a334 209 uint8_t sum = 0U;
johnb 5:b40a6fd3a334 210 uint16_t len;
johnb 5:b40a6fd3a334 211 uint16_t i;
johnb 5:b40a6fd3a334 212 const uint8_t* cmdData;
johnb 10:0d084d0253a7 213 uint16_t written = 0;
johnb 5:b40a6fd3a334 214
johnb 5:b40a6fd3a334 215 #if defined XBEEAPI_CONFIG_USING_RTOS
johnb 5:b40a6fd3a334 216 m_ifMutex.lock();
johnb 5:b40a6fd3a334 217 #endif
johnb 5:b40a6fd3a334 218
johnb 5:b40a6fd3a334 219 xbeeWrite( XBEE_SB_FRAME_DELIMITER, false );
johnb 5:b40a6fd3a334 220
johnb 5:b40a6fd3a334 221 len = p_cmd->getCmdLen();
johnb 5:b40a6fd3a334 222 xbeeWrite((uint8_t)(len >> 8U));
johnb 5:b40a6fd3a334 223 xbeeWrite((uint8_t)(len & 0xFF));
johnb 5:b40a6fd3a334 224
johnb 5:b40a6fd3a334 225 sum += xbeeWrite((uint8_t)p_cmd->getApiId());
johnb 10:0d084d0253a7 226 len--;
johnb 5:b40a6fd3a334 227
johnb 10:0d084d0253a7 228 /* While data still to go out */
johnb 10:0d084d0253a7 229 while( written < len )
johnb 5:b40a6fd3a334 230 {
johnb 10:0d084d0253a7 231 uint16_t buffer_len;
johnb 10:0d084d0253a7 232
johnb 10:0d084d0253a7 233 /* Get the next chunk of data from the frame object */
johnb 10:0d084d0253a7 234 p_cmd->getDataPtr( written, &cmdData, &buffer_len );
johnb 10:0d084d0253a7 235
johnb 10:0d084d0253a7 236 /* Write the buffer to the XBee */
johnb 10:0d084d0253a7 237 for( i = 0;
johnb 10:0d084d0253a7 238 i < buffer_len;
johnb 10:0d084d0253a7 239 ++i,++written )
johnb 10:0d084d0253a7 240 {
johnb 10:0d084d0253a7 241 sum += xbeeWrite(cmdData[i]);
johnb 10:0d084d0253a7 242 }
johnb 5:b40a6fd3a334 243 }
johnb 6:3cb62daace78 244
johnb 5:b40a6fd3a334 245 /* Checksum is 0xFF - summation of bytes (excluding delimiter and length) */
johnb 5:b40a6fd3a334 246 xbeeWrite( (uint8_t)0xFFU - sum );
johnb 5:b40a6fd3a334 247
johnb 5:b40a6fd3a334 248 fflush( m_if );
johnb 16:8095c43a2a6e 249 #if defined XBEE_DEBUG_DEVICE_DUMP_MESSAGE_DECODE
johnb 16:8095c43a2a6e 250 m_if.printf("\r\n");
johnb 16:8095c43a2a6e 251 #endif
johnb 5:b40a6fd3a334 252
johnb 5:b40a6fd3a334 253 #if defined XBEEAPI_CONFIG_USING_RTOS
johnb 5:b40a6fd3a334 254 m_ifMutex.unlock();
johnb 5:b40a6fd3a334 255 #endif
johnb 5:b40a6fd3a334 256 }
johnb 5:b40a6fd3a334 257
johnb 5:b40a6fd3a334 258 uint8_t XBeeDevice::xbeeWrite( uint8_t p_byte, bool p_doEscape )
johnb 5:b40a6fd3a334 259 {
johnb 5:b40a6fd3a334 260 uint8_t c_sum = 0;
johnb 5:b40a6fd3a334 261
johnb 5:b40a6fd3a334 262 if (p_doEscape && m_escape &&
johnb 5:b40a6fd3a334 263 ((p_byte == XBEE_SB_FRAME_DELIMITER ) ||
johnb 5:b40a6fd3a334 264 (p_byte == XBEE_SB_ESCAPE ) ||
johnb 5:b40a6fd3a334 265 (p_byte == XBEE_SB_XON ) ||
johnb 5:b40a6fd3a334 266 (p_byte == XBEE_SB_XOFF)))
johnb 5:b40a6fd3a334 267 {
johnb 16:8095c43a2a6e 268 #if defined XBEE_DEBUG_DEVICE_DUMP_MESSAGE_DECODE
johnb 5:b40a6fd3a334 269 m_if.printf("%02x ",XBEE_SB_ESCAPE);
johnb 5:b40a6fd3a334 270 m_if.printf("%02x ",p_byte ^ 0x20);
johnb 16:8095c43a2a6e 271 #else
johnb 5:b40a6fd3a334 272 m_if.putc(XBEE_SB_ESCAPE);
johnb 5:b40a6fd3a334 273 m_if.putc(p_byte ^ 0x20);
johnb 16:8095c43a2a6e 274 #endif
johnb 5:b40a6fd3a334 275 c_sum += XBEE_SB_ESCAPE;
johnb 5:b40a6fd3a334 276 c_sum += p_byte ^ 0x20;
johnb 5:b40a6fd3a334 277 } else {
johnb 16:8095c43a2a6e 278 #if defined XBEE_DEBUG_DEVICE_DUMP_MESSAGE_DECODE
johnb 5:b40a6fd3a334 279 m_if.printf("%02x ",p_byte);
johnb 16:8095c43a2a6e 280 #else
johnb 5:b40a6fd3a334 281 m_if.putc(p_byte);
johnb 16:8095c43a2a6e 282 #endif
johnb 5:b40a6fd3a334 283 c_sum += p_byte;
johnb 5:b40a6fd3a334 284 }
johnb 5:b40a6fd3a334 285 return c_sum;
johnb 5:b40a6fd3a334 286 }
johnb 5:b40a6fd3a334 287
johnb 5:b40a6fd3a334 288 #define IS_OK( _b ) (( _b[ 0 ] == 'O' ) && ( _b[ 1 ] == 'K' ) && ( _b[ 2 ] == '\r' ))
johnb 5:b40a6fd3a334 289 #define OK_LEN (3U)
johnb 5:b40a6fd3a334 290
johnb 5:b40a6fd3a334 291 XBeeDevice::XBeeDeviceReturn_t XBeeDevice::SendFrame( const char* const p_dat, size_t p_len, int p_wait_ms )
johnb 5:b40a6fd3a334 292 {
johnb 5:b40a6fd3a334 293 XBeeDeviceReturn_t ret_val;
johnb 5:b40a6fd3a334 294
johnb 5:b40a6fd3a334 295 if( m_inAtCmdMode )
johnb 5:b40a6fd3a334 296 {
johnb 5:b40a6fd3a334 297 #if defined XBEEAPI_CONFIG_USING_RTOS
johnb 5:b40a6fd3a334 298 m_ifMutex.lock();
johnb 5:b40a6fd3a334 299 #endif
johnb 5:b40a6fd3a334 300 for( size_t i = 0;
johnb 5:b40a6fd3a334 301 i < p_len;
johnb 5:b40a6fd3a334 302 i++ ) {
johnb 5:b40a6fd3a334 303 m_if.putc(p_dat[i]);
johnb 5:b40a6fd3a334 304 }
johnb 5:b40a6fd3a334 305
johnb 5:b40a6fd3a334 306 fflush( m_if );
johnb 5:b40a6fd3a334 307
johnb 5:b40a6fd3a334 308 wait_ms( p_wait_ms );
johnb 5:b40a6fd3a334 309
johnb 5:b40a6fd3a334 310 /* Check the response for the OK indicator */
johnb 5:b40a6fd3a334 311 if( m_rxBuff.getSize() == OK_LEN )
johnb 5:b40a6fd3a334 312 {
johnb 5:b40a6fd3a334 313 uint8_t ok_buff[OK_LEN];
johnb 5:b40a6fd3a334 314 m_rxBuff.read( ok_buff, OK_LEN );
johnb 5:b40a6fd3a334 315
johnb 5:b40a6fd3a334 316 if( IS_OK( ok_buff ))
johnb 5:b40a6fd3a334 317 {
johnb 5:b40a6fd3a334 318 ret_val = XBEEDEVICE_OK;
johnb 5:b40a6fd3a334 319 }
johnb 5:b40a6fd3a334 320 else
johnb 5:b40a6fd3a334 321 {
johnb 5:b40a6fd3a334 322 ret_val = XBEEDEVICE_UNEXPECTED_DATA;
johnb 5:b40a6fd3a334 323 }
johnb 5:b40a6fd3a334 324 }
johnb 5:b40a6fd3a334 325 else
johnb 5:b40a6fd3a334 326 {
johnb 5:b40a6fd3a334 327 ret_val = XBEEDEVICE_UNEXPECTED_LENGTH;
johnb 5:b40a6fd3a334 328 }
johnb 5:b40a6fd3a334 329 #if defined XBEEAPI_CONFIG_USING_RTOS
johnb 5:b40a6fd3a334 330 m_ifMutex.unlock();
johnb 5:b40a6fd3a334 331 #endif
johnb 5:b40a6fd3a334 332 }
johnb 5:b40a6fd3a334 333 else
johnb 5:b40a6fd3a334 334 {
johnb 5:b40a6fd3a334 335 ret_val = XBEEDEVICE_WRONG_MODE;
johnb 5:b40a6fd3a334 336 }
johnb 5:b40a6fd3a334 337 return ret_val;
johnb 5:b40a6fd3a334 338 }
johnb 5:b40a6fd3a334 339
johnb 5:b40a6fd3a334 340 XBeeDevice::XBeeDeviceReturn_t XBeeDevice::setUpApi( void )
johnb 5:b40a6fd3a334 341 {
johnb 5:b40a6fd3a334 342 XBeeDeviceReturn_t ret_val;
johnb 5:b40a6fd3a334 343
johnb 5:b40a6fd3a334 344 /* Wait for the guard period before transmitting command sequence */
johnb 5:b40a6fd3a334 345 wait_ms( XBEEAPI_CONFIG_GUARDPERIOD_MS );
johnb 5:b40a6fd3a334 346
johnb 5:b40a6fd3a334 347 m_inAtCmdMode = true;
johnb 5:b40a6fd3a334 348
johnb 5:b40a6fd3a334 349 /* Request to enter command mode */
johnb 5:b40a6fd3a334 350 /* TODO: Magic number */
johnb 5:b40a6fd3a334 351 ret_val = SendFrame("+++", 3, 3000);
johnb 5:b40a6fd3a334 352
johnb 5:b40a6fd3a334 353 /* Everything OK with last request? */
johnb 5:b40a6fd3a334 354 if( ret_val == XBEEDEVICE_OK )
johnb 5:b40a6fd3a334 355 {
johnb 5:b40a6fd3a334 356 wait_ms( XBEEAPI_CONFIG_GUARDPERIOD_MS );
johnb 5:b40a6fd3a334 357
johnb 5:b40a6fd3a334 358 /* API mode 2 please! */
johnb 5:b40a6fd3a334 359 ret_val = SendFrame(api_mode2_cmd,sizeof(api_mode2_cmd));
johnb 5:b40a6fd3a334 360 }
johnb 5:b40a6fd3a334 361
johnb 5:b40a6fd3a334 362 /* Everything OK with last request? */
johnb 5:b40a6fd3a334 363 if( ret_val == XBEEDEVICE_OK )
johnb 5:b40a6fd3a334 364 {
johnb 5:b40a6fd3a334 365 /* Exit command mode, back to API mode */
johnb 5:b40a6fd3a334 366 ret_val = SendFrame(exit_cmd_mode_cmd,sizeof(exit_cmd_mode_cmd));
johnb 5:b40a6fd3a334 367 }
johnb 5:b40a6fd3a334 368
johnb 5:b40a6fd3a334 369 m_inAtCmdMode = false;
johnb 5:b40a6fd3a334 370
johnb 5:b40a6fd3a334 371 return ret_val;
johnb 5:b40a6fd3a334 372 }
johnb 5:b40a6fd3a334 373
johnb 5:b40a6fd3a334 374 #if defined XBEEAPI_CONFIG_ENABLE_DEVELOPER
johnb 5:b40a6fd3a334 375
johnb 5:b40a6fd3a334 376 #define PRINTABLE_ASCII_FIRST 32U
johnb 5:b40a6fd3a334 377 #define PRINTABLE_ASCII_LAST 126U
johnb 5:b40a6fd3a334 378
johnb 5:b40a6fd3a334 379 void XBeeDevice::dumpRxBuffer( Stream* p_buf, const bool p_hexView )
johnb 5:b40a6fd3a334 380 {
johnb 5:b40a6fd3a334 381 uint8_t c;
johnb 5:b40a6fd3a334 382 while( m_rxBuff.getSize() ) {
johnb 5:b40a6fd3a334 383 if( m_rxBuff.read( &c, 1 ) ) {
johnb 5:b40a6fd3a334 384 if( p_hexView ) {
johnb 5:b40a6fd3a334 385 uint8_t a = '-';
johnb 5:b40a6fd3a334 386 if(( c>=PRINTABLE_ASCII_FIRST ) && (c<=PRINTABLE_ASCII_LAST)) {
johnb 5:b40a6fd3a334 387 a = c;
johnb 5:b40a6fd3a334 388 }
johnb 5:b40a6fd3a334 389 p_buf->printf("0x%02x (%c) ",c,a);
johnb 5:b40a6fd3a334 390 } else {
johnb 5:b40a6fd3a334 391 p_buf->printf("%c",c);
johnb 5:b40a6fd3a334 392 if( c == '\r' ) {
johnb 5:b40a6fd3a334 393 p_buf->printf("\n");
johnb 5:b40a6fd3a334 394 }
johnb 5:b40a6fd3a334 395 }
johnb 5:b40a6fd3a334 396 }
johnb 5:b40a6fd3a334 397 }
johnb 5:b40a6fd3a334 398 }
johnb 5:b40a6fd3a334 399
johnb 5:b40a6fd3a334 400 #endif