This is an experimental driver for the XBee 900 HP pro module's SPI connection. This driver is unfinished and stability is not guaranteed. Use with caution.
Dependents: Sentinel_BASE Sentinel_NODE
Diff: xbee900hp.cpp
- Revision:
- 7:3cb67634fa4e
- Parent:
- 6:3873db4a0164
- Child:
- 8:fa84dacc45b9
diff -r 3873db4a0164 -r 3cb67634fa4e xbee900hp.cpp --- a/xbee900hp.cpp Thu Apr 30 17:01:46 2015 +0000 +++ b/xbee900hp.cpp Thu Apr 07 18:09:59 2016 +0000 @@ -3,15 +3,20 @@ /** * Initialize the xBee Module */ -xbee900hp::xbee900hp(PinName pin_mosi,PinName pin_miso,PinName pin_sck,PinName pin_attn, PinName pin_rst) - : _pin_rst(pin_rst), _pin_attn(pin_attn), _xbeespi(pin_mosi,pin_miso,pin_sck) -{ +xbee900hp::xbee900hp(PinName pin_mosi,PinName pin_miso,PinName pin_sck,PinName pin_attn, PinName pin_rst, unsigned int freq) + : _pin_rst(pin_rst), _pin_attn(pin_attn), _xbeespi(pin_mosi,pin_miso,pin_sck) { + // Set proper spi transfer mode format. _xbeespi.format(8,0); - _xbeespi.frequency(1000000); - + // Set SPI frequency + _xbeespi.frequency(freq); + + // Reset for good measure. reset(); + + // Xbee is up and running! } + /** * Destructor */ @@ -24,33 +29,53 @@ { _pin_rst = 0; // Minimum pulse is 1ms - wait_ms(1); + wait_ms(2); _pin_rst = 1; - // wait for module to come back online - wait_ms(500); + + // Wait for device to have time to start the reboot process. + wait_ms(80); + + // Now wait for the startup message. + while (attn() == 1) {} + + // This is the message the XBEE should send out on startup after a reset. + unsigned int modemMsg[6] = { 0x7E,0x00,0x02,0x8A,0x00,0x75 }; + // Container for or new message. + unsigned int delim[6]; + + // Read in the new message from the xbee. + for (int i = 0; i < 6; i++) { + delim[i] = _xbeespi.write(0x00); + } + + // Compare recieved msg with msg we want. + if (memcmp(delim, modemMsg, sizeof(modemMsg))) { + // If msg mismatch. + error("XBEE FAILURE"); + } } + /** * Send packet out on RF */ -void xbee900hp::sendPacket(char* data, unsigned int length) -{ +int xbee900hp::sendPacket(char* data, unsigned int length, bool enMesh) { // checksum unsigned int checksum; unsigned int checksumsub = 0; - + // start char _xbeespi.write(0x7E); // lenght _xbeespi.write(0x00); - + unsigned int totallength = 14 + length - 1; _xbeespi.write(totallength); // frame delimter _xbeespi.write(0x10); checksumsub += 0x10; - // id for later reference 0 = no id + // id for later reference _xbeespi.write(0x00); // destination address @@ -74,16 +99,30 @@ //bcast radius _xbeespi.write(0x00); - //transmit options 0xC0 to enable digimesh - _xbeespi.write(0xC0); - checksumsub += 0xC0; + // This is a bitmasked field + // bit 0: Disable ACK + // bit 1: Disable Route Discovery + // bit 2: Enable Unicast NACK messages. + // bit 3: Enable Unicast Trace Route messages. + // bits 6,7: b’01 - Point-Multipoint + // b’10 - Repeater mode (directed broadcast) + // b’11 - DigiMesh + // All other bits must be set to 0. + if (enMesh == true) { + // Transmit using digimesh + _xbeespi.write(0xC0); + checksumsub += 0xC0; + } else { + // Transmit point to point (without ACK) + _xbeespi.write(0x41); + checksumsub += 0x41; + } // dat data for (int i = 0; i < (length - 1); i++) { _xbeespi.write(*data); checksumsub += (*(data++)); } - // Calculate checksum checksumsub = checksumsub & 0xFF; @@ -91,52 +130,74 @@ // finally write checksum _xbeespi.write(checksum); + + return 0; } -int xbee900hp::readPacket(char* data) { - unsigned int temp1; + +/** +* Wait for and read incoming data packet +*/ +unsigned long long xbee900hp::readPacket(char* data) { + unsigned long long temp1; unsigned int temp2; + unsigned long long srcAddr = 0; + unsigned int checksumsub = 0; unsigned int checksum; - + // get first vars. temp1 = _xbeespi.write(0x00); if (temp1 != 0x7E) { - // drop packet - return 1; + return 0; } // Get length of message temp1 = _xbeespi.write(0x00); temp2 = _xbeespi.write(0x00); - + // Get total length unsigned int length = (temp1<<8) | temp2; - + // Next read frame type to ensure it is an RX packet. temp1 = _xbeespi.write(0x00); if (temp1 != 0x90) { - // drop packet - return 1; + return 0; } checksumsub += temp1; - + // in our case we dont care about source address this should be modified to extract source address if needed. - checksumsub += _xbeespi.write(0x00); - checksumsub += _xbeespi.write(0x00); - checksumsub += _xbeespi.write(0x00); - checksumsub += _xbeespi.write(0x00); - checksumsub += _xbeespi.write(0x00); - checksumsub += _xbeespi.write(0x00); - checksumsub += _xbeespi.write(0x00); - checksumsub += _xbeespi.write(0x00); + temp1 = _xbeespi.write(0x00); + srcAddr = (temp1 << 56); + checksumsub += temp1; + temp1 = _xbeespi.write(0x00); + srcAddr ^= (temp1 << 48); + checksumsub += temp1; + temp1 = _xbeespi.write(0x00); + srcAddr ^= (temp1 << 40); + checksumsub += temp1; + temp1 = _xbeespi.write(0x00); + srcAddr ^= (temp1 << 32); + checksumsub += temp1; + temp1 = _xbeespi.write(0x00); + srcAddr ^= (temp1 << 24); + checksumsub += temp1; + temp1 = _xbeespi.write(0x00); + srcAddr ^= (temp1 << 16); + checksumsub += temp1; + temp1 = _xbeespi.write(0x00); + srcAddr ^= (temp1 << 8); + checksumsub += temp1; + temp1 = _xbeespi.write(0x00); + srcAddr ^= (temp1); + checksumsub += temp1; // reserved field, we dont care about except for checksum checksumsub += _xbeespi.write(0x00); checksumsub += _xbeespi.write(0x00); - + // recive options we also dont care though checksumsub += _xbeespi.write(0x00); - + // Now for the sweet sweet data. for (int i = 0; i<(length-12); i++) { *data = _xbeespi.write(0x00); @@ -144,143 +205,228 @@ } // Null terminate char array. *data = '\0'; - + // Get that salty checksum temp1 = _xbeespi.write(0x00); - + checksumsub = checksumsub & 0xFF; checksum = 0xFF - checksumsub; - + // Check the checksum if (temp1 != checksum) { // Checksum failure, flag to discard packet - return 1; + return 0; } - - return 0; + + return srcAddr; } + +/** +* Check ATTN signal +*/ int xbee900hp::attn() { return _pin_attn; } -void xbee900hp::writeSetting(char command[2], unsigned int value) { +/** +* Get signal strength of last recieved packet +*/ +unsigned int xbee900hp::getRSSI() { // checksum Variables unsigned int checksum = 0; unsigned int checksumsub = 0; - - // Start config, send frames for SPI pins enable + + // RSSI storage container + unsigned int rssi; + + // Frame initiator _xbeespi.write(0x7E); + // Length _xbeespi.write(0x00); - _xbeespi.write(0x05); - + _xbeespi.write(0x04); + // Frame type (config) _xbeespi.write(0x08); checksumsub += 0x08; - _xbeespi.write(0x00); - - + // Response frame ID + _xbeespi.write(0x44); + checksumsub += 0x44; + // AT Command - for (int i = 0; i < 2; i++) { - _xbeespi.write(*command); - checksumsub += (*(command++)); - } - - // Value to set - _xbeespi.write(value); - checksumsub += value; - + _xbeespi.write(0x44); // Hex for ASCII D + checksumsub += 0x44; + _xbeespi.write(0x42); // Hex for ASCII B + checksumsub += 0x42; + // Calculate checksum checksumsub = checksumsub & 0xFF; checksum = 0xFF - checksumsub; // finally write checksum _xbeespi.write(checksum); -} -int xbee900hp::getSerial(char* serialnumber) { - ///////////////////////////////////////////////////Send portion - // checksum Variables - unsigned int checksum = 0; - unsigned int checksumsub = 0; - - // Write frame to return serial high and low.s - - // Start config, send frames for SPI pins enable - _xbeespi.write(0x7E); - _xbeespi.write(0x00); - _xbeespi.write(0x04); - - // Frame type (config) - _xbeespi.write(0x08); - checksumsub += 0x08; - _xbeespi.write(0x52); - checksumsub += 0x52; - - // Setting wanted - _xbeespi.write('S'); - checksumsub += 'S'; - _xbeespi.write('H'); - checksumsub += 'H'; - - // Calculate checksum - checksumsub = checksumsub & 0xFF; - checksum = 0xFF - checksumsub; - // finally write checksum - _xbeespi.write(checksum); - - //////////////////////////////////////RECIEVE PORTION // Block until xbee replys - while (_pin_attn != 0) {} - - // Containers for read values - char temp1 = 0; - char temp2 = 0; - + while (_pin_attn != 0) { } + // reset checksum to zero. checksum = 0; checksumsub = 0; - + + unsigned int temp1; + unsigned int temp2; + // get start byte temp1 = _xbeespi.write(0x00); if (temp1 != 0x7E) { // drop packet return 1; } - // Get length of message - temp1 = _xbeespi.write(0x00); - temp2 = _xbeespi.write(0x00); - - // Get total length - unsigned int length = (temp1<<8) | temp2; - + // Get length of message (we dont care, we know what it is) + _xbeespi.write(0x00); + _xbeespi.write(0x00); + // Next read frame type to ensure it is an response packet. temp1 = _xbeespi.write(0x00); if (temp1 != 0x88) { // drop packet - return 1; + return 0; } checksumsub += temp1; - + // get response frame id - temp1 = _xbeespi.write(0x00); - if (temp1 != 0x52) { - // drop packet - return 1; + + while (temp1 != 0x44) { + // Dredge through data until the response frame we want arrives. + temp1 = _xbeespi.write(0x00); } checksumsub += temp1; - + // get at response parameter temp1 = _xbeespi.write(0x00); checksumsub += temp1; temp2 = _xbeespi.write(0x00); checksumsub += temp2; - - if ((temp1 != 'S') || (temp2 != 'H')) { + + if ((temp1 != 0x44) || (temp2 != 0x42)) { + return 1; + // drop + } + + // Check OK flag + temp1 = _xbeespi.write(0x00); + if (temp1 != 0x00) { return 1; // drop } - + checksumsub += temp1; + + // Get RSSI Data + rssi = _xbeespi.write(0x00); + checksumsub += rssi; + + // Get that salty checksum + temp1 = _xbeespi.write(0x00); + + checksumsub = checksumsub & 0xFF; + checksum = 0xFF - checksumsub; + + // Check the checksum + if (temp1 != checksum) { + // Checksum failure, flag to discard packet + return 1; + } + + return rssi; +} + +/** +* Set the transmission power level. +*/ +int xbee900hp::setPower(int value) { + if ((value > 4) || (value < 0)) { + return 1; + } + + // checksum Variables + unsigned int checksum = 0; + unsigned int checksumsub = 0; + + // Frame initiator + _xbeespi.write(0x7E); + // Length + _xbeespi.write(0x00); + _xbeespi.write(0x05); + + // Frame type (config) + _xbeespi.write(0x08); + checksumsub += 0x08; + // Response frame ID + _xbeespi.write(0x50); + checksumsub += 0x50; + + // AT Command + _xbeespi.write(0x50); // Hex for ASCII P + checksumsub += 0x50; + _xbeespi.write(0x4C); // Hex for ASCII L + checksumsub += 0x4C; + + // Value to set + _xbeespi.write(value); + checksumsub += value; + + // Calculate checksum + checksumsub = checksumsub & 0xFF; + checksum = 0xFF - checksumsub; + + // finally write checksum + _xbeespi.write(checksum); + + // Block until xbee replys + while (_pin_attn != 0) { } + + // reset checksum to zero. + checksum = 0; + checksumsub = 0; + + unsigned int temp1; + unsigned int temp2; + + // get start byte + temp1 = _xbeespi.write(0x00); + if (temp1 != 0x7E) { + // drop packet + return 1; + } + // Get length of message (we dont care, we know what it is) + _xbeespi.write(0x00); + _xbeespi.write(0x00); + + // Next read frame type to ensure it is an response packet. + temp1 = _xbeespi.write(0x00); + if (temp1 != 0x88) { + // drop packet + return 0; + } + checksumsub += temp1; + + while (temp1 != 0x50) { + // Keep going through data until response frame is found. + temp1 = _xbeespi.write(0x00); + } + checksumsub += temp1; + + // get at response parameter + temp1 = _xbeespi.write(0x00); + checksumsub += temp1; + temp2 = _xbeespi.write(0x00); + checksumsub += temp2; + + if ((temp1 != 0x50) || (temp2 != 0x4C)) { + return 1; + // drop + } + // Check OK flag temp1 = _xbeespi.write(0x00); if (temp1 != 0x00) { @@ -288,143 +434,282 @@ // drop } checksumsub += temp1; - - // Now for the sweet sweet data. - for (int i = 0; i<(length-5); i++) { - *serialnumber = _xbeespi.write(0x00); - checksumsub += *(serialnumber++); - } - + // Get that salty checksum temp1 = _xbeespi.write(0x00); - + checksumsub = checksumsub & 0xFF; checksum = 0xFF - checksumsub; - + // Check the checksum if (temp1 != checksum) { // Checksum failure, flag to discard packet return 1; } - -//////////////////////////////////////////////////////////////////////// - ///////////////////////////////////////////////////Send portion + + return 0; +} + +/** +* Get serial number of xbee module +*/ +unsigned long long xbee900hp::getSerial() { // checksum Variables - checksum = 0; - checksumsub = 0; - - // Write frame to return serial high and low.s - - // Start config, send frames for SPI pins enable + unsigned int checksum = 0; + unsigned int checksumsub = 0; + + // Container for serial as we calculate it. + unsigned long long serialNumber = 0; + + // Containers for read values + unsigned long long temp1 = 0; + unsigned long long temp2 = 0; + unsigned long long temp3 = 0; + unsigned long long temp4 = 0; + + // Write frame to return serial high. + // Total frame looks like this: + // 7E 00 04 08 52 53(S) 48(H) CHECKSUM + // Wait for response to get high part of serial + // Profit???? + + // Frame Header _xbeespi.write(0x7E); + // Frame Length _xbeespi.write(0x00); _xbeespi.write(0x04); - + // Frame type (config) _xbeespi.write(0x08); checksumsub += 0x08; _xbeespi.write(0x52); checksumsub += 0x52; - - // Setting wanted - _xbeespi.write('S'); - checksumsub += 'S'; - _xbeespi.write('L'); - checksumsub += 'L'; - + + // Setting wanted SerialHigh + _xbeespi.write(0x53); + checksumsub += 0x53; + _xbeespi.write(0x48); + checksumsub += 0x48; + // Calculate checksum checksumsub = checksumsub & 0xFF; checksum = 0xFF - checksumsub; // finally write checksum _xbeespi.write(checksum); - - //////////////////////////////////////RECIEVE PORTION + + // RECIEVE PORTION // Block until xbee replys - while (_pin_attn != 0) {} - - // Containers for read values - temp1 = 0; - temp2 = 0; - + while (_pin_attn != 0) { } + // reset checksum to zero. checksum = 0; checksumsub = 0; - + // get start byte temp1 = _xbeespi.write(0x00); if (temp1 != 0x7E) { // drop packet - return 1; + return 0; } - // Get length of message - temp1 = _xbeespi.write(0x00); - temp2 = _xbeespi.write(0x00); - - // Get total length - length = (temp1<<8) | temp2; - + // Get length of message (we don't care we know how long) + _xbeespi.write(0x00); + _xbeespi.write(0x00); + // Next read frame type to ensure it is an response packet. temp1 = _xbeespi.write(0x00); if (temp1 != 0x88) { // drop packet - return 1; + return 0; } checksumsub += temp1; - + // get response frame id temp1 = _xbeespi.write(0x00); if (temp1 != 0x52) { // drop packet - return 1; + return 0; } checksumsub += temp1; - + // get at response parameter temp1 = _xbeespi.write(0x00); checksumsub += temp1; temp2 = _xbeespi.write(0x00); checksumsub += temp2; - - if ((temp1 != 'S') || (temp2 != 'L')) { - return 1; + + if ((temp1 != 0x53) || (temp2 != 0x48)) { + return 0; // drop } - + // Check OK flag temp1 = _xbeespi.write(0x00); if (temp1 != 0x00) { - return 1; + return 0; // drop } checksumsub += temp1; - - // Now for the sweet sweet data. - for (int i = 0; i<(length-5); i++) { - *serialnumber = _xbeespi.write(0x00); - checksumsub += *(serialnumber++); - } - // Null terminate char array. - *serialnumber = '\0'; - + + // Now for the high portion of the serial + temp1 = _xbeespi.write(0x00); + checksumsub += temp1; + temp2 = _xbeespi.write(0x00); + checksumsub += temp2; + temp3 = _xbeespi.write(0x00); + checksumsub += temp3; + temp4 = _xbeespi.write(0x00); + checksumsub += temp4; + + // Store new items in serial number + serialNumber += (temp1 << 56) ^ (temp2 << 48) ^ (temp3 << 40) ^ (temp4 << 32); + // Get that salty checksum temp1 = _xbeespi.write(0x00); - + checksumsub = checksumsub & 0xFF; checksum = 0xFF - checksumsub; - + // Check the checksum if (temp1 != checksum) { // Checksum failure, flag to discard packet - return 1; + return 0; + } + + ///////////////////////////////////////////////////Send portion + // checksum Variables + checksum = 0; + checksumsub = 0; + + // Containers for read values + temp1 = 0; + temp2 = 0; + temp3 = 0; + temp4 = 0; + + // Write frame to return serial low. + // Total frame looks like this: + // 7E 00 04 08 52 53(S) 4C(L) CHECKSUM + // Wait for response to get lower part of serial + // Profit???? + + // Frame Header + _xbeespi.write(0x7E); + // Frame Length + _xbeespi.write(0x00); + _xbeespi.write(0x04); + + // Frame type (config) + _xbeespi.write(0x08); + checksumsub += 0x08; + _xbeespi.write(0x52); + checksumsub += 0x52; + + // Setting wanted SerialLow + _xbeespi.write(0x53); + checksumsub += 0x53; + _xbeespi.write(0x4C); + checksumsub += 0x4C; + + // Calculate checksum + checksumsub = checksumsub & 0xFF; + checksum = 0xFF - checksumsub; + // finally write checksum + _xbeespi.write(checksum); + + // RECIEVE PORTION + // Block until xbee replys + while (_pin_attn != 0) { } + + // reset checksum to zero. + checksum = 0; + checksumsub = 0; + + // get start byte + temp1 = _xbeespi.write(0x00); + if (temp1 != 0x7E) { + // drop packet + return 0; } - - return 0; + // Get length of message (dont care again) + _xbeespi.write(0x00); + _xbeespi.write(0x00); + + // Next read frame type to ensure it is an response packet. + temp1 = _xbeespi.write(0x00); + if (temp1 != 0x88) { + // drop packet + return 0; + } + checksumsub += temp1; + + // get response frame id + temp1 = _xbeespi.write(0x00); + if (temp1 != 0x52) { + // drop packet + return 0; + } + checksumsub += temp1; + + // get at response parameter + temp1 = _xbeespi.write(0x00); + checksumsub += temp1; + temp2 = _xbeespi.write(0x00); + checksumsub += temp2; + + if ((temp1 != 0x53) || (temp2 != 0x4C)) { + return 0; + // drop + } + // Check OK flag + temp1 = _xbeespi.write(0x00); + if (temp1 != 0x00) { + return 0; + // drop + } + checksumsub += temp1; + + // Now for the high portion of the serial + temp1 = _xbeespi.write(0x00); + checksumsub += temp1; + temp2 = _xbeespi.write(0x00); + checksumsub += temp2; + temp3 = _xbeespi.write(0x00); + checksumsub += temp3; + temp4 = _xbeespi.write(0x00); + checksumsub += temp4; + + serialNumber += (temp1 << 24) ^ (temp2 << 16) ^ (temp3 << 8) ^ (temp4); + + // Get that salty checksum + temp1 = _xbeespi.write(0x00); + + checksumsub = checksumsub & 0xFF; + checksum = 0xFF - checksumsub; + + // Check the checksum + if (temp1 != checksum) { + // Checksum failure, flag to discard packet + return 0; + } + + return serialNumber; } -void xbee900hp::clearBuff() -{ + +/** +* Clear output buffer +*/ +void xbee900hp::clearBuff() { while(_pin_attn == 0) { _xbeespi.write(0x00); } -} \ No newline at end of file +} + + +/** +* Read raw data in from module +*/ +char xbee900hp::debug() { + return _xbeespi.write(0x00); +}