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 15:33:04 2014 +0000
Revision:
41:07cb97b44e81
Parent:
40:b96e8cad93d3
Child:
42:81c789ba4c08
Change from Serial to RawSerial so that the library is RTOS friendly.

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 41:07cb97b44e81 54 m_if = new RawSerial( 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 41:07cb97b44e81 66 XBeeDevice::XBeeDevice( RawSerial* 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 16:8095c43a2a6e 266 #if defined XBEE_DEBUG_DEVICE_DUMP_MESSAGE_DECODE
johnb 16:8095c43a2a6e 267 m_if.printf("\r\n");
johnb 16:8095c43a2a6e 268 #endif
johnb 5:b40a6fd3a334 269
johnb 5:b40a6fd3a334 270 #if defined XBEEAPI_CONFIG_USING_RTOS
johnb 5:b40a6fd3a334 271 m_ifMutex.unlock();
johnb 5:b40a6fd3a334 272 #endif
johnb 5:b40a6fd3a334 273 }
johnb 5:b40a6fd3a334 274
johnb 5:b40a6fd3a334 275 uint8_t XBeeDevice::xbeeWrite( uint8_t p_byte, bool p_doEscape )
johnb 5:b40a6fd3a334 276 {
johnb 5:b40a6fd3a334 277 uint8_t c_sum = 0;
johnb 5:b40a6fd3a334 278
johnb 5:b40a6fd3a334 279 if (p_doEscape && m_escape &&
johnb 5:b40a6fd3a334 280 ((p_byte == XBEE_SB_FRAME_DELIMITER ) ||
johnb 5:b40a6fd3a334 281 (p_byte == XBEE_SB_ESCAPE ) ||
johnb 5:b40a6fd3a334 282 (p_byte == XBEE_SB_XON ) ||
johnb 5:b40a6fd3a334 283 (p_byte == XBEE_SB_XOFF)))
johnb 5:b40a6fd3a334 284 {
johnb 16:8095c43a2a6e 285 #if defined XBEE_DEBUG_DEVICE_DUMP_MESSAGE_DECODE
johnb 33:eccf4725930c 286 m_if->printf("%02x ",XBEE_SB_ESCAPE);
johnb 33:eccf4725930c 287 m_if->printf("%02x ",p_byte ^ 0x20);
johnb 16:8095c43a2a6e 288 #else
johnb 33:eccf4725930c 289 m_if->putc(XBEE_SB_ESCAPE);
johnb 33:eccf4725930c 290 m_if->putc(p_byte ^ 0x20);
johnb 16:8095c43a2a6e 291 #endif
johnb 5:b40a6fd3a334 292 c_sum += XBEE_SB_ESCAPE;
johnb 5:b40a6fd3a334 293 c_sum += p_byte ^ 0x20;
johnb 5:b40a6fd3a334 294 } else {
johnb 16:8095c43a2a6e 295 #if defined XBEE_DEBUG_DEVICE_DUMP_MESSAGE_DECODE
johnb 33:eccf4725930c 296 m_if->printf("%02x ",p_byte);
johnb 16:8095c43a2a6e 297 #else
johnb 33:eccf4725930c 298 m_if->putc(p_byte);
johnb 16:8095c43a2a6e 299 #endif
johnb 5:b40a6fd3a334 300 c_sum += p_byte;
johnb 5:b40a6fd3a334 301 }
johnb 5:b40a6fd3a334 302 return c_sum;
johnb 5:b40a6fd3a334 303 }
johnb 5:b40a6fd3a334 304
johnb 5:b40a6fd3a334 305 #define IS_OK( _b ) (( _b[ 0 ] == 'O' ) && ( _b[ 1 ] == 'K' ) && ( _b[ 2 ] == '\r' ))
johnb 5:b40a6fd3a334 306 #define OK_LEN (3U)
johnb 5:b40a6fd3a334 307
johnb 5:b40a6fd3a334 308 XBeeDevice::XBeeDeviceReturn_t XBeeDevice::SendFrame( const char* const p_dat, size_t p_len, int p_wait_ms )
johnb 5:b40a6fd3a334 309 {
johnb 5:b40a6fd3a334 310 XBeeDeviceReturn_t ret_val;
johnb 5:b40a6fd3a334 311
johnb 5:b40a6fd3a334 312 if( m_inAtCmdMode )
johnb 5:b40a6fd3a334 313 {
johnb 5:b40a6fd3a334 314 #if defined XBEEAPI_CONFIG_USING_RTOS
johnb 5:b40a6fd3a334 315 m_ifMutex.lock();
johnb 5:b40a6fd3a334 316 #endif
johnb 5:b40a6fd3a334 317 for( size_t i = 0;
johnb 5:b40a6fd3a334 318 i < p_len;
johnb 5:b40a6fd3a334 319 i++ ) {
johnb 33:eccf4725930c 320 m_if->putc(p_dat[i]);
johnb 5:b40a6fd3a334 321 }
johnb 5:b40a6fd3a334 322
johnb 5:b40a6fd3a334 323 wait_ms( p_wait_ms );
johnb 5:b40a6fd3a334 324
johnb 5:b40a6fd3a334 325 /* Check the response for the OK indicator */
johnb 5:b40a6fd3a334 326 if( m_rxBuff.getSize() == OK_LEN )
johnb 5:b40a6fd3a334 327 {
johnb 5:b40a6fd3a334 328 uint8_t ok_buff[OK_LEN];
johnb 5:b40a6fd3a334 329 m_rxBuff.read( ok_buff, OK_LEN );
johnb 5:b40a6fd3a334 330
johnb 5:b40a6fd3a334 331 if( IS_OK( ok_buff ))
johnb 5:b40a6fd3a334 332 {
johnb 5:b40a6fd3a334 333 ret_val = XBEEDEVICE_OK;
johnb 5:b40a6fd3a334 334 }
johnb 5:b40a6fd3a334 335 else
johnb 5:b40a6fd3a334 336 {
johnb 5:b40a6fd3a334 337 ret_val = XBEEDEVICE_UNEXPECTED_DATA;
johnb 5:b40a6fd3a334 338 }
johnb 5:b40a6fd3a334 339 }
johnb 5:b40a6fd3a334 340 else
johnb 5:b40a6fd3a334 341 {
johnb 5:b40a6fd3a334 342 ret_val = XBEEDEVICE_UNEXPECTED_LENGTH;
johnb 5:b40a6fd3a334 343 }
johnb 5:b40a6fd3a334 344 #if defined XBEEAPI_CONFIG_USING_RTOS
johnb 5:b40a6fd3a334 345 m_ifMutex.unlock();
johnb 5:b40a6fd3a334 346 #endif
johnb 5:b40a6fd3a334 347 }
johnb 5:b40a6fd3a334 348 else
johnb 5:b40a6fd3a334 349 {
johnb 5:b40a6fd3a334 350 ret_val = XBEEDEVICE_WRONG_MODE;
johnb 5:b40a6fd3a334 351 }
johnb 5:b40a6fd3a334 352 return ret_val;
johnb 5:b40a6fd3a334 353 }
johnb 5:b40a6fd3a334 354
johnb 5:b40a6fd3a334 355 XBeeDevice::XBeeDeviceReturn_t XBeeDevice::setUpApi( void )
johnb 5:b40a6fd3a334 356 {
johnb 5:b40a6fd3a334 357 XBeeDeviceReturn_t ret_val;
johnb 5:b40a6fd3a334 358
johnb 5:b40a6fd3a334 359 /* Wait for the guard period before transmitting command sequence */
johnb 5:b40a6fd3a334 360 wait_ms( XBEEAPI_CONFIG_GUARDPERIOD_MS );
johnb 5:b40a6fd3a334 361
johnb 5:b40a6fd3a334 362 m_inAtCmdMode = true;
johnb 5:b40a6fd3a334 363
johnb 5:b40a6fd3a334 364 /* Request to enter command mode */
johnb 5:b40a6fd3a334 365 /* TODO: Magic number */
johnb 5:b40a6fd3a334 366 ret_val = SendFrame("+++", 3, 3000);
johnb 5:b40a6fd3a334 367
johnb 5:b40a6fd3a334 368 /* Everything OK with last request? */
johnb 5:b40a6fd3a334 369 if( ret_val == XBEEDEVICE_OK )
johnb 5:b40a6fd3a334 370 {
johnb 5:b40a6fd3a334 371 wait_ms( XBEEAPI_CONFIG_GUARDPERIOD_MS );
johnb 5:b40a6fd3a334 372
johnb 5:b40a6fd3a334 373 /* API mode 2 please! */
johnb 5:b40a6fd3a334 374 ret_val = SendFrame(api_mode2_cmd,sizeof(api_mode2_cmd));
johnb 5:b40a6fd3a334 375 }
johnb 5:b40a6fd3a334 376
johnb 5:b40a6fd3a334 377 /* Everything OK with last request? */
johnb 5:b40a6fd3a334 378 if( ret_val == XBEEDEVICE_OK )
johnb 5:b40a6fd3a334 379 {
johnb 5:b40a6fd3a334 380 /* Exit command mode, back to API mode */
johnb 5:b40a6fd3a334 381 ret_val = SendFrame(exit_cmd_mode_cmd,sizeof(exit_cmd_mode_cmd));
johnb 5:b40a6fd3a334 382 }
johnb 5:b40a6fd3a334 383
johnb 5:b40a6fd3a334 384 m_inAtCmdMode = false;
johnb 5:b40a6fd3a334 385
johnb 5:b40a6fd3a334 386 return ret_val;
johnb 5:b40a6fd3a334 387 }
johnb 5:b40a6fd3a334 388
johnb 5:b40a6fd3a334 389 #if defined XBEEAPI_CONFIG_ENABLE_DEVELOPER
johnb 5:b40a6fd3a334 390
johnb 5:b40a6fd3a334 391 #define PRINTABLE_ASCII_FIRST 32U
johnb 5:b40a6fd3a334 392 #define PRINTABLE_ASCII_LAST 126U
johnb 5:b40a6fd3a334 393
johnb 5:b40a6fd3a334 394 void XBeeDevice::dumpRxBuffer( Stream* p_buf, const bool p_hexView )
johnb 5:b40a6fd3a334 395 {
johnb 5:b40a6fd3a334 396 uint8_t c;
johnb 5:b40a6fd3a334 397 while( m_rxBuff.getSize() ) {
johnb 5:b40a6fd3a334 398 if( m_rxBuff.read( &c, 1 ) ) {
johnb 5:b40a6fd3a334 399 if( p_hexView ) {
johnb 5:b40a6fd3a334 400 uint8_t a = '-';
johnb 5:b40a6fd3a334 401 if(( c>=PRINTABLE_ASCII_FIRST ) && (c<=PRINTABLE_ASCII_LAST)) {
johnb 5:b40a6fd3a334 402 a = c;
johnb 5:b40a6fd3a334 403 }
johnb 5:b40a6fd3a334 404 p_buf->printf("0x%02x (%c) ",c,a);
johnb 5:b40a6fd3a334 405 } else {
johnb 5:b40a6fd3a334 406 p_buf->printf("%c",c);
johnb 5:b40a6fd3a334 407 if( c == '\r' ) {
johnb 5:b40a6fd3a334 408 p_buf->printf("\n");
johnb 5:b40a6fd3a334 409 }
johnb 5:b40a6fd3a334 410 }
johnb 5:b40a6fd3a334 411 }
johnb 5:b40a6fd3a334 412 }
johnb 5:b40a6fd3a334 413 }
johnb 5:b40a6fd3a334 414
johnb 5:b40a6fd3a334 415 #endif