Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: CircularBuffer FixedLengthList
Dependents: XBeeApiTest XBeeApiSimpleATCmdsExample XBeeApiBroadcastExample XBeeApiBroadcastExampleRTOS ... more
Base/XBeeDevice.cpp@33:eccf4725930c, 2014-03-25 (annotated)
- Committer:
- johnb
- Date:
- Tue Mar 25 18:38:42 2014 +0000
- Revision:
- 33:eccf4725930c
- Parent:
- 29:c6d037cceb02
- Child:
- 40:b96e8cad93d3
New constructor to allow Serial object to be passed rather than instantiated by the XBeeDevice
Who changed what in which revision?
User | Revision | Line number | New 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 | 33:eccf4725930c | 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 |