From ac944112aaaab53b526101d7635479a66f0a3ef2 Mon Sep 17 00:00:00 2001 From: Martin Peach Date: Fri, 28 Jun 2013 19:33:35 +0000 Subject: Added handlers for transmit and receive packets for Series1 XBees (64-bit and 16-bit address versions). Some packets are still not implemented. svn path=/trunk/externals/mrpeach/; revision=17169 --- xbee/packxbee.c | 278 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- xbee/pdxbee.h | 6 ++ xbee/unpackxbee.c | 117 ++++++++++++++++++----- 3 files changed, 369 insertions(+), 32 deletions(-) (limited to 'xbee') 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 #include @@ -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 //#include @@ -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) { -- cgit v1.2.1