XBee-mbed library http://mbed.org/users/okini3939/notebook/xbee-mbed/

Dependents:   device_server_udp led_sender_post XBee_API_ex1 XBee_API_ex2 ... more

Revision:
4:f6d73acc1f75
Parent:
3:8573b122fa84
Child:
6:6f84e2840408
--- a/XBee.cpp	Thu Mar 08 17:41:29 2012 +0000
+++ b/XBee.cpp	Tue Mar 13 09:01:52 2012 +0000
@@ -67,11 +67,11 @@
     _checksum = checksum;
 }
 
-uint8_t XBeeResponse::getFrameDataLength() {
+uint16_t XBeeResponse::getFrameDataLength() {
     return _frameLength;
 }
 
-void XBeeResponse::setFrameLength(uint8_t frameLength) {
+void XBeeResponse::setFrameLength(uint16_t frameLength) {
     _frameLength = frameLength;
 }
 
@@ -158,7 +158,7 @@
     return 11;
 }
 
-uint8_t ZBRxResponse::getDataLength() {
+uint16_t ZBRxResponse::getDataLength() {
     return getPacketLength() - getDataOffset() - 1;
 }
 
@@ -461,7 +461,7 @@
     return (getOption() & 4) == 4;
 }
 
-uint8_t RxResponse::getDataLength() {
+uint16_t RxResponse::getDataLength() {
     return getPacketLength() - getDataOffset() - 1;
 }
 
@@ -519,7 +519,7 @@
     return getStatus() == AT_OK;
 }
 
-uint8_t RemoteAtCommandResponse::getValueLength() {
+uint16_t RemoteAtCommandResponse::getValueLength() {
     return getFrameDataLength() - 14;
 }
 
@@ -605,7 +605,7 @@
     return getFrameData()[3];
 }
 
-uint8_t AtCommandResponse::getValueLength() {
+uint16_t AtCommandResponse::getValueLength() {
     return getFrameDataLength() - 4;
 }
 
@@ -632,7 +632,7 @@
 }
 
 uint16_t XBeeResponse::getPacketLength() {
-    return ((_msbLength << 8) & 0xff) + (_lsbLength & 0xff);
+    return ((uint16_t)_msbLength << 8) + _lsbLength;
 }
 
 uint8_t* XBeeResponse::getFrameData() {
@@ -664,27 +664,60 @@
 
 void XBee::resetResponse() {
     _pos = 0;
+    _epos = 0;
     _escape = false;
+    _checksumTotal = 0;
     _response.reset();
 }
 
 XBee::XBee(PinName p_tx, PinName p_rx): _xbee(p_tx, p_rx) {
     _pos = 0;
+    _epos = 0;
     _escape = false;
     _checksumTotal = 0;
     _nextFrameId = 0;
-    _cts = NULL;
 
     _response.init();
     _response.setFrameData(_responseFrameData);
 }
 
-XBee::XBee(PinName p_tx, PinName p_rx, PinName p_cts): _xbee(p_tx, p_rx) {
+XBee::XBee(PinName p_tx, PinName p_rx, PinName p_cts, PinName p_rts): _xbee(p_tx, p_rx) {
     _pos = 0;
+    _epos = 0;
     _escape = false;
     _checksumTotal = 0;
     _nextFrameId = 0;
-    _cts = new DigitalIn(p_cts);
+#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
+    if (p_cts == p12) { // CTS (P0_17)
+        LPC_UART1->MCR |= (1<<7); // CTSEN
+        LPC_PINCON->PINSEL1 &= ~(3 << 2);
+        LPC_PINCON->PINSEL1 |= (1 << 2); // UART CTS
+    }
+    if (p_rts == P0_22) { // RTS (P0_22)
+        LPC_UART1->MCR |= (1<<6); // RTSEN
+        LPC_PINCON->PINSEL1 &= ~(3 << 12);
+        LPC_PINCON->PINSEL1 |= (1 << 12); // UART RTS
+        _xbee.attach(this, &XBee::isr_recv, Serial::RxIrq);
+        _rts = true;
+    } else {
+        _rts = false;
+    }
+#elif defined(TARGET_LPC11U24)
+    if (p_cts == p21) { // CTS (P0_7)
+        LPC_UART->MCR = (1<<7); // CTSEN
+        LPC_IOCON->PIO0_7 &= ~0x07;
+        LPC_IOCON->PIO0_7 |= 0x01; // UART CTS
+    }
+    if (p_rts == p22) { // RTS (P0_17)
+        LPC_UART->MCR = (1<<6); // RTSEN
+        LPC_IOCON->PIO0_17 &= ~0x07;
+        LPC_IOCON->PIO0_17 |= 0x01; // UART RTS
+        _xbee.attach(this, &XBee::isr_recv, Serial::RxIrq);
+        _rts = true;
+    } else {
+        _rts = false;
+    }
+#endif
 
     _response.init();
     _response.setFrameData(_responseFrameData);
@@ -760,11 +793,30 @@
          }
     }
 
+    DBG("(timeout %d %d)\r\n", _pos, _epos);
     // timed out
     t.stop();
     return false;
 }
 
+void XBee::isr_recv () {
+    _rxbuf[_rxaddr_w] = _xbee.getc();
+    _rxaddr_w = (_rxaddr_w + 1) % MAX_RXBUF_SIZE;
+}
+
+int XBee::getbuf () {
+    int r;
+    __disable_irq();
+    r = _rxbuf[_rxaddr_r];
+    _rxaddr_r = (_rxaddr_r + 1) % MAX_RXBUF_SIZE;
+    __enable_irq();
+    return r;
+}
+
+int XBee::bufreadable () {
+    return _rxaddr_w != _rxaddr_r;
+}
+
 void XBee::readPacket() {
     // reset previous response
     if (_response.isAvailable() || _response.isError()) {
@@ -772,20 +824,33 @@
         resetResponse();
     }
 
-    while (_xbee.readable()) {
+//    while (_xbee.readable()) {
+    while ((! _rts && _xbee.readable()) || (_rts && bufreadable())) {
 
-        b = _xbee.getc();
+//        b = _xbee.getc();
+        if (_rts) {
+            b = getbuf();
+        } else {
+            b = _xbee.getc();
+        }
 
         if (_pos > 0 && b == START_BYTE && ATAP == 2) {
             // new packet start before previous packeted completed -- discard previous packet and start over
+            DBG("error: %02x %d %d\r\n", b, _pos, _epos);
             _response.setErrorCode(UNEXPECTED_START_BYTE);
             return;
         }
 
         if (_pos > 0 && b == ESCAPE) {
             if (_xbee.readable()) {
-                b = _xbee.getc();
+//                b = _xbee.getc();
+                if (_rts) {
+                    b = getbuf();
+                } else {
+                    b = _xbee.getc();
+                }
                 b = 0x20 ^ b;
+                _epos ++;
             } else {
                 // escape byte.  next byte will be
                 _escape = true;
@@ -797,6 +862,7 @@
         if (_escape == true) {
             b = 0x20 ^ b;
             _escape = false;
+            _epos ++;
         }
 
         // checksum includes all bytes starting with api id
@@ -840,10 +906,10 @@
                 // check if we're at the end of the packet
                 // packet length does not include start, length, or checksum bytes, so add 3
                 if (_pos == (_response.getPacketLength() + 3)) {
+//                if (_pos + _epos == (_response.getPacketLength() + 3)) {
                     // verify checksum
 
                     //std::cout << "read checksum " << static_cast<unsigned int>(b) << " at pos " << static_cast<unsigned int>(_pos) << std::endl;
-
                     if ((_checksumTotal & 0xff) == 0xff) {
                         _response.setChecksum(b);
                         _response.setAvailable(true);
@@ -851,6 +917,7 @@
                         _response.setErrorCode(NO_ERROR);
                     } else {
                         // checksum failed
+                        DBG("error: checksum %02x %02x %d %d\r\n", b, _checksumTotal, _pos, _epos);
                         _response.setErrorCode(CHECKSUM_FAILURE);
                     }
 
@@ -860,6 +927,7 @@
 
                     // reset state vars
                     _pos = 0;
+                    _epos = 0;
 
                     _checksumTotal = 0;
 
@@ -909,7 +977,7 @@
 //}
 
 
-PayloadRequest::PayloadRequest(uint8_t apiId, uint8_t frameId, uint8_t *payload, uint8_t payloadLength) : XBeeRequest(apiId, frameId) {
+PayloadRequest::PayloadRequest(uint8_t apiId, uint8_t frameId, uint8_t *payload, uint16_t payloadLength) : XBeeRequest(apiId, frameId) {
     _payloadPtr = payload;
     _payloadLength = payloadLength;
 }
@@ -922,11 +990,11 @@
     _payloadPtr = payload;
 }
 
-uint8_t PayloadRequest::getPayloadLength() {
+uint16_t PayloadRequest::getPayloadLength() {
     return _payloadLength;
 }
 
-void PayloadRequest::setPayloadLength(uint8_t payloadLength) {
+void PayloadRequest::setPayloadLength(uint16_t payloadLength) {
     _payloadLength = payloadLength;
 }
 
@@ -967,21 +1035,21 @@
 
 }
 
-ZBTxRequest::ZBTxRequest(XBeeAddress64 &addr64, uint16_t addr16, uint8_t broadcastRadius, uint8_t option, uint8_t *data, uint8_t dataLength, uint8_t frameId): PayloadRequest(ZB_TX_REQUEST, frameId, data, dataLength) {
+ZBTxRequest::ZBTxRequest(XBeeAddress64 &addr64, uint16_t addr16, uint8_t broadcastRadius, uint8_t option, uint8_t *data, uint16_t dataLength, uint8_t frameId): PayloadRequest(ZB_TX_REQUEST, frameId, data, dataLength) {
     _addr64 = addr64;
     _addr16 = addr16;
     _broadcastRadius = broadcastRadius;
     _option = option;
 }
 
-ZBTxRequest::ZBTxRequest(XBeeAddress64 &addr64, uint8_t *data, uint8_t dataLength): PayloadRequest(ZB_TX_REQUEST, DEFAULT_FRAME_ID, data, dataLength) {
+ZBTxRequest::ZBTxRequest(XBeeAddress64 &addr64, uint8_t *data, uint16_t dataLength): PayloadRequest(ZB_TX_REQUEST, DEFAULT_FRAME_ID, data, dataLength) {
     _addr64 = addr64;
     _addr16 = ZB_BROADCAST_ADDRESS;
     _broadcastRadius = ZB_BROADCAST_RADIUS_MAX_HOPS;
     _option = ZB_TX_UNICAST;
 }
 
-uint8_t ZBTxRequest::getFrameData(uint8_t pos) {
+uint8_t ZBTxRequest::getFrameData(uint16_t pos) {
     if (pos == 0) {
         return (_addr64.getMsb() >> 24) & 0xff;
     } else if (pos == 1) {
@@ -1011,7 +1079,7 @@
     }
 }
 
-uint8_t ZBTxRequest::getFrameDataLength() {
+uint16_t ZBTxRequest::getFrameDataLength() {
     return ZB_TX_API_LENGTH + getPayloadLength();
 }
 
@@ -1055,17 +1123,17 @@
 
 }
 
-Tx16Request::Tx16Request(uint16_t addr16, uint8_t option, uint8_t *data, uint8_t dataLength, uint8_t frameId) : PayloadRequest(TX_16_REQUEST, frameId, data, dataLength) {
+Tx16Request::Tx16Request(uint16_t addr16, uint8_t option, uint8_t *data, uint16_t dataLength, uint8_t frameId) : PayloadRequest(TX_16_REQUEST, frameId, data, dataLength) {
     _addr16 = addr16;
     _option = option;
 }
 
-Tx16Request::Tx16Request(uint16_t addr16, uint8_t *data, uint8_t dataLength) : PayloadRequest(TX_16_REQUEST, DEFAULT_FRAME_ID, data, dataLength) {
+Tx16Request::Tx16Request(uint16_t addr16, uint8_t *data, uint16_t dataLength) : PayloadRequest(TX_16_REQUEST, DEFAULT_FRAME_ID, data, dataLength) {
     _addr16 = addr16;
     _option = ACK_OPTION;
 }
 
-uint8_t Tx16Request::getFrameData(uint8_t pos) {
+uint8_t Tx16Request::getFrameData(uint16_t pos) {
 
     if (pos == 0) {
         return (_addr16 >> 8) & 0xff;
@@ -1078,7 +1146,7 @@
     }
 }
 
-uint8_t Tx16Request::getFrameDataLength() {
+uint16_t Tx16Request::getFrameDataLength() {
     return TX_16_API_LENGTH + getPayloadLength();
 }
 
@@ -1102,17 +1170,17 @@
 
 }
 
-Tx64Request::Tx64Request(XBeeAddress64 &addr64, uint8_t option, uint8_t *data, uint8_t dataLength, uint8_t frameId) : PayloadRequest(TX_64_REQUEST, frameId, data, dataLength) {
+Tx64Request::Tx64Request(XBeeAddress64 &addr64, uint8_t option, uint8_t *data, uint16_t dataLength, uint8_t frameId) : PayloadRequest(TX_64_REQUEST, frameId, data, dataLength) {
     _addr64 = addr64;
     _option = option;
 }
 
-Tx64Request::Tx64Request(XBeeAddress64 &addr64, uint8_t *data, uint8_t dataLength) : PayloadRequest(TX_64_REQUEST, DEFAULT_FRAME_ID, data, dataLength) {
+Tx64Request::Tx64Request(XBeeAddress64 &addr64, uint8_t *data, uint16_t dataLength) : PayloadRequest(TX_64_REQUEST, DEFAULT_FRAME_ID, data, dataLength) {
     _addr64 = addr64;
     _option = ACK_OPTION;
 }
 
-uint8_t Tx64Request::getFrameData(uint8_t pos) {
+uint8_t Tx64Request::getFrameData(uint16_t pos) {
 
     if (pos == 0) {
         return (_addr64.getMsb() >> 24) & 0xff;
@@ -1137,7 +1205,7 @@
     }
 }
 
-uint8_t Tx64Request::getFrameDataLength() {
+uint16_t Tx64Request::getFrameDataLength() {
     return TX_64_API_LENGTH + getPayloadLength();
 }
 
@@ -1199,7 +1267,7 @@
     _commandValueLength = length;
 }
 
-uint8_t AtCommandRequest::getFrameData(uint8_t pos) {
+uint8_t AtCommandRequest::getFrameData(uint16_t pos) {
 
     if (pos == 0) {
         return _command[0];
@@ -1219,7 +1287,7 @@
 //     XBeeRequest::reset();
 //}
 
-uint8_t AtCommandRequest::getFrameDataLength() {
+uint16_t AtCommandRequest::getFrameDataLength() {
     // command is 2 byte + length of value
     return AT_COMMAND_API_LENGTH + _commandValueLength;
 }
@@ -1286,7 +1354,7 @@
 }
 
 
-uint8_t RemoteAtCommandRequest::getFrameData(uint8_t pos) {
+uint8_t RemoteAtCommandRequest::getFrameData(uint16_t pos) {
     if (pos == 0) {
         return (_remoteAddress64.getMsb() >> 24) & 0xff;
     } else if (pos == 1) {
@@ -1318,7 +1386,7 @@
     }
 }
 
-uint8_t RemoteAtCommandRequest::getFrameDataLength() {
+uint16_t RemoteAtCommandRequest::getFrameDataLength() {
     return REMOTE_AT_COMMAND_API_LENGTH + getCommandValueLength();
 }
 
@@ -1376,12 +1444,9 @@
 
     if (escape && (b == START_BYTE || b == ESCAPE || b == XON || b == XOFF)) {
 //        std::cout << "escaping byte [" << toHexString(b) << "] " << std::endl;
-        if (_cts) while (_cts->read() != 0);
         _xbee.putc(ESCAPE);
-        if (_cts) while (_cts->read() != 0);
         _xbee.putc(b ^ 0x20);
     } else {
-        if (_cts) while (_cts->read() != 0);
         _xbee.putc(b);
     }
     DBG("%02x ", b);