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