diff options
Diffstat (limited to 'xbee')
-rw-r--r-- | xbee/packxbee-help.pd | 521 | ||||
-rw-r--r-- | xbee/packxbee.c | 655 | ||||
-rw-r--r-- | xbee/pdxbee.h | 41 | ||||
-rw-r--r-- | xbee/unpackxbee.c | 452 |
4 files changed, 1669 insertions, 0 deletions
diff --git a/xbee/packxbee-help.pd b/xbee/packxbee-help.pd new file mode 100644 index 0000000..2949d19 --- /dev/null +++ b/xbee/packxbee-help.pd @@ -0,0 +1,521 @@ +#N canvas 502 3 994 313 10;
+#X declare -lib mrpeach;
+#X msg 80 53 AT DH 0x0013A200;
+#X text 193 52 set upper 32 bits of destination address;
+#X msg 103 76 AT DL 0x407694DB;
+#X msg 128 101 AT MY;
+#X text 80 9 get upper 32 bits of destination address;
+#X text 97 31 get loweer 32 bits of destination address;
+#X msg 37 10 AT DH;
+#X msg 60 33 AT DL;
+#X msg 148 121 AT MP;
+#X text 171 99 get our 16-bit address (Read Only);
+#X msg 171 144 AT NC;
+#X text 210 141 get number of remaining children (Read Only);
+#X msg 193 166 AT SH;
+#X text 232 163 get serial number high 32 bits (Read Only);
+#X text 253 184 get serial number low 32 bits (Read Only);
+#X msg 214 187 AT SL;
+#X msg 234 207 AT NI diddley;
+#X text 321 204 set node identifier string;
+#X msg 254 227 AT NI;
+#X text 299 225 get node identifier string;
+#X text 527 50 prefix hexadecimal parameters with 0x;
+#X msg 274 247 AT NP;
+#X text 319 245 get maximum payload;
+#X msg 294 267 AT DD;
+#X text 336 264 get device type identifier;
+#X text 191 119 get endpoint parent's 16-bit address (Read Only);
+#X msg 328 301 AT CH;
+#X text 366 300 get operating channel;
+#X msg 348 321 AT ID;
+#X text 386 320 get 64-bit PAN ID;
+#X text 529 342 set 64-bit PAN ID;
+#X msg 390 363 AT ID 0x0;
+#X text 458 362 set coordinator chosen 64-bit PAN ID;
+#X msg 370 343 AT ID 0xFEEAFEEBFEECFEED;
+#X text 210 74 set lower 32 bits of destination address;
+#X msg 412 385 AT OP;
+#X text 455 383 get operating 64-bit PAN ID;
+#X msg 432 405 AT NH;
+#X msg 452 425 AT NH 0xFF;
+#X text 528 443 set maximum unicast hops (float arg);
+#X text 525 423 set maximum unicast hops (symbol arg);
+#X text 475 403 get maximum unicast hops (no arg);
+#X msg 492 465 AT BH;
+#X text 535 463 get maximum broadcastcast hops (no arg);
+#X text 585 483 set maximum broadcast hops (symbol arg);
+#X msg 512 485 AT BH 0x1E;
+#X msg 532 505 AT BH 3;
+#X text 585 502 set maximum broadcast hops (float arg);
+#X msg 552 525 AT OI;
+#X text 595 523 get operating 16-bit PAN ID;
+#X msg 472 445 AT NH 2;
+#X msg 573 546 AT NT;
+#X text 616 544 get node discovery timeout;
+#X text 662 564 set node discovery timeout;
+#X msg 593 566 AT NT 0xFF;
+#X msg 613 586 AT NO;
+#X msg 633 606 AT NO 3;
+#X text 656 584 get node discovery options;
+#X text 684 604 set node discovery options;
+#X msg 654 627 AT SC;
+#X msg 673 646 AT SC 0xFFFF;
+#X text 697 625 get scan channel bitmask;
+#X text 754 645 set scan channels;
+#X msg 692 665 AT SD;
+#X msg 711 684 AT SD 3;
+#X text 735 663 get scan duration;
+#X text 762 683 set scan duration;
+#X text 66 300 get zigbee stack profile;
+#X text 94 320 set zigbee stack profile;
+#X msg 28 301 AT ZS;
+#X msg 47 320 AT ZS 0;
+#X msg 68 341 AT NJ;
+#X msg 88 361 AT NJ 0xFF;
+#X text 106 340 get node join time;
+#X text 161 360 set node join time;
+#X obj 412 700 s topackxbee;
+#X obj 583 690 r topackxbee;
+#X msg 108 381 AT JV;
+#X text 146 380 get channel verification;
+#X text 181 400 set channel verification;
+#X msg 128 401 AT JV 1;
+#X obj 237 720 comport 23 9600;
+#X text 203 437 get power level;
+#X msg 165 438 AT PL;
+#X msg 185 458 AT PM;
+#X text 223 457 get power mode;
+#X msg 205 478 AT DB;
+#X msg 225 498 AT PP;
+#X text 263 497 get peak power dBm;
+#X text 243 477 get received signal strength -dBm;
+#X text 283 517 get API mode;
+#X msg 245 518 AT AP;
+#X msg 325 598 AT AO;
+#X text 363 597 get API options;
+#X msg 345 618 AT BD;
+#X text 383 617 get interface data rate;
+#X msg 365 638 AT NB;
+#X text 403 637 get interface parity;
+#X msg 385 658 AT SB;
+#X text 423 657 get interface stop bits;
+#X msg 405 678 AT RO;
+#X text 443 677 get packetization timeout;
+#X obj 1082 736 s topackxbee;
+#X msg 954 593 AT D7;
+#X msg 936 575 AT D6;
+#X msg 708 347 AT IR;
+#X text 746 346 get IO sample rate;
+#X msg 728 367 AT IC;
+#X text 766 366 get IO digital change detection;
+#X msg 748 387 AT P0;
+#X text 786 386 get PWM0 function;
+#X msg 768 407 AT P1;
+#X text 806 406 get PWM1 function;
+#X msg 788 427 AT P2;
+#X text 826 426 get PWM2 function;
+#X msg 808 447 AT P3;
+#X text 846 446 get PWM3 function;
+#X msg 828 467 AT D0;
+#X text 872 466 get AD0/DIO0 function;
+#X msg 846 485 AT D1;
+#X msg 864 503 AT D2;
+#X text 908 502 get AD2/DIO2 function;
+#X text 890 484 get AD1/DIO1 function;
+#X msg 882 521 AT D3;
+#X msg 900 539 AT D4;
+#X msg 918 557 AT D5;
+#X text 926 520 get AD3/DIO3 function;
+#X text 944 538 get DIO4 function;
+#X text 962 556 get DIO5 function;
+#X text 974 574 get DIO6 configuration;
+#X text 992 592 get DIO7 configuration;
+#X msg 972 611 AT D8;
+#X text 1010 610 get DIO8 configuration;
+#X msg 991 630 AT LT;
+#X text 1026 628 get Associate LED blink time 10ms;
+#X msg 1009 648 AT PR;
+#X text 1044 646 get pullup resistors;
+#X text 1067 664 get supply voltage 1200/1024mV;
+#X msg 1028 667 AT %V;
+#X msg 1048 687 AT V+;
+#X text 1087 684 get supply voltage threshold 1200/1024mV;
+#X msg 1068 707 AT TP;
+#X text 1107 704 get temperature C;
+#X obj 1277 662 s topackxbee;
+#X msg 979 349 AT VR;
+#X text 1018 346 get firmware version;
+#X msg 999 369 AT HV;
+#X text 1038 366 get hardware version;
+#X msg 1019 389 AT AI;
+#X text 1058 386 get association indication;
+#X msg 1039 409 AT CC;
+#X text 1078 406 get AT command sequence character;
+#X msg 1069 439 AT ND;
+#X text 1108 436 node discover;
+#X text 1187 457 resolve destination node;
+#X msg 1089 459 AT DN jellybaby;
+#X msg 1109 479 AT IS;
+#X msg 1129 499 AT 1S;
+#X text 1157 477 force sample;
+#X text 1167 497 force xbee sample;
+#X msg 143 705 devices;
+#X msg 11 546 API 1;
+#X msg 33 568 API 2;
+#X obj 86 636 s topackxbee;
+#X text 50 545 set API mode 1;
+#X text 74 569 set API mode 2 (escaped characters);
+#X text 55 583 mode 2 is the default setting;
+#X text 314 537 set API mode;
+#X msg 265 538 AT AP 1;
+#X text 334 557 set API mode;
+#X msg 285 558 AT AP 2;
+#X msg 1162 532 AT AC;
+#X text 1202 530 apply changes;
+#X msg 1182 552 AT WR;
+#X text 1222 550 write parameters to non-volatile memory;
+#X msg 1202 572 AT RE;
+#X text 1242 570 restore defaults;
+#X msg 1222 592 AT FR;
+#X text 1262 590 software reset;
+#X msg 1242 612 AT NR;
+#X text 1282 610 network reset;
+#X msg 1262 632 AT CB 1;
+#X text 1312 630 commisioning pushbutton;
+#X text 1115 515 ***DANGEROUS***;
+#X text 14 704 list available ports;
+#X obj 792 320 s topackxbee;
+#X text 640 79 queue set interface data rate;
+#X msg 566 79 ATQ BD 7;
+#X msg 184 652 baud 115200;
+#X msg 208 676 baud 9600;
+#X text 660 99 queue set interface data rate;
+#X msg 586 99 ATQ BD 3;
+#X msg 150 750 verbosity \$1;
+#X obj 96 735 hradio 15 1 0 3 empty empty verbosity 0 -8 0 10 -4034
+-1 -1 0;
+#X msg 713 226 verbosity \$1;
+#X obj 659 211 hradio 15 1 0 3 empty empty verbosity 0 -8 0 10 -4034
+-1 -1 0;
+#X msg 656 169 TX 0x0013A200406ADE1E 0x79D6 0 0 64;
+#X obj 237 739 t f f;
+#X obj 237 793 print data;
+#N canvas 4 353 1019 577 status 1;
+#X obj 73 16 inlet;
+#X floatatom 184 218 5 0 0 0 - - -;
+#X obj 264 97 print unpack5;
+#X obj 73 50 route AT_Command_Response;
+#X obj 73 82 list split 3;
+#X obj 184 142 route ND;
+#X obj 184 120 list trim;
+#X symbolatom 201 234 7 0 0 0 - - -;
+#X symbolatom 219 251 17 0 0 0 - - -;
+#X obj 73 120 unpack 0 0 0;
+#X floatatom 73 144 5 0 0 0 - - -;
+#X floatatom 107 164 5 0 0 0 - - -;
+#X floatatom 142 184 5 0 0 0 - - -;
+#X text -1 144 packet type;
+#X text 39 164 packet ID;
+#X text 64 183 data length;
+#X text 71 215 AT command status;
+#X text 155 233 addr16;
+#X text 175 249 addr64;
+#X obj 428 65 route ZigBee_Transmit_Status;
+#X floatatom 428 105 5 0 0 0 - - -;
+#X floatatom 449 123 5 0 0 0 - - -;
+#X text 354 105 packet type;
+#X text 381 123 packet ID;
+#X symbolatom 470 140 7 0 0 0 - - -;
+#X text 427 139 addr16;
+#X floatatom 533 192 5 0 0 0 - - -;
+#X floatatom 512 175 5 0 0 0 - - -;
+#X floatatom 491 158 5 0 0 0 - - -;
+#X text 360 156 transmit retry count;
+#X text 411 173 delivery status;
+#X text 427 190 discovery status;
+#X symbolatom 236 268 32 0 0 0 - - -;
+#X symbolatom 254 286 7 0 0 0 - - -;
+#X symbolatom 307 339 7 0 0 0 - - -;
+#X symbolatom 325 357 7 0 0 0 - - -;
+#X obj 184 196 unpack 0 s s s s 0 0 s s;
+#X floatatom 272 304 5 0 0 0 - - -;
+#X floatatom 289 321 5 0 0 0 - - -;
+#X text 139 267 Node Identifier;
+#X text 207 285 parent;
+#X text 197 301 device type;
+#X text 209 319 source event;
+#X text 252 337 profile;
+#X text 247 355 manufacturer;
+#X obj 229 162 print unpack7;
+#X obj 428 85 unpack 0 0 s 0 0 0;
+#X obj 616 80 route ZigBee_Receive_Packet;
+#X obj 775 100 print someotherpacket;
+#X symbolatom 685 177 7 0 0 0 - - -;
+#X symbolatom 662 159 17 0 0 0 - - -;
+#X text 639 176 addr16;
+#X text 618 157 addr64;
+#X floatatom 616 123 5 0 0 0 - - -;
+#X text 542 123 packet type;
+#X floatatom 709 195 5 0 0 0 - - -;
+#X text 610 193 receive options;
+#X obj 709 245 tgl 15 0 empty empty acknowledged 17 7 0 10 -4034 -1
+-1 0 1;
+#X obj 749 265 tgl 15 0 empty empty broadcast 17 7 0 10 -4034 -1 -1
+0 1;
+#X obj 789 285 tgl 15 0 empty empty encrypted 17 7 0 10 -4034 -1 -1
+0 1;
+#X obj 829 305 tgl 15 0 empty empty from_end_device 17 7 0 10 -4034
+-1 -1 0 1;
+#X obj 709 209 & 1;
+#X obj 749 209 & 2;
+#X obj 789 209 & 32;
+#X obj 829 209 & 64;
+#X obj 616 101 unpack 0 0 s s 0;
+#X floatatom 639 140 5 0 0 0 - - -;
+#X text 565 140 data length;
+#X obj 511 214 select 0 2 21 33 34 35 36 37;
+#X symbolatom 511 411 32 0 0 0 - - -;
+#X msg 511 238 set success;
+#X msg 676 396 set unknown;
+#X msg 531 257 set CCA_failurs;
+#X msg 572 297 set Network_ACK_Failure;
+#X msg 552 277 set Invalid_Destination_Endpoint;
+#X msg 593 317 set Not_Joined_To_Network;
+#X msg 612 337 set Self-Addresed;
+#X msg 634 356 set Address_Not_Found;
+#X msg 655 376 set Route_Not_Found;
+#X text 408 410 delivery status:;
+#X symbolatom 532 547 32 0 0 0 - - -;
+#X msg 613 532 set unknown;
+#X obj 532 435 select 0 1 2 3;
+#X msg 532 456 set No_Discovery_Overhead;
+#X msg 552 475 set Address_Discovery;
+#X msg 573 494 set Route_Discovery;
+#X msg 593 513 set Address_And_Route_Discovery;
+#X text 428 545 discovery status:;
+#X connect 0 0 3 0;
+#X connect 3 0 4 0;
+#X connect 3 1 19 0;
+#X connect 4 0 9 0;
+#X connect 4 1 6 0;
+#X connect 4 2 2 0;
+#X connect 5 0 36 0;
+#X connect 5 1 45 0;
+#X connect 6 0 5 0;
+#X connect 9 0 10 0;
+#X connect 9 1 11 0;
+#X connect 9 2 12 0;
+#X connect 19 0 46 0;
+#X connect 19 1 47 0;
+#X connect 36 0 1 0;
+#X connect 36 1 7 0;
+#X connect 36 2 8 0;
+#X connect 36 3 32 0;
+#X connect 36 4 33 0;
+#X connect 36 5 37 0;
+#X connect 36 6 38 0;
+#X connect 36 7 34 0;
+#X connect 36 8 35 0;
+#X connect 46 0 20 0;
+#X connect 46 1 21 0;
+#X connect 46 2 24 0;
+#X connect 46 3 28 0;
+#X connect 46 4 27 0;
+#X connect 46 4 68 0;
+#X connect 46 5 26 0;
+#X connect 46 5 82 0;
+#X connect 47 0 65 0;
+#X connect 47 1 48 0;
+#X connect 55 0 61 0;
+#X connect 55 0 62 0;
+#X connect 55 0 63 0;
+#X connect 55 0 64 0;
+#X connect 61 0 57 0;
+#X connect 62 0 58 0;
+#X connect 63 0 59 0;
+#X connect 64 0 60 0;
+#X connect 65 0 53 0;
+#X connect 65 1 66 0;
+#X connect 65 2 50 0;
+#X connect 65 3 49 0;
+#X connect 65 4 55 0;
+#X connect 68 0 70 0;
+#X connect 68 1 72 0;
+#X connect 68 2 74 0;
+#X connect 68 3 73 0;
+#X connect 68 4 75 0;
+#X connect 68 5 76 0;
+#X connect 68 6 77 0;
+#X connect 68 7 78 0;
+#X connect 68 8 71 0;
+#X connect 70 0 69 0;
+#X connect 71 0 69 0;
+#X connect 72 0 69 0;
+#X connect 73 0 69 0;
+#X connect 74 0 69 0;
+#X connect 75 0 69 0;
+#X connect 76 0 69 0;
+#X connect 77 0 69 0;
+#X connect 78 0 69 0;
+#X connect 81 0 80 0;
+#X connect 82 0 83 0;
+#X connect 82 1 84 0;
+#X connect 82 2 85 0;
+#X connect 82 3 86 0;
+#X connect 82 4 81 0;
+#X connect 83 0 80 0;
+#X connect 84 0 80 0;
+#X connect 85 0 80 0;
+#X connect 86 0 80 0;
+#X restore 317 780 pd status;
+#X obj 385 754 spigot;
+#X obj 385 776 print raw;
+#X obj 418 730 tgl 15 0 empty empty print_raw 17 7 0 10 -4034 -1 -1
+0 1;
+#X obj 709 771 print packed;
+#X obj 717 754 spigot;
+#X obj 750 730 tgl 15 0 empty empty print_packed 17 7 0 10 -4034 -1
+-1 0 1;
+#X obj 717 705 packxbee 2;
+#X obj 237 765 unpackxbee 2;
+#X msg 742 255 RAT 0x0013A200406ADE1E 0x79D6 0 AT SH;
+#X msg 762 275 RAT 0x0013A200406ADE1E 0x79D6 0 AT SL;
+#X msg 636 149 TX 0x0013A20040769444 0xFFFE 0 0 1 2 3 4;
+#X msg 836 196 RAT 0x0013A20040769698 0xDA23 0 AT SL;
+#X obj 412 2 import mrpeach;
+#X text 891 135 data packet: 64-bit_destination 16-bit_destination
+broadcast_radius options data;
+#X msg 617 130 TX 0x0013A20040769698 0xFFFE 0 0 136 \$1;
+#X obj 898 97 hsl 128 15 0 127 0 0 empty empty empty -2 -8 0 10 -262144
+-1 -1 8100 1;
+#X obj 895 116 nbx 5 14 -1e+037 1e+037 0 0 empty empty empty 0 -8 0
+10 -262144 -1 -1 81 256;
+#X obj 931 47 metro 2000;
+#X obj 925 74 f;
+#X obj 968 74 + 1;
+#X obj 942 16 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X obj 1012 72 % 128;
+#X connect 0 0 206 0;
+#X connect 2 0 206 0;
+#X connect 3 0 206 0;
+#X connect 6 0 206 0;
+#X connect 7 0 206 0;
+#X connect 8 0 206 0;
+#X connect 10 0 206 0;
+#X connect 12 0 206 0;
+#X connect 15 0 206 0;
+#X connect 16 0 206 0;
+#X connect 18 0 206 0;
+#X connect 21 0 206 0;
+#X connect 23 0 206 0;
+#X connect 26 0 206 0;
+#X connect 28 0 206 0;
+#X connect 31 0 206 0;
+#X connect 33 0 206 0;
+#X connect 35 0 206 0;
+#X connect 37 0 206 0;
+#X connect 38 0 206 0;
+#X connect 42 0 206 0;
+#X connect 45 0 206 0;
+#X connect 46 0 206 0;
+#X connect 48 0 206 0;
+#X connect 50 0 206 0;
+#X connect 51 0 206 0;
+#X connect 54 0 206 0;
+#X connect 55 0 206 0;
+#X connect 56 0 206 0;
+#X connect 59 0 206 0;
+#X connect 60 0 206 0;
+#X connect 63 0 206 0;
+#X connect 64 0 206 0;
+#X connect 69 0 75 0;
+#X connect 70 0 75 0;
+#X connect 71 0 75 0;
+#X connect 72 0 75 0;
+#X connect 76 0 206 0;
+#X connect 77 0 75 0;
+#X connect 80 0 75 0;
+#X connect 81 0 197 0;
+#X connect 83 0 75 0;
+#X connect 84 0 75 0;
+#X connect 86 0 75 0;
+#X connect 87 0 75 0;
+#X connect 91 0 75 0;
+#X connect 92 0 75 0;
+#X connect 94 0 75 0;
+#X connect 96 0 75 0;
+#X connect 98 0 75 0;
+#X connect 100 0 75 0;
+#X connect 103 0 102 0;
+#X connect 104 0 102 0;
+#X connect 105 0 102 0;
+#X connect 107 0 102 0;
+#X connect 109 0 102 0;
+#X connect 111 0 102 0;
+#X connect 113 0 102 0;
+#X connect 115 0 102 0;
+#X connect 117 0 102 0;
+#X connect 119 0 102 0;
+#X connect 120 0 102 0;
+#X connect 123 0 102 0;
+#X connect 124 0 102 0;
+#X connect 125 0 102 0;
+#X connect 131 0 102 0;
+#X connect 133 0 102 0;
+#X connect 135 0 102 0;
+#X connect 138 0 102 0;
+#X connect 139 0 102 0;
+#X connect 141 0 102 0;
+#X connect 144 0 143 0;
+#X connect 146 0 143 0;
+#X connect 148 0 143 0;
+#X connect 150 0 143 0;
+#X connect 152 0 143 0;
+#X connect 155 0 143 0;
+#X connect 156 0 143 0;
+#X connect 157 0 143 0;
+#X connect 160 0 81 0;
+#X connect 161 0 163 0;
+#X connect 162 0 163 0;
+#X connect 168 0 75 0;
+#X connect 170 0 75 0;
+#X connect 171 0 143 0;
+#X connect 173 0 143 0;
+#X connect 175 0 143 0;
+#X connect 177 0 143 0;
+#X connect 179 0 143 0;
+#X connect 181 0 143 0;
+#X connect 187 0 185 0;
+#X connect 188 0 81 0;
+#X connect 189 0 81 0;
+#X connect 191 0 185 0;
+#X connect 192 0 207 0;
+#X connect 193 0 192 0;
+#X connect 194 0 185 0;
+#X connect 195 0 194 0;
+#X connect 196 0 185 0;
+#X connect 197 0 207 0;
+#X connect 197 1 200 0;
+#X connect 200 0 201 0;
+#X connect 202 0 200 1;
+#X connect 204 0 203 0;
+#X connect 205 0 204 1;
+#X connect 206 0 81 0;
+#X connect 206 0 204 0;
+#X connect 207 0 198 0;
+#X connect 207 1 199 0;
+#X connect 208 0 185 0;
+#X connect 209 0 185 0;
+#X connect 210 0 185 0;
+#X connect 211 0 185 0;
+#X connect 214 0 185 0;
+#X connect 215 0 216 0;
+#X connect 216 0 214 0;
+#X connect 217 0 218 0;
+#X connect 218 0 219 0;
+#X connect 218 0 215 0;
+#X connect 219 0 221 0;
+#X connect 220 0 217 0;
+#X connect 221 0 218 1;
diff --git a/xbee/packxbee.c b/xbee/packxbee.c new file mode 100644 index 0000000..37ea476 --- /dev/null +++ b/xbee/packxbee.c @@ -0,0 +1,655 @@ +/* packxbee outputs a list of floats which are the bytes making up an xbee api packet. */ +/* The packet can then be sent through [comport]. */ +/* 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 */ + +#include <stdio.h> +//#include <string.h> +#include "m_pd.h" +#include "pdxbee.h" + +static t_class *packxbee_class; + + +typedef struct _packxbee +{ + t_object x_obj; + t_outlet *x_listout; + int x_api_mode; + unsigned char x_frameID; + unsigned char x_frameType; + int x_verbosity; + t_atom x_outbuf[MAX_XBEE_PACKET_LENGTH]; +} t_packxbee; + +static void *packxbee_new(t_floatarg f); +static int packxbee_outbuf_add(t_packxbee *x, int index, unsigned char val); +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_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); +static void packxbee_verbosity(t_packxbee *x, t_float verbosity_level); +static void packxbee_free(t_packxbee *x); +void packxbee_setup(void); + +static void *packxbee_new(t_floatarg f) +{ + int i; + + t_packxbee *x = (t_packxbee *)pd_new(packxbee_class); + if (x) + { + x->x_listout = outlet_new(&x->x_obj, &s_list); + if (1 == f) x->x_api_mode = 1; + else x->x_api_mode = 2; /* default to escaped mode */ + x->x_verbosity = 2; /* debug level */ + for(i = 0; i < MAX_XBEE_PACKET_LENGTH; ++i) x->x_outbuf[i].a_type = A_FLOAT; /* init output atoms as floats */ + } + return (x); +} + +static void packxbee_API(t_packxbee *x, t_float api) +{ + if ((api == 1) || (api ==2)) x->x_api_mode = api; + else error ("packxbee: api mode must be 1 or 2"); +} + +static void packxbee_verbosity(t_packxbee *x, t_float verbosity_level) +{ + if (verbosity_level >= 0) x->x_verbosity = verbosity_level; + else error ("packxbee: verbosity_level must be positive"); +} + +static int packxbee_outbuf_add(t_packxbee *x, int index, unsigned char val) +{ + int i = index; + +/* if API mode is 2 all characters after the first are escaped if they are one of the sacred texts */ +/* to escape the character prefix it with XSCAPE and XOR it with 0x20 */ + if + ( + (2 == x->x_api_mode) + && + ( + ((0 < index)&&(XFRAME == val)) + ||(XSCAPE == val) + ||(XON == val) + ||(XOFF == val) + ) + ) + { /* escape the character */ + x->x_outbuf[i].a_w.w_float = XSCAPE; + ++i; + x->x_outbuf[i].a_w.w_float = val ^ 0x20; + ++i; + } + else + { /* otherwise just put it in the buffer */ + x->x_outbuf[i++].a_w.w_float = val; + } + return i; +} + +/* send a packet given a 64-bit address, a 16-bit address, broadcast radius, options, followed by raw data */ +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 */ + unsigned long long dest64; + unsigned int dest16; + int result; + char checksum = 0xFF; + unsigned char broadcast_radius, options; + t_float f; + int d, i, j, k; + int length = 0; + unsigned char c; + + if (argc < 5) + { + error("packxbee_TX: not enough parameters"); + return; + } + /* first arg is dest64, a symbol starting with "0x" */ + if (argv[0].a_type != A_SYMBOL) + { + error("packxbee_TX: 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_TX: first argument is not a hex string beginning with \"0x\""); + return; + } + result = sscanf(argv[0].a_w.w_symbol->s_name, "0x%I64X", &dest64); + if (result == 0) + { + error("packxbee_TX: first argument is not a hex string"); + return; + } + if (x->x_verbosity > 0) post ("packxbee_TX: dest64:0x%I64X", dest64); + /* second arg is dest16 also a symbol starting with "0x" */ + if (argv[1].a_type != A_SYMBOL) + { + error("packxbee_TX: second argument is not a symbol"); + return; + } + if ((argv[1].a_w.w_symbol->s_name[0] != '0')||(argv[1].a_w.w_symbol->s_name[1] != 'x')) + { + error("packxbee_TX: second argument is not a hex string beginning with \"0x\""); + return; + } + result = sscanf(argv[1].a_w.w_symbol->s_name, "0x%X", &dest16); + if (result == 0) + { + error("packxbee_TX: second argument is not a hex string"); + return; + } + if (x->x_verbosity > 0) post ("packxbee_TX: dest16: 0x%X", dest16); + /* broadcast radius is a single byte as a float */ + if (argv[2].a_type != A_FLOAT) + { + error("packxbee_TX: third argument is not a float"); + return; + } + f = argv[2].a_w.w_float; + if (x->x_verbosity > 0) 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"); + return; + } + else broadcast_radius = d; + if (x->x_verbosity > 0) post("packxbee_TX: broadcast_radius: %d", d); + + /* options is a single byte as a float */ + if (argv[3].a_type != A_FLOAT) + { + error("packxbee_TX: fourth argument is not a float"); + return; + } + f = argv[3].a_w.w_float; + if (x->x_verbosity > 0) 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"); + return; + } + else options = d; + if (x->x_verbosity > 0) post("packxbee_TX: options: %d", d); + + x->x_frameType = ZigBee_Transmit_Request;/* because we're building a queued AT frame */ + 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] = (dest16>>8)&0x0FF; + checksum -= floatstring[13]; + floatstring[14] = (dest16)&0x0FF; + checksum -= floatstring[14]; + + floatstring[15] = broadcast_radius; + checksum -= floatstring[15]; + floatstring[16] = options; + checksum -= floatstring[16]; + /* the rest is payload */ + i = 17; + for (k = 4; k < argc; ++k) + { + if (A_FLOAT == argv[k].a_type) + { + f = argv[k].a_w.w_float; + if (x->x_verbosity > 0) 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); + return; + } + floatstring[i++] = d; + checksum -= d; + } + else if (A_SYMBOL == argv[k].a_type) + { + if (x->x_verbosity > 0) post("packxbee_TX symbol parameter %s", argv[k].a_w.w_symbol->s_name); + j = i; + i += sprintf(&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); + 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); + } + } +} + +/* format a queued AT packet and send it through x_listout as a list of floats */ +static void packxbee_ATQ(t_packxbee *x, t_symbol *s, int argc, t_atom *argv) +{ + x->x_frameType = AT_Command_Queue_Parameter_Value;/* we're building a queued AT frame */ + packxbee_pack_frame(x, s, argc, argv); +} + +/* format an AT packet and send it through x_listout as a list of floats */ +static void packxbee_AT(t_packxbee *x, t_symbol *s, int argc, t_atom *argv) +{ + x->x_frameType = AT_Command;/* we're building an AT frame */ + packxbee_pack_frame(x, s, argc, argv); +} + +/* format a remote AT packet and send it through x_listout as a list of floats */ +static void packxbee_RAT(t_packxbee *x, t_symbol *s, int argc, t_atom *argv) +{ + x->x_frameType = Remote_Command_Request;/* we're building a remote AT frame */ + if (argc < 3) + { + error("packxbee_RAT: not enough parameters"); + return; + } + packxbee_pack_remote_frame(x, s, argc, argv); +} + +static void packxbee_pack_remote_frame(t_packxbee *x, t_symbol *s, int argc, t_atom *argv) +{ + int i, j, k, maxdigits, d; + char checksum = 0xFF; + unsigned char floatstring[256]; /* longer than the longest hex number with each character escaped plus the header and checksum overhead */ + int length = 0; + int usefloatstring = 0; + unsigned char c, digits; + long param; + t_float f; + + unsigned long long dest64; + unsigned int dest16; + int result; + unsigned char options; + + + if (x->x_verbosity > 0) post("packxbee_AT s is %s, argc is %d", s->s_name, argc); + if (argc >= 4) /* we must have addr64, addr16, option byte, and an AT command */ + { + /* first arg is dest64, a symbol starting with "0x" */ + if (argv[0].a_type != A_SYMBOL) + { + error("packxbee_pack_remote_frame: 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_pack_remote_frame: first argument is not a hex string beginning with \"0x\""); + return; + } + result = sscanf(argv[0].a_w.w_symbol->s_name, "0x%I64X", &dest64); + if (result == 0) + { + error("packxbee_pack_remote_frame: first argument is not a hex string"); + return; + } + if (x->x_verbosity > 0) post ("packxbee_pack_remote_frame: dest64:0x%I64X", dest64); + /* second arg is dest16 also a symbol starting with "0x" */ + if (argv[1].a_type != A_SYMBOL) + { + error("packxbee_pack_remote_frame: second argument is not a symbol"); + return; + } + if ((argv[1].a_w.w_symbol->s_name[0] != '0')||(argv[1].a_w.w_symbol->s_name[1] != 'x')) + { + error("packxbee_pack_remote_frame: second argument is not a hex string beginning with \"0x\""); + return; + } + result = sscanf(argv[1].a_w.w_symbol->s_name, "0x%X", &dest16); + if (result == 0) + { + error("packxbee_pack_remote_frame: second argument is not a hex string"); + return; + } + if (x->x_verbosity > 0) post ("packxbee_pack_remote_frame: dest16: 0x%X", dest16); + /* options is a single byte as a float */ + if (argv[2].a_type != A_FLOAT) + { + error("packxbee_pack_remote_frame: third argument is not a float"); + return; + } + f = argv[2].a_w.w_float; + if (x->x_verbosity > 0) post("packxbee_pack_remote_frame float parameter %f", f); + d = ((unsigned int)f)&0x0FF; + if (f != d) + { + post ("packxbee_pack_remote_frame third argument not a positive integer from 0 to 255"); + return; + } + else options = d; + if (x->x_verbosity > 0) post("packxbee_pack_remote_frame: options: %d", d); + if (argv[3].a_type != A_SYMBOL) + { + post ("packxbee_pack_remote_frame: argument 4 must be an AT command"); + return; + } + if (x->x_verbosity > 0) post ("packxbee_pack_remote_frame: argument 4 is %s", argv[3].a_w.w_symbol->s_name); + if (2 != strlen(argv[3].a_w.w_symbol->s_name)) + { + post ("packxbee_pack_remote_frame: argument 4 must be a two-character AT command"); + return; + } + if (((argv[3].a_w.w_symbol->s_name[0] < 0x20) || (argv[3].a_w.w_symbol->s_name[0] > 0x7F)) + || ((argv[3].a_w.w_symbol->s_name[1] < 0x20) || (argv[3].a_w.w_symbol->s_name[1] > 0x7F))) + { + post ("packxbee_pack_remote_frame: argument 4 must be printable ascii"); + return; + } + /* parameters seem valid, now build the frame */ + i = 0; + floatstring[i++] = XFRAME; /* as usual */ + floatstring[i++] = 0; /* length MSB */ + floatstring[i++] = 0;/* length LSB */ + floatstring[i++] = x->x_frameType; + checksum -= x->x_frameType; + if (0 == x->x_frameID) x->x_frameID++; /* never use zero as frame ID */ + floatstring[i] = x->x_frameID++; + checksum -= floatstring[i++]; + + /* raw 8 byte address in big-endian order: */ + floatstring[i] = (dest64>>56)&0x0FF; + checksum -= floatstring[i++]; + floatstring[i] = (dest64>>48)&0x0FF; + checksum -= floatstring[i++]; + floatstring[i] = (dest64>>40)&0x0FF; + checksum -= floatstring[i++]; + floatstring[i] = (dest64>>32)&0x0FF; + checksum -= floatstring[i++]; + floatstring[i] = (dest64>>24)&0x0FF; + checksum -= floatstring[i++]; + floatstring[i] = (dest64>>16)&0x0FF; + checksum -= floatstring[i++]; + floatstring[i] = (dest64>>8)&0x0FF; + checksum -= floatstring[i++]; + floatstring[i] = (dest64)&0x0FF; + checksum -= floatstring[i++]; + + floatstring[i] = (dest16>>8)&0x0FF; + checksum -= floatstring[i++]; + floatstring[i] = (dest16)&0x0FF; + checksum -= floatstring[i++]; + + floatstring[i] = options; + checksum -= floatstring[i++]; + + c = argv[3].a_w.w_symbol->s_name[0];/* the first character of the AT command */ + floatstring[i] = c; + checksum -= floatstring[i++]; + c = argv[3].a_w.w_symbol->s_name[1];/* the second character of the AT command */ + floatstring[i] = c; + checksum -= floatstring[i++]; + j = i; /* save i in j so we can calculate checksum on any further parameters */ + /* parameters if any */ + if (argc >= 5) + { /* some parameters */ + if (argv[4].a_type == A_SYMBOL) + { + if (x->x_verbosity > 0) post("packxbee_pack_remote_frame symbol parameter %s", argv[4].a_w.w_symbol->s_name); + if (('0' == argv[4].a_w.w_symbol->s_name[0])&&(('x' == argv[4].a_w.w_symbol->s_name[1]))) + { /* this is a hexadecimal number: strip the "0x" and copy the rest to the buffer as ascii digits */ + i += sprintf(&floatstring[i], "%s", &argv[4].a_w.w_symbol->s_name[2]); + } + else // if ((0 == strncmp("NI", argv[0].a_w.w_symbol->s_name, 2))||(0 == strncmp("DN", argv[0].a_w.w_symbol->s_name, 2))) + { /* we hope it's just an ascii string for the NI command */ + for (k = 0; (k < 20); ++k) /* no more than 20 characters in a node identifier */ + { + c = argv[4].a_w.w_symbol->s_name[k]; + if (0 == c) break; + //checksum -= c; + floatstring[i++] = c; + } + } + } + else if (argv[4].a_type == A_FLOAT) + { + f = argv[4].a_w.w_float; + if (x->x_verbosity > 0) post("packxbee_pack_remote_frame float parameter %f", f); + d = ((unsigned int)f)&0x0FF; + if (f != d) + { + post ("packxbee_pack_remote_frame parameter not a positive integer from 0 to 255"); + } + else + { + // put the significant part of the raw value into floatstring in big endian order + if (0 != ((d>>24) & 0x0FF)) digits = 4; + else if (0 != ((d>>16) & 0x0FF)) digits = 3; + else if (0 != ((d>>8) & 0x0FF)) digits = 2; + else digits = 1; + if (4 == digits) floatstring[i++] = (d>>24) & 0x0FF; + if (3 <= digits) floatstring[i++] = (d>>16) & 0x0FF; + if (2 <= digits) floatstring[i++] = (d>>8) & 0x0FF; + floatstring[i++] = d & 0x0FF; + } + } + else + { + post("packxbee_pack_remote_frame parameter not symbol or float: ignoring"); + } + maxdigits = 32; /* the longest possible hex string is for the encryption key */ + /* we leave it up to the user to send the correct values */ + if (j != i) + { /* update the checksum */ + for (; ((j < maxdigits)&&(j < i)); ++j) + { + c = floatstring[j]; + if (0 == c) break; + checksum -= c; + } + } + } /* argc >= 5 */ + } /* argc >= 4 */ + else + { + error("packxbee_pack_remote_frame: not enough parameters"); + 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); + } + } +} + +static void packxbee_pack_frame(t_packxbee *x, t_symbol *s, int argc, t_atom *argv) +{ + int i, j, k, maxdigits, d; + char checksum = 0xFF; + unsigned char floatstring[256]; /* longer than the longest hex number with each character escaped plus the header and checksum overhead */ + int length = 0; + int usefloatstring = 0; + unsigned char c, digits; + long param; + t_float f; + + if (x->x_verbosity > 0) post("packxbee_AT s is %s, argc is %d", s->s_name, argc); + if (argc >= 1) + { + if (argv[0].a_type != A_SYMBOL) + { + post ("packxbee_AT: argument 1 must be an AT command"); + return; + } + if (x->x_verbosity > 0) post ("packxbee_AT: argument 1 is %s", argv[0].a_w.w_symbol->s_name); + if (2 != strlen(argv[0].a_w.w_symbol->s_name)) + { + post ("packxbee_AT: argument 1 must be a two-character AT command"); + return; + } + if (((argv[0].a_w.w_symbol->s_name[0] < 0x20) || (argv[0].a_w.w_symbol->s_name[0] > 0x7F)) + || ((argv[0].a_w.w_symbol->s_name[1] < 0x20) || (argv[0].a_w.w_symbol->s_name[1] > 0x7F))) + { + post ("packxbee_AT: argument 1 must be printable ascii"); + return; + } + i = 0; + floatstring[i++] = XFRAME; /* as usual */ + floatstring[i++] = 0; /* length MSB */ + floatstring[i++] = 0;/* length LSB */ + floatstring[i] = x->x_frameType; + checksum -= floatstring[i++]; + if (0 == x->x_frameID) x->x_frameID++; + floatstring[i] = x->x_frameID++; + checksum -= floatstring[i++]; + c = argv[0].a_w.w_symbol->s_name[0];/* the first character of the AT command */ + floatstring[i] = c; + checksum -= floatstring[i++]; + c = argv[0].a_w.w_symbol->s_name[1];/* the second character of the AT command */ + floatstring[i] = c; + checksum -= floatstring[i++]; + j = i; /* store i in j to see if anything gets added later and we need to update the checksum */ + /* parameters if any */ + if (argc >= 2) + { /* some parameters */ + if (argv[1].a_type == A_SYMBOL) + { + if (x->x_verbosity > 0) post("packxbee_AT symbol parameter %s", argv[1].a_w.w_symbol->s_name); + if (('0' == argv[1].a_w.w_symbol->s_name[0])&&(('x' == argv[1].a_w.w_symbol->s_name[1]))) + { /* this is a hexadecimal number: strip the "0x" and copy the rest to the buffer as ascii digits */ + i += sprintf(&floatstring[i], "%s", &argv[1].a_w.w_symbol->s_name[2]); + } + else // if ((0 == strncmp("NI", argv[0].a_w.w_symbol->s_name, 2))||(0 == strncmp("DN", argv[0].a_w.w_symbol->s_name, 2))) + { /* we hope it's just an ascii string for the NI command */ + for (k = 0; (k < 20); ++k) /* no more than 20 characters in a node identifier */ + { + c = argv[1].a_w.w_symbol->s_name[k]; + if (0 == c) break; +// checksum -= c; + floatstring[i++] = c; + } + } + } + else if (argv[1].a_type == A_FLOAT) + { + f = argv[1].a_w.w_float; + if (x->x_verbosity > 0) post("packxbee_AT float parameter %f", f); + d = ((unsigned int)f)&0x0FF; + if (f != d) + { + post ("packxbee_AT parameter not a positive integer from 0 to 255"); + } + else + { + // put the significant part of the raw value into floatstring in big endian order + if (0 != ((d>>24) & 0x0FF)) digits = 4; + else if (0 != ((d>>16) & 0x0FF)) digits = 3; + else if (0 != ((d>>8) & 0x0FF)) digits = 2; + else digits = 1; + if (4 == digits) floatstring[i++] = (d>>24) & 0x0FF; + if (3 <= digits) floatstring[i++] = (d>>16) & 0x0FF; + if (2 <= digits) floatstring[i++] = (d>>8) & 0x0FF; + floatstring[i++] = d & 0x0FF; + } + } + else + { + post("packxbee_AT parameter not symbol or float: ignoring"); + } + maxdigits = 32; /* the longest possible hex string is for the encryption key */ + /* we leave it up to the user to send the correct values */ + /* if anything was added to floatstring, calculate the checksum on it */ + /* update the checksum */ + if (j != i) + { + for (; ((j < maxdigits)&&(j < i)); ++j) + { + c = floatstring[j]; + if (0 == c) break; + checksum -= c; + } + } + } /* argc >= 2 */ + } /* argc >= 1 */ + 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); + } + } +} + +static void packxbee_free(t_packxbee *x) +{ + /* free any memory we allocated */ + /* stop any callbacks */ +} + +void packxbee_setup(void) +{ + packxbee_class = class_new(gensym("packxbee"), (t_newmethod)packxbee_new, + (t_method)packxbee_free, + sizeof(t_packxbee), 0, A_DEFFLOAT, 0); + class_addmethod(packxbee_class, (t_method)packxbee_AT, gensym("AT"), A_GIMME, 0); + 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_API, gensym("API"), A_DEFFLOAT, 0); + class_addmethod(packxbee_class, (t_method)packxbee_verbosity, gensym("verbosity"), A_DEFFLOAT, 0); +} + +/* fin packxbee.c*/ diff --git a/xbee/pdxbee.h b/xbee/pdxbee.h new file mode 100644 index 0000000..d3023c3 --- /dev/null +++ b/xbee/pdxbee.h @@ -0,0 +1,41 @@ +#ifndef _PDXBEE +#define _PDXBEE + +// MAX_XBEE_PACKET_LENGTH is around 80 +#define MAX_XBEE_PACKET_LENGTH 128 + +#define LENGTH_MSB_INDEX 1 /* offset in x_outbuf */ +#define LENGTH_LSB_INDEX 2 /* offset in x_outbuf */ +#define FRAME_TYPE_INDEX 3 /* offset in x_outbuf */ +#define FRAME_ID_INDEX 4 /* offset in x_outbuf */ +#define AT_COMMAND_INDEX 5 /* offset in x_outbuf */ +#define AT_PARAMETER_INDEX 6 /* offset in x_outbuf */ + +/* API Frame Names and Values */ + +#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 AT_Command_Response 0x88 +#define Modem_Status 0x8A +#define ZigBee_Transmit_Status 0x8B +#define ZigBee_Receive_Packet 0x90 +#define ZigBee_Explicit_Rx_Indicator 0x91 +#define ZigBee_IO_Data_Sample_Rx_Indicator 0x92 +#define XBee_Sensor_Read_Indicator 0x94 +#define Node_Identification_Indicator 0x95 +#define Remote_Command_Response 0x97 +#define Over_the_Air_Firmware_Update_Status 0xA0 +#define Route_Record_Indicator 0xA1 +#define Many_to_One_Route_Request_Indicator 0xA3 + +/* if API mode is 2 all characters after the first are escaped if they are one of */ +#define XFRAME 0x7E /* Frame Delimiter */ +#define XSCAPE 0x7D /* Escape */ +#define XON 0x11 /* XON */ +#define XOFF 0x13 /* XOFF */ +/* to escape the character prefix it with XSCAPE and XOR it with 0x20 */ +#endif /* _PDXBEE */ diff --git a/xbee/unpackxbee.c b/xbee/unpackxbee.c new file mode 100644 index 0000000..35f36e3 --- /dev/null +++ b/xbee/unpackxbee.c @@ -0,0 +1,452 @@ +/* unpackxbee outputs a list of floats which are the bytes making up an xbee api packet. */
+/* The packet can then be sent through [comport]. */
+/* 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 */
+
+#include <stdio.h>
+//#include <string.h>
+#include "m_pd.h"
+#include "pdxbee.h"
+
+static t_class *unpackxbee_class;
+
+
+typedef struct _unpackxbee
+{
+ t_object x_obj;
+ t_outlet *x_status_out;
+ t_outlet *x_payload_out;
+ int x_api_mode;
+ unsigned char x_frame_ID;
+ unsigned char x_frame_type;
+ unsigned int x_frame_length;
+ int x_verbosity;
+ unsigned char x_message[MAX_XBEE_PACKET_LENGTH];
+ int x_message_index;
+ int x_escaped;
+ t_atom x_outbuf[MAX_XBEE_PACKET_LENGTH];
+ t_atom x_statusbuf[32]; /* some number bigger than we will ever reach */
+} t_unpackxbee;
+
+static void *unpackxbee_new(t_floatarg f);
+static void unpackxbee_input(t_unpackxbee *x, t_symbol *s, int argc, t_atom *argv);
+static void unpackxbee_API(t_unpackxbee *x, t_float api);
+static void unpackxbee_verbosity(t_unpackxbee *x, t_float verbosity_level);
+static void unpackxbee_free(t_unpackxbee *x);
+void unpackxbee_setup(void);
+
+static void *unpackxbee_new(t_floatarg f)
+{
+ int i;
+
+ t_unpackxbee *x = (t_unpackxbee *)pd_new(unpackxbee_class);
+ if (x)
+ {
+ x->x_payload_out = outlet_new(&x->x_obj, &s_list); /* the first outlet on the left */
+ x->x_status_out = outlet_new(&x->x_obj, &s_list);
+
+ if (1 == f) x->x_api_mode = 1;
+ else x->x_api_mode = 2; /* default to escaped mode */
+ x->x_verbosity = 2; /* debug level */
+ for(i = 0; i < MAX_XBEE_PACKET_LENGTH; ++i) x->x_outbuf[i].a_type = A_FLOAT; /* init output atoms as floats */
+ }
+ return (x);
+}
+
+static void unpackxbee_API(t_unpackxbee *x, t_float api)
+{
+ if ((api == 1) || (api ==2)) x->x_api_mode = api;
+ else error ("unpackxbee: api mode must be 1 or 2");
+}
+
+static void unpackxbee_verbosity(t_unpackxbee *x, t_float verbosity_level)
+{
+ if (verbosity_level >= 0) x->x_verbosity = verbosity_level;
+ else error ("packxbee: verbosity_level must be positive");
+}
+
+int unpackxbee_add(t_unpackxbee *x, unsigned char d)
+{
+ if (XFRAME == d)
+ {
+ if (x->x_verbosity > 1) post ("frame start");
+ x->x_message_index = 0;
+ x->x_frame_length = 0;
+ x->x_frame_type = 0;
+ x->x_escaped = 0;
+ }
+ if (2 == x->x_api_mode)
+ {
+ if (XSCAPE == d)
+ {
+ x->x_escaped = 1; /* we need to xor the next character with 0x20 */
+ return 0; /* don't store the escape character */
+ }
+ else if (1 == x->x_escaped)
+ {
+ d ^= 0x20; /* xor with 0x20 to restore the original character */
+ x->x_escaped = 0; /* don't do it again */
+ }
+ }
+ if (LENGTH_LSB_INDEX == x->x_message_index) /* length is a bigendian pair */
+ {
+ x->x_frame_length = (x->x_message[LENGTH_MSB_INDEX]<<8) + d;
+ if (x->x_verbosity > 1) post ("frame length %d", x->x_frame_length);
+ }
+ else if (FRAME_TYPE_INDEX == x->x_message_index)
+ {
+ x->x_frame_type = d;
+ if (x->x_verbosity > 1) post ("frame type 0x%02X", x->x_frame_type);
+ }
+ else if (FRAME_ID_INDEX == x->x_message_index)
+ { /* this is part of the payload and may not be valid in some frame types */
+ x->x_frame_ID = d;
+ if (x->x_verbosity > 1) post ("frame ID %d", x->x_frame_ID);
+ }
+ x->x_message[x->x_message_index++] = d; /* add the unescaped character to the output list */
+ return 1;
+}
+
+static void unpackxbee_input(t_unpackxbee *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int i , j, k;
+ t_float f;
+ unsigned int d, checksum = 0;
+ unsigned char c;
+ t_symbol *type_selector;
+ int statuslength = 0, payloadstart = 0;
+ char atbuf[64];
+ unsigned char floatstring[256]; /* longer than the longest hex number with each character escaped plus the header and checksum overhead */
+ unsigned long long addr64;
+ unsigned int addr16;
+
+ if (x->x_verbosity > 1) post("unpackxbee_input: s is %s, argc is %d", s->s_name, argc);
+ for (i = 0; i < argc; ++i)
+ {
+ if (A_FLOAT == argv[i].a_type)
+ {
+ f = argv[i].a_w.w_float;
+ d = ((unsigned int)f)&0x0FF;
+ if (x->x_verbosity > 1) post("unpackxbee_input: argv[%d] is %f int is %d", i, f, d);
+ if (f != d)
+ {
+ post ("unpackxbee_input not a positive integer from 0 to 255");
+ }
+ else unpackxbee_add(x, d);
+ }
+ else
+ post("unpackxbee_input: item %d is not a float", i+1);
+ }
+ if ((x->x_frame_length > 0)&&(x->x_frame_length + 4 == x->x_message_index))
+ { /* end of frame reached */
+ k = x->x_frame_length+4; /* total packet length is payload + 1 start 2 length 1 checksum*/
+ if(x->x_verbosity > 1)
+ {
+ post("frame end");
+ for (j = 0; j < k; ++j)
+ {
+ c = x->x_message[j];
+ post("unpackxbee buf[%d]: %d [0x%02X]", j, c, c);
+ }
+ }
+ for (j = 3; j < k; ++j)
+ {
+ checksum += x->x_message[j];
+ }
+ checksum &= 0x0FF;
+ if (checksum != 0xFF)
+ {
+ post("unpackxbee: wrong checksum; dropping packet");
+ return;
+ }
+ if(x->x_verbosity > 1) post("unpackxbee checksum %d [0x%02X]", checksum, checksum);
+ switch(x->x_frame_type)
+ {
+ case AT_Command:
+ type_selector = gensym("AT_Command");
+ break;
+ case AT_Command_Queue_Parameter_Value:
+ type_selector = gensym("AT_Command_Queue_Parameter_Value");
+ break;
+ case ZigBee_Transmit_Request:
+ type_selector = gensym("ZigBee_Transmit_Request");
+ break;
+ case Explicit_Addressing_ZigBee_Command_Frame:
+ type_selector = gensym("Explicit_Addressing_ZigBee_Command_Frame");
+ break;
+ case Remote_Command_Request:
+ type_selector = gensym("Remote_Command_Request");
+ break;
+ case Create_Source_Route:
+ type_selector = gensym("Create_Source_Route");
+ break;
+ case AT_Command_Response:
+ type_selector = gensym("AT_Command_Response");
+ break;
+ case Modem_Status:
+ type_selector = gensym("Modem_Status");
+ break;
+ case ZigBee_Transmit_Status:
+ type_selector = gensym("ZigBee_Transmit_Status");
+ break;
+ case ZigBee_Receive_Packet:
+ type_selector = gensym("ZigBee_Receive_Packet");
+ break;
+ case ZigBee_Explicit_Rx_Indicator:
+ type_selector = gensym("ZigBee_Explicit_Rx_Indicator");
+ break;
+ case ZigBee_IO_Data_Sample_Rx_Indicator:
+ type_selector = gensym("ZigBee_IO_Data_Sample_Rx_Indicator");
+ break;
+ case XBee_Sensor_Read_Indicator:
+ type_selector = gensym("XBee_Sensor_Read_Indicator");
+ break;
+ case Node_Identification_Indicator:
+ type_selector = gensym("Node_Identification_Indicator");
+ break;
+ case Remote_Command_Response:
+ type_selector = gensym("Remote_Command_Response");
+ break;
+ case Over_the_Air_Firmware_Update_Status:
+ type_selector = gensym("Over_the_Air_Firmware_Update_Status");
+ break;
+ case Route_Record_Indicator:
+ type_selector = gensym("Route_Record_Indicator");
+ break;
+ case Many_to_One_Route_Request_Indicator:
+ type_selector = gensym("Many_to_One_Route_Request_Indicator");
+ break;
+ default:
+ type_selector = gensym("unknown");
+ }
+ statuslength = 0;
+ SETFLOAT(&x->x_statusbuf[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)
+ )
+ {
+ if (x->x_verbosity > 1)
+ post("AT_Command_Response AT_Command AT_Command_Queue_Parameter_Value statuslength %d", statuslength);
+ SETFLOAT(&x->x_statusbuf[statuslength], x->x_frame_ID);
+ statuslength++;
+ /* data doesn't include 1byte frame type 1byte ID 2byte AT command 1byte AT command status = 5bytes */
+ SETFLOAT(&x->x_statusbuf[statuslength], x->x_frame_length-5);
+ statuslength++;
+ atbuf[0] = x->x_message[5]; /* the AT command string */
+ atbuf[1] = x->x_message[6];
+ atbuf[2] = '\0';
+ SETSYMBOL(&x->x_statusbuf[statuslength], gensym(atbuf));
+ statuslength++;
+ SETFLOAT(&x->x_statusbuf[statuslength], x->x_message[7]);/* AT command status */
+ statuslength++;
+ if ((0 == x->x_message[7]) && ('N' == x->x_message[5]) && ('D' == x->x_message[6]))
+ { /* a succesful node discover response: output the addresses as symbols */
+/*
+buf[0]: 126 [0x7E] ND packet start
+buf[1]: 0 [0x00] Length MSB
+buf[2]: 25 [0x19] Length LSB
+buf[3]: 136 [0x88] AT response
+buf[4]: 5 [0x05] packet ID
+buf[5]: 78 [0x4E] N
+buf[6]: 68 [0x44] D
+buf[7]: 0 [0x00] status
+*/
+ addr16 = (x->x_message[8]<<8) + x->x_message[9];
+ sprintf(floatstring, "0x%X", addr16);
+ SETSYMBOL(&x->x_statusbuf[statuslength], gensym(floatstring));
+ statuslength++;
+/*
+buf[8]: 121 [0x79] MY
+buf[9]: 214 [0xD6]
+*/
+/* now switch endianness */
+
+ addr64 = x->x_message[10];
+ addr64 <<= 8;
+ addr64 |= x->x_message[11];
+ addr64 <<= 8;
+ addr64 |= x->x_message[12];
+ addr64 <<= 8;
+ addr64 |= x->x_message[13];
+ addr64 <<= 8;
+ addr64 |= x->x_message[14];
+ addr64 <<= 8;
+ addr64 |= x->x_message[15];
+ addr64 <<= 8;
+ addr64 |= x->x_message[16];
+ addr64 <<= 8;
+ addr64 |= x->x_message[17];
+ sprintf(floatstring, "0x%I64X", addr64);
+ SETSYMBOL(&x->x_statusbuf[statuslength], gensym(floatstring)); /* addr64 */
+ statuslength++;
+/*
+buf[10]: 0 [0x00] SH
+buf[11]: 19 [0x13]
+buf[12]: 162 [0xA2]
+buf[13]: 0 [0x00]
+buf[14]: 64 [0x40] SL
+buf[15]: 106 [0x6A]
+buf[16]: 222 [0xDE]
+buf[17]: 30 [0x1E]
+*/
+ for (j = 0, i = 18; i < k; ++i, ++j)
+ {
+ floatstring[j] = x->x_message[i];
+ if (0 == floatstring[j])
+ {
+ i++;
+ break;/* Node Identifier should be a null-terminated ascii string */
+ }
+ }
+ SETSYMBOL(&x->x_statusbuf[statuslength], gensym(floatstring)); /* Node Identifier */
+ statuslength++;
+/*
+buf[18]: 32 [0x20] NI
+buf[19]: 0 [0x00]
+*/
+ addr16 = (x->x_message[i]<<8) + x->x_message[i+1];
+ sprintf(floatstring, "0x%X", addr16);
+ i += 2;
+ SETSYMBOL(&x->x_statusbuf[statuslength], gensym(floatstring)); /* parent addr16 */
+ statuslength++;
+/*
+buf[20]: 255 [0xFF] parent
+buf[21]: 254 [0xFE]
+*/
+ SETFLOAT(&x->x_statusbuf[statuslength], x->x_message[i++]);/* Device Type */
+ statuslength++;
+/*
+buf[22]: 1 [0x01] device type
+*/
+ SETFLOAT(&x->x_statusbuf[statuslength], x->x_message[i++]);/* Source Event */
+ statuslength++;
+/*
+buf[23]: 0 [0x00] source event
+*/
+ addr16 = x->x_message[i++]<<8;
+ addr16 |= x->x_message[i++];
+ sprintf(floatstring, "0x%X", addr16);
+ SETSYMBOL(&x->x_statusbuf[statuslength], gensym(floatstring)); /* Profile ID */
+ statuslength++;
+/*
+buf[24]: 193 [0xC1] Profile ID
+buf[25]: 5 [0x05]
+*/
+ addr16 = (x->x_message[i]<<8) + x->x_message[i+1];
+ sprintf(floatstring, "0x%X", addr16);
+ i += 2;
+ SETSYMBOL(&x->x_statusbuf[statuslength], gensym(floatstring)); /* Manufacturer ID */
+ statuslength++;
+/*
+buf[26]: 16 [0x10] Manufacturer ID
+buf[27]: 30 [0x1E]
+*/
+
+/*
+buf[28]: 36 [0x24] checksum
+*/
+ payloadstart = 0;/* no payload */
+ }
+ else
+ {
+ payloadstart = 8;
+ }
+ }
+ else if (ZigBee_Transmit_Status == x->x_frame_type)
+ {
+ if (x->x_verbosity > 1)
+ post("ZigBee_Transmit_Status statuslength %d", statuslength);
+ SETFLOAT(&x->x_statusbuf[statuslength], x->x_frame_ID);
+ statuslength++;
+ sprintf(atbuf, "0x%X", (x->x_message[5]<<8) + x->x_message[6]); /* the 16-bit address as a symbol */
+ SETSYMBOL(&x->x_statusbuf[statuslength], gensym(atbuf));
+ statuslength++;
+ SETFLOAT(&x->x_statusbuf[statuslength], x->x_message[7]);/* Transmit Retry Count */
+ statuslength++;
+ SETFLOAT(&x->x_statusbuf[statuslength], x->x_message[8]);/* Delivery Status */
+ statuslength++;
+ SETFLOAT(&x->x_statusbuf[statuslength], x->x_message[9]);/* Discovery Status */
+ statuslength++;
+ payloadstart = 0; /* no payload */
+ }
+ else if (ZigBee_Receive_Packet == x->x_frame_type)
+ {
+ if (x->x_verbosity > 1)
+ post("ZigBee_Receive_Packet statuslength %d", statuslength);
+ /* data doesn't include 1byte frametype, 8byte addr64, 2byte addr16, 1byte options = 12bytes*/
+ SETFLOAT(&x->x_statusbuf[statuslength], x->x_frame_length-12);
+ 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++];
+ sprintf(floatstring, "0x%I64X", addr64);
+ SETSYMBOL(&x->x_statusbuf[statuslength], gensym(floatstring)); /* addr64 */
+ statuslength++;
+ /* 16-bit source address */
+ addr16 = x->x_message[i++]<<8;
+ addr16 |= x->x_message[i++];
+ sprintf(floatstring, "0x%X", addr16);
+ SETSYMBOL(&x->x_statusbuf[statuslength], gensym(floatstring)); /* addr16 */
+ statuslength++;
+ /* receive options byte */
+ SETFLOAT(&x->x_statusbuf[statuslength], x->x_message[i++]);/* 1 2 32 64 */
+ statuslength++;
+ /* data */
+ payloadstart = i;
+ }
+ else
+ {
+ if (x->x_verbosity > 1)
+ post("some other packet statuslength %d", statuslength);
+ SETFLOAT(&x->x_statusbuf[statuslength], x->x_frame_ID);/* may not be valid */
+ statuslength++;
+ SETFLOAT(&x->x_statusbuf[statuslength], x->x_frame_length-2);/* payload doesn't include frame type and ID */
+ statuslength++;
+ payloadstart = 5;
+ }
+ outlet_anything(x->x_status_out, type_selector, statuslength, x->x_statusbuf);
+ if (payloadstart > 0)
+ {
+ for (j = 0, i = payloadstart; i < k-1; ++j, ++i)
+ SETFLOAT(&x->x_outbuf[j], x->x_message[i]); /* the payload */
+ if (j > 0)
+ outlet_list(x->x_payload_out, &s_list, j, x->x_outbuf);
+ }
+ }
+}
+
+static void unpackxbee_free(t_unpackxbee *x)
+{
+}
+
+void unpackxbee_setup(void)
+{
+ unpackxbee_class = class_new(gensym("unpackxbee"), (t_newmethod)unpackxbee_new,
+ (t_method)unpackxbee_free,
+ sizeof(t_unpackxbee), 0, A_DEFFLOAT, 0);
+ class_addanything(unpackxbee_class, (t_method)unpackxbee_input);
+ class_addmethod(unpackxbee_class, (t_method)unpackxbee_API, gensym("API"), A_DEFFLOAT, 0);
+ class_addmethod(unpackxbee_class, (t_method)unpackxbee_verbosity, gensym("verbosity"), A_DEFFLOAT, 0);
+}
+
+/* fin unpackxbee.c*/
|