diff options
-rw-r--r-- | xbee/packxbee.c | 278 | ||||
-rw-r--r-- | xbee/pdxbee.h | 6 | ||||
-rw-r--r-- | xbee/unpackxbee.c | 117 |
3 files changed, 369 insertions, 32 deletions
diff --git a/xbee/packxbee.c b/xbee/packxbee.c index 23c0343..cd83179 100644 --- a/xbee/packxbee.c +++ b/xbee/packxbee.c @@ -3,6 +3,7 @@ /* Started by Martin Peach 20110731 */ /* Information taken from "XBeeŽ/XBee-PROŽ ZB RF Modules" (document 90000976_G, 11/15/2010)*/ /* by Digi International Inc. http://www.digi.com */ +/* Series 1 info from "XBeeŽ/XBee-PROŽ RF Modules" (document 90000982_L 4/30/2013) */ #include <stdio.h> #include <string.h> @@ -29,6 +30,8 @@ static void packxbee_AT(t_packxbee *x, t_symbol *s, int argc, t_atom *argv); static void packxbee_RAT(t_packxbee *x, t_symbol *s, int argc, t_atom *argv); static void packxbee_ATQ(t_packxbee *x, t_symbol *s, int argc, t_atom *argv); static void packxbee_TX(t_packxbee *x, t_symbol *s, int argc, t_atom *argv); +static void packxbee_TX64(t_packxbee *x, t_symbol *s, int argc, t_atom *argv); +static void packxbee_TX16(t_packxbee *x, t_symbol *s, int argc, t_atom *argv); static void packxbee_pack_remote_frame(t_packxbee *x, t_symbol *s, int argc, t_atom *argv); static void packxbee_pack_frame(t_packxbee *x, t_symbol *s, int argc, t_atom *argv); static void packxbee_API(t_packxbee *x, t_float api); @@ -94,7 +97,7 @@ static int packxbee_outbuf_add(t_packxbee *x, int index, unsigned char val) return i; } -/* send a packet given a 64-bit address, a 16-bit address, broadcast radius, options, followed by raw data */ +/* send a packet given a 64-bit address, a 16-bit address, broadcast radius, options, followed by raw data (Series2 ZB only) */ static void packxbee_TX(t_packxbee *x, t_symbol *s, int argc, t_atom *argv) { unsigned char floatstring[256]; /* longer than the longest hex number with each character escaped plus the header and checksum overhead */ @@ -164,11 +167,11 @@ static void packxbee_TX(t_packxbee *x, t_symbol *s, int argc, t_atom *argv) return; } f = argv[2].a_w.w_float; - if (x->x_verbosity > 1) post("packxbee_TX float parameter %f", f); + if (x->x_verbosity > 1) post("packxbee_TX: float parameter %f", f); d = ((unsigned int)f)&0x0FF; if (f != d) { - post ("packxbee_TX third argument not a positive integer from 0 to 255"); + error ("packxbee_TX: third argument is not a positive integer from 0 to 255"); return; } else broadcast_radius = d; @@ -181,11 +184,11 @@ static void packxbee_TX(t_packxbee *x, t_symbol *s, int argc, t_atom *argv) return; } f = argv[3].a_w.w_float; - if (x->x_verbosity > 1) post("packxbee_TX float parameter %f", f); + if (x->x_verbosity > 1) post("packxbee_TX: float parameter %f", f); d = ((unsigned int)f)&0x0FF; if (f != d) { - post ("packxbee_TX fourth argument not a positive integer from 0 to 255"); + error ("packxbee_TX: fourth argument is not a positive integer from 0 to 255"); return; } else options = d; @@ -234,11 +237,11 @@ static void packxbee_TX(t_packxbee *x, t_symbol *s, int argc, t_atom *argv) if (A_FLOAT == argv[k].a_type) { f = argv[k].a_w.w_float; - if (x->x_verbosity > 1) post("packxbee_TX float parameter %f", f); + if (x->x_verbosity > 1) post("packxbee_TX: float parameter %f", f); d = ((unsigned int)f)&0x0FF; if (f != d) { - post ("packxbee_TX %dth argument not a positive integer from 0 to 255", k+1); + error ("packxbee_TX: argument %d is not a positive integer from 0 to 255", k+1); return; } floatstring[i++] = d; @@ -246,14 +249,269 @@ static void packxbee_TX(t_packxbee *x, t_symbol *s, int argc, t_atom *argv) } else if (A_SYMBOL == argv[k].a_type) { - if (x->x_verbosity > 1) post("packxbee_TX symbol parameter %s", argv[k].a_w.w_symbol->s_name); + if (x->x_verbosity > 1) post("packxbee_TX: symbol parameter %s", argv[k].a_w.w_symbol->s_name); j = i; i += sprintf((char *)&floatstring[i], "%s", argv[k].a_w.w_symbol->s_name); for (;j < i; ++j) checksum -= floatstring[j]; } else { - error("packxbee_TX %dth argument neither a float nor a symbol", k); + error("packxbee_TX: argument %d is not a float or a symbol", k+1); + return; + } + } + length = i-3; + floatstring[LENGTH_LSB_INDEX] = length & 0x0FF; + floatstring[LENGTH_MSB_INDEX] = length >> 8; + floatstring[i++] = checksum; + k = j = 0; /* j indexes the outbuf, k indexes the floatbuf, i is the length of floatbuf */ + for (k = 0; k < i; ++k) j = packxbee_outbuf_add(x, j, floatstring[k]); + outlet_list(x->x_listout, &s_list, j, x->x_outbuf); + if(x->x_verbosity > 1) + { + for (k = 0; k < j; ++k) + { + c = (unsigned char)atom_getfloat(&x->x_outbuf[k]); + post("buf[%d]: %d [0x%02X]", k, c, c); + } + } +} + +/* send a packet given a 64-bit address, options, followed by raw data (Series1 only) */ +static void packxbee_TX64(t_packxbee *x, t_symbol *s, int argc, t_atom *argv) +{ + unsigned char floatstring[256]; /* longer than the longest hex number with each character escaped plus the header and checksum overhead */ + unsigned long long dest64; + int result; + char checksum = 0xFF; + unsigned char options; + t_float f; + int d, i, j, k; + int length = 0; + unsigned char c; + + if (argc < 3) + { + error("packxbee_TX64: not enough parameters"); + return; + } + /* first arg is dest64, a symbol starting with "0x" */ + if (argv[0].a_type != A_SYMBOL) + { + error("packxbee_TX64: first argument is not a symbol"); + return; + } + if ((argv[0].a_w.w_symbol->s_name[0] != '0')||(argv[0].a_w.w_symbol->s_name[1] != 'x')) + { + error("packxbee_TX64: first argument is not a hex string beginning with \"0x\""); + return; + } +#ifdef _MSC_VER + result = sscanf(argv[0].a_w.w_symbol->s_name, "0x%I64X", &dest64); +#else + result = sscanf(argv[0].a_w.w_symbol->s_name, "0x%LX", &dest64); +#endif + if (result == 0) + { + error("packxbee_TX64: first argument is not a hex string"); + return; + } +#ifdef _MSC_VER + if (x->x_verbosity > 1) post ("packxbee_TX64: dest64:0x%016I64X", dest64); +#else + if (x->x_verbosity > 1) post ("packxbee_TX64: dest64:0x%016LX", dest64); +#endif + /* options is a single byte as a float */ + if (argv[1].a_type != A_FLOAT) + { + error("packxbee_TX64: second argument is not a float"); + return; + } + f = argv[1].a_w.w_float; + if (x->x_verbosity > 1) post("packxbee_TX64 float parameter %f", f); + d = ((unsigned int)f)&0x0FF; + if (f != d) + { + error("packxbee_TX64 second argument is not a positive integer from 0 to 255"); + return; + } + else options = d; + if (x->x_verbosity > 1) post("packxbee_TX64: options: %d", d); + + x->x_frameType = Transmit_Request_64_Bit_Address; + floatstring[0] = XFRAME; /* as usual */ + floatstring[1] = 0; /* length MSB */ + floatstring[2] = 0;/* length LSB */ + floatstring[3] = x->x_frameType; + checksum -= x->x_frameType; + if (0 == x->x_frameID) x->x_frameID++; + checksum -= x->x_frameID; /* frame ID */ + floatstring[4] = x->x_frameID++; + /* raw 8 byte address in big-endian order: */ + floatstring[5] = (dest64>>56)&0x0FF; + checksum -= floatstring[5]; + floatstring[6] = (dest64>>48)&0x0FF; + checksum -= floatstring[6]; + floatstring[7] = (dest64>>40)&0x0FF; + checksum -= floatstring[7]; + floatstring[8] = (dest64>>32)&0x0FF; + checksum -= floatstring[8]; + floatstring[9] = (dest64>>24)&0x0FF; + checksum -= floatstring[9]; + floatstring[10] = (dest64>>16)&0x0FF; + checksum -= floatstring[10]; + floatstring[11] = (dest64>>8)&0x0FF; + checksum -= floatstring[11]; + floatstring[12] = (dest64)&0x0FF; + checksum -= floatstring[12]; + floatstring[13] = options; + checksum -= floatstring[13]; + + /* the rest is payload */ + i = 14; + for (k = 2; k < argc; ++k) + { + if (A_FLOAT == argv[k].a_type) + { + f = argv[k].a_w.w_float; + if (x->x_verbosity > 1) post("packxbee_TX64: float parameter %f", f); + d = ((unsigned int)f)&0x0FF; + if (f != d) + { + error("packxbee_TX64: argument %d is not a positive integer from 0 to 255", k+1); + return; + } + floatstring[i++] = d; + checksum -= d; + } + else if (A_SYMBOL == argv[k].a_type) + { + if (x->x_verbosity > 1) post("packxbee_TX64: symbol parameter %s", argv[k].a_w.w_symbol->s_name); + j = i; + i += sprintf((char *)&floatstring[i], "%s", argv[k].a_w.w_symbol->s_name); + for (;j < i; ++j) checksum -= floatstring[j]; + } + else + { + error("packxbee_TX64: argument %d is not a float or a symbol", k+1); + return; + } + } + length = i-3; + floatstring[LENGTH_LSB_INDEX] = length & 0x0FF; + floatstring[LENGTH_MSB_INDEX] = length >> 8; + floatstring[i++] = checksum; + k = j = 0; /* j indexes the outbuf, k indexes the floatbuf, i is the length of floatbuf */ + for (k = 0; k < i; ++k) j = packxbee_outbuf_add(x, j, floatstring[k]); + outlet_list(x->x_listout, &s_list, j, x->x_outbuf); + if(x->x_verbosity > 1) + { + for (k = 0; k < j; ++k) + { + c = (unsigned char)atom_getfloat(&x->x_outbuf[k]); + post("buf[%d]: %d [0x%02X]", k, c, c); + } + } +} + +/* send a packet given a 16-bit address, options, followed by raw data (Series1 only) */ +static void packxbee_TX16(t_packxbee *x, t_symbol *s, int argc, t_atom *argv) +{ + unsigned char floatstring[256]; /* longer than the longest hex number with each character escaped plus the header and checksum overhead */ + unsigned int dest16; + int result; + char checksum = 0xFF; + unsigned char options; + t_float f; + int d, i, j, k; + int length = 0; + unsigned char c; + + if (argc < 3) + { + error("packxbee_TX16: not enough parameters"); + return; + } + /* first arg is dest16 also a symbol starting with "0x" */ + if (argv[0].a_type != A_SYMBOL) + { + error("packxbee_TX16: first argument is not a symbol"); + return; + } + if ((argv[0].a_w.w_symbol->s_name[0] != '0')||(argv[0].a_w.w_symbol->s_name[1] != 'x')) + { + error("packxbee_TX16: first argument is not a hex string beginning with \"0x\""); + return; + } + result = sscanf(argv[0].a_w.w_symbol->s_name, "0x%X", &dest16); + if (result == 0) + { + error("packxbee_TX16: first argument is not a hex string"); + return; + } + if (x->x_verbosity > 1) post ("packxbee_TX16: dest16: 0x%X", dest16); + + /* options is a single byte as a float */ + if (argv[1].a_type != A_FLOAT) + { + error("packxbee_TX16: second argument is not a float"); + return; + } + f = argv[1].a_w.w_float; + if (x->x_verbosity > 1) post("packxbee_TX16: float parameter %f", f); + d = ((unsigned int)f)&0x0FF; + if (f != d) + { + post ("packxbee_TX16: second argument is not a positive integer from 0 to 255"); + return; + } + else options = d; + if (x->x_verbosity > 1) post("packxbee_TX16: options: %d", d); + + x->x_frameType = Transmit_Request_16_bit_Address; + floatstring[0] = XFRAME; /* as usual */ + floatstring[1] = 0; /* length MSB */ + floatstring[2] = 0;/* length LSB */ + floatstring[3] = x->x_frameType; + checksum -= x->x_frameType; + if (0 == x->x_frameID) x->x_frameID++; + checksum -= x->x_frameID; /* frame ID */ + floatstring[4] = x->x_frameID++; + /* 16-bit address in big-endian order */ + floatstring[5] = (dest16>>8)&0x0FF; + checksum -= floatstring[5]; + floatstring[6] = (dest16)&0x0FF; + checksum -= floatstring[6]; + + floatstring[7] = options; + checksum -= floatstring[7]; + /* the rest is payload */ + i = 8; + for (k = 2; k < argc; ++k) + { + if (A_FLOAT == argv[k].a_type) + { + f = argv[k].a_w.w_float; + if (x->x_verbosity > 1) post("packxbee_TX16: float parameter %f", f); + d = ((unsigned int)f)&0x0FF; + if (f != d) + { + error ("packxbee_TX16: argument %d is not a positive integer from 0 to 255", k+1); + return; + } + floatstring[i++] = d; + checksum -= d; + } + else if (A_SYMBOL == argv[k].a_type) + { + if (x->x_verbosity > 1) post("packxbee_TX16: symbol parameter %s", argv[k].a_w.w_symbol->s_name); + j = i; + i += sprintf((char *)&floatstring[i], "%s", argv[k].a_w.w_symbol->s_name); + for (;j < i; ++j) checksum -= floatstring[j]; + } + else + { + error("packxbee_TX16: argument %d is not a float or a symbol", k+1); return; } } @@ -692,6 +950,8 @@ void packxbee_setup(void) class_addmethod(packxbee_class, (t_method)packxbee_ATQ, gensym("ATQ"), A_GIMME, 0); class_addmethod(packxbee_class, (t_method)packxbee_RAT, gensym("RAT"), A_GIMME, 0); class_addmethod(packxbee_class, (t_method)packxbee_TX, gensym("TX"), A_GIMME, 0); + class_addmethod(packxbee_class, (t_method)packxbee_TX64, gensym("TX64"), A_GIMME, 0); + class_addmethod(packxbee_class, (t_method)packxbee_TX16, gensym("TX16"), A_GIMME, 0); class_addmethod(packxbee_class, (t_method)packxbee_API, gensym("API"), A_DEFFLOAT, 0); class_addmethod(packxbee_class, (t_method)packxbee_verbosity, gensym("verbosity"), A_DEFFLOAT, 0); } diff --git a/xbee/pdxbee.h b/xbee/pdxbee.h index d3023c3..2ce65fa 100644 --- a/xbee/pdxbee.h +++ b/xbee/pdxbee.h @@ -13,12 +13,18 @@ /* API Frame Names and Values */ +#define Transmit_Request_64_Bit_Address 0x00 +#define Transmit_Request_16_bit_Address 0x01 #define AT_Command 0x08 #define AT_Command_Queue_Parameter_Value 0x09 #define ZigBee_Transmit_Request 0x10 #define Explicit_Addressing_ZigBee_Command_Frame 0x11 #define Remote_Command_Request 0x17 #define Create_Source_Route 0x21 +#define Receive_Packet_64_Bit_Address 0x80 +#define Receive_Packet_16_Bit_Address 0x81 +#define Receive_Packet_64_Bit_Address_IO 0x82 +#define Receive_Packet_16_Bit_Address_IO 0x83 #define AT_Command_Response 0x88 #define Modem_Status 0x8A #define ZigBee_Transmit_Status 0x8B diff --git a/xbee/unpackxbee.c b/xbee/unpackxbee.c index 405c799..c7eb6c2 100644 --- a/xbee/unpackxbee.c +++ b/xbee/unpackxbee.c @@ -5,6 +5,7 @@ /* Started by Martin Peach 20110731 */
/* Information taken from "XBeeŽ/XBee-PROŽ ZB RF Modules" (document 90000976_G, 11/15/2010)*/
/* by Digi International Inc. http://www.digi.com */
+/* Series 1 info from "XBeeŽ/XBee-PROŽ RF Modules" (document 90000982_L 4/30/2013) */
#include <stdio.h>
//#include <string.h>
@@ -119,7 +120,7 @@ static void unpackxbee_input(t_unpackxbee *x, t_symbol *s, int argc, t_atom *arg unsigned int d, checksum = 0;
unsigned char c;
t_symbol *type_selector;
- int statuslength = 0, samplelength = 0, payloadstart = 0;
+ int statuslength = 0, payloadstart = 0;
int payload_is_sample_frame = 0;
int digital_bits = 0, digital_ins = 0, digital_channel = 0;
int analog_bits = 0, analog_channel = 0;
@@ -202,6 +203,18 @@ static void unpackxbee_input(t_unpackxbee *x, t_symbol *s, int argc, t_atom *arg case ZigBee_Receive_Packet:
type_selector = gensym("ZigBee_Receive_Packet");
break;
+ case Receive_Packet_64_Bit_Address:
+ type_selector = gensym("Receive_Packet_64_Bit_Address");
+ break;
+ case Receive_Packet_16_Bit_Address:
+ type_selector = gensym("Receive_Packet_16_Bit_Address");
+ break;
+ case Receive_Packet_64_Bit_Address_IO:
+ type_selector = gensym("Receive_Packet_64_Bit_Address_IO");
+ break;
+ case Receive_Packet_16_Bit_Address_IO:
+ type_selector = gensym("Receive_Packet_16_Bit_Address_IO");
+ break;
case ZigBee_Explicit_Rx_Indicator:
type_selector = gensym("ZigBee_Explicit_Rx_Indicator");
break;
@@ -232,13 +245,11 @@ static void unpackxbee_input(t_unpackxbee *x, t_symbol *s, int argc, t_atom *arg statuslength = 0;
SETFLOAT(&status_atoms[statuslength], x->x_frame_type);
statuslength++;
- if
- (
- (AT_Command_Response == x->x_frame_type)
- ||(AT_Command == x->x_frame_type)
- ||(AT_Command_Queue_Parameter_Value == x->x_frame_type)
- )
+ switch (x->x_frame_type)
{
+ case AT_Command_Response:
+ case AT_Command:
+ case AT_Command_Queue_Parameter_Value:
if (x->x_verbosity > 0)
post("AT_Command_Response AT_Command AT_Command_Queue_Parameter_Value statuslength %d", statuslength);
SETFLOAT(&status_atoms[statuslength], x->x_frame_ID);
@@ -369,10 +380,9 @@ buf[28]: 36 [0x24] checksum {
payloadstart = 8;
}
- }
+ break;
/* RAT */
- if (Remote_Command_Response == x->x_frame_type)
- {
+ case Remote_Command_Response:
if (x->x_verbosity > 0)
post("Remote_Command_Response statuslength %d", statuslength);
SETFLOAT(&status_atoms[statuslength], x->x_frame_ID);
@@ -432,10 +442,9 @@ buf[18...] data SETFLOAT(&status_atoms[statuslength], x->x_frame_length-15);
statuslength++;
payloadstart = 18;
- }
+ break;
/* RAT */
- else if (ZigBee_Transmit_Status == x->x_frame_type)
- {
+ case ZigBee_Transmit_Status:
if (x->x_verbosity > 0)
post("ZigBee_Transmit_Status statuslength %d", statuslength);
SETFLOAT(&status_atoms[statuslength], x->x_frame_ID);
@@ -450,9 +459,8 @@ buf[18...] data SETFLOAT(&status_atoms[statuslength], x->x_message[9]);/* Discovery Status */
statuslength++;
payloadstart = 0; /* no payload */
- }
- else if (ZigBee_Receive_Packet == x->x_frame_type)
- {
+ break;
+ case ZigBee_Receive_Packet:
if (x->x_verbosity > 0)
post("ZigBee_Receive_Packet statuslength %d", statuslength);
/* data doesn't include 1byte frametype, 8byte addr64, 2byte addr16, 1byte options = 12bytes*/
@@ -494,9 +502,72 @@ buf[18...] data statuslength++;
/* data */
payloadstart = i;
- }
- else if (ZigBee_IO_Data_Sample_Rx_Indicator == x->x_frame_type)
- {
+ break;
+ case Receive_Packet_64_Bit_Address:
+ if (x->x_verbosity > 0)
+ post("Receive_Packet_64_Bit_Address statuslength %d", statuslength);
+ /* data doesn't include 1byte frametype, 8byte addr64, 1byte RSSI, 1byte options = 11bytes*/
+ SETFLOAT(&status_atoms[statuslength], x->x_frame_length-11);
+ statuslength++;
+ /* frame type */
+ /* 64-bit source address */
+ i = 4;
+ addr64 = x->x_message[i++];
+ addr64 <<= 8;
+ addr64 |= x->x_message[i++];
+ addr64 <<= 8;
+ addr64 |= x->x_message[i++];
+ addr64 <<= 8;
+ addr64 |= x->x_message[i++];
+ addr64 <<= 8;
+ addr64 |= x->x_message[i++];
+ addr64 <<= 8;
+ addr64 |= x->x_message[i++];
+ addr64 <<= 8;
+ addr64 |= x->x_message[i++];
+ addr64 <<= 8;
+ addr64 |= x->x_message[i++];
+#ifdef _MSC_VER
+ sprintf((char *)floatstring, "0x%016I64X", addr64);
+#else
+ sprintf((char *)floatstring, "0x%016LX", addr64);
+#endif
+ SETSYMBOL(&status_atoms[statuslength], gensym((char *)floatstring)); /* addr64 */
+ statuslength++;
+ /* receive signal strength indicator */
+ SETFLOAT(&status_atoms[statuslength], x->x_message[i++]);
+ statuslength++;
+ /* receive options byte */
+ SETFLOAT(&status_atoms[statuslength], x->x_message[i++]);/* 1 2 32 64 */
+ statuslength++;
+ /* data */
+ payloadstart = i;
+ break;
+ case Receive_Packet_16_Bit_Address:
+ if (x->x_verbosity > 0)
+ post("Receive_Packet_16_Bit_Address statuslength %d", statuslength);
+ /* data doesn't include 1byte frametype, 2byte addr64, 1byte RSSI, 1byte options = 5bytes*/
+ SETFLOAT(&status_atoms[statuslength], x->x_frame_length-5);
+ statuslength++;
+ /* frame type */
+ /* 16-bit source address */
+ i = 4;
+ /* 16-bit source address */
+ addr16 = x->x_message[i++]<<8;
+ addr16 |= x->x_message[i++];
+ sprintf((char *)floatstring, "0x%X", addr16);
+ SETSYMBOL(&status_atoms[statuslength], gensym((char *)floatstring)); /* addr16 */
+ statuslength++;
+ /* receive signal strength indicator */
+ SETFLOAT(&status_atoms[statuslength], x->x_message[i++]);
+ statuslength++;
+ /* receive options byte */
+ SETFLOAT(&status_atoms[statuslength], x->x_message[i++]);/* 1 2 32 64 */
+ statuslength++;
+ /* data */
+ payloadstart = i;
+ break;
+ case ZigBee_IO_Data_Sample_Rx_Indicator:
if (x->x_verbosity > 0)
post("ZigBee_IO_Data_Sample_Rx_Indicator statuslength %d", statuslength);
payload_is_sample_frame = 1;
@@ -539,9 +610,8 @@ buf[18...] data statuslength++;
/* data */
payloadstart = i;
- }
- else
- {
+ break;
+ default:
if (x->x_verbosity > 0)
post("some other packet statuslength %d", statuslength);
SETFLOAT(&status_atoms[statuslength], x->x_frame_ID);/* may not be valid */
@@ -549,7 +619,8 @@ buf[18...] data SETFLOAT(&status_atoms[statuslength], x->x_frame_length-2);/* payload doesn't include frame type and ID */
statuslength++;
payloadstart = 5;
- }
+ } /* end of switch */
+
outlet_anything(x->x_status_out, type_selector, statuslength, status_atoms);
if (payloadstart > 0)
{
|