John Bailey / XBeeApi

Dependencies:   CircularBuffer FixedLengthList

Dependents:   XBeeApiTest XBeeApiSimpleATCmdsExample XBeeApiBroadcastExample XBeeApiBroadcastExampleRTOS ... more

Committer:
johnb
Date:
Sun Jul 06 20:06:06 2014 +0000
Revision:
42:81c789ba4c08
Parent:
41:07cb97b44e81
Child:
43:975a28e01dac
Changes to support working with mbed-rtos; Use a dispatcher thread to deal with data received from the serial port rather than doing it in the interrupt.  Not only is this poor practice, it seems that when using mbed-rtos there's less interrupt stack

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