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:
Sat Jul 05 14:59:07 2014 +0000
Revision:
40:b96e8cad93d3
Parent:
33:eccf4725930c
Child:
41:07cb97b44e81
Fix comma/semi-colon typo in serial interface setup

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