IEEE 802.15.4 subsystem
Sign in or create your account | Project List | Help
IEEE 802.15.4 subsystem Commit Details
Date: | 2011-01-20 19:23:56 (13 years 2 months ago) |
---|---|
Author: | Werner Almesberger |
Commit: | f16224f57583d3cc1d910a6ebc572b93384f4893 |
Message: | atrf-txrx: new option -P to select ping mode - atrf-txrx.c (struct ping, enum rx_res, ping_tx, ping_rx, ping): send back a packet containing a locally generated sequence number and the last sequence number received whenever a packet arrives - atrf-txrx.c (usage, main): added option -P to select ping mode |
Files: |
tools/atrf-txrx/atrf-txrx.c (11 diffs) |
Change Details
tools/atrf-txrx/atrf-txrx.c | ||
---|---|---|
44 | 44 | #define DEFAULT_POWER -3.2 /* transmit power, dBm */ |
45 | 45 | |
46 | 46 | |
47 | struct ping { | |
48 | uint32_t seq; /* sequence number from originator, > 0 */ | |
49 | uint32_t ack; /* last sequence number received, 0 if none */ | |
50 | uint8_t pad[117]; /* pad to 127 bytes */ | |
51 | uint16_t crc; | |
52 | } __attribute__((__packed__)); | |
53 | ||
54 | enum rx_res { | |
55 | rx_exit, | |
56 | rx_good, | |
57 | rx_bad, | |
58 | rx_timeout, | |
59 | }; | |
60 | ||
61 | ||
47 | 62 | static double tx_pwr_230[] = { |
48 | 63 | 3.0, 2.6, 2.1, 1.6, |
49 | 64 | 1.1, 0.5, -0.2, -1.2, |
... | ... | |
409 | 424 | } |
410 | 425 | |
411 | 426 | |
427 | static void ping_tx(struct atrf_dsc *dsc, const struct ping *pck) | |
428 | { | |
429 | atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_PLL_ON); | |
430 | /* | |
431 | * 180 us, according to AVR2001 section 4.3. We time out after | |
432 | * nominally 200 us. | |
433 | */ | |
434 | wait_for_interrupt(dsc, IRQ_PLL_LOCK, IRQ_PLL_LOCK, 10, 20); | |
435 | ||
436 | atrf_buf_write(dsc, pck, sizeof(*pck)); | |
437 | atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TX_START); | |
438 | ||
439 | /* wait up to 10 ms (nominally) */ | |
440 | wait_for_interrupt(dsc, IRQ_TRX_END, | |
441 | IRQ_TRX_END | IRQ_PLL_LOCK, 10, 1000); | |
442 | } | |
443 | ||
444 | ||
445 | static enum rx_res ping_rx(struct atrf_dsc *dsc, struct ping *pck, int wait_ds) | |
446 | { | |
447 | uint8_t irq; | |
448 | int n; | |
449 | ||
450 | atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_RX_ON); | |
451 | irq = wait_for_interrupt(dsc, IRQ_TRX_END, | |
452 | IRQ_TRX_END | IRQ_RX_START | IRQ_PLL_LOCK, | |
453 | 100000, wait_ds); | |
454 | if (!run) | |
455 | return rx_exit; | |
456 | if (!irq) | |
457 | return rx_timeout; | |
458 | ||
459 | n = atrf_buf_read(dsc, pck, sizeof(*pck)); | |
460 | if (n < 0) | |
461 | exit(1); | |
462 | if (n != sizeof(*pck)) { | |
463 | fprintf(stderr, "%d bytes received\n", n); | |
464 | return rx_bad; | |
465 | } | |
466 | return atrf_reg_read(dsc, REG_PHY_RSSI) & RX_CRC_VALID ? | |
467 | rx_good : rx_bad; | |
468 | } | |
469 | ||
470 | ||
471 | static void ping(struct atrf_dsc *dsc, double max_wait_s, int master) | |
472 | { | |
473 | static int first = 1; | |
474 | struct ping tx_pck = { | |
475 | .seq = 0, | |
476 | .ack = 0, | |
477 | }; | |
478 | struct ping rx_pck; | |
479 | enum rx_res res; | |
480 | ||
481 | while (run) { | |
482 | tx_pck.seq++; | |
483 | if (master || !first) { | |
484 | ping_tx(dsc, &tx_pck); | |
485 | if (!run) | |
486 | break; | |
487 | } | |
488 | first = 0; | |
489 | res = ping_rx(dsc, &rx_pck, master ? max_wait_s*10 : 0); | |
490 | switch (res) { | |
491 | case rx_good: | |
492 | tx_pck.ack = rx_pck.seq; | |
493 | if (tx_pck.seq == rx_pck.ack) | |
494 | write(2, ".", 1); | |
495 | else | |
496 | write(2, "*", 1); | |
497 | break; | |
498 | case rx_bad: | |
499 | write(2, "-", 1); | |
500 | break; | |
501 | case rx_timeout: | |
502 | write(2, "+", 1); | |
503 | break; | |
504 | case rx_exit: | |
505 | return; | |
506 | default: | |
507 | abort(); | |
508 | } | |
509 | } | |
510 | } | |
511 | ||
512 | ||
412 | 513 | static int test_mode(struct atrf_dsc *dsc, uint8_t cont_tx, const char *cmd) |
413 | 514 | { |
414 | 515 | int status = 0; |
... | ... | |
451 | 552 | fprintf(stderr, |
452 | 553 | "usage: %s [common_options] [message [repetitions]]\n" |
453 | 554 | " %s [common_options] -E pause_s [repetitions]\n" |
555 | " %s [common_options] -P [max_wait_s]\n" | |
454 | 556 | " %s [common_options] -T offset [command]\n\n" |
455 | 557 | " text message mode:\n" |
456 | 558 | " message message string to send (if absent, receive)\n" |
... | ... | |
458 | 560 | " PER test mode (transmit only):\n" |
459 | 561 | " -E pause_s seconds to pause between frames (floating-point)\n" |
460 | 562 | " repetitions number of messages to send (default: infinite)\n\n" |
563 | " Ping-pong mode:\n" | |
564 | " -P exchange packets between two stations\n" | |
565 | " max_wait_s generate a new packet if no response is received (master)\n\n" | |
461 | 566 | " constant wave test mode (transmit only):\n" |
462 | 567 | " -T offset test mode. offset is the frequency offset of the constant\n" |
463 | 568 | " wave in MHz: -2, -0.5, or +0.5\n" |
... | ... | |
471 | 576 | " -o file write received data to a file in pcap format\n" |
472 | 577 | " -p power transmit power, -17.2 to 3.0 dBm (default %.1f)\n" |
473 | 578 | " -t trim trim capacitor, 0 to 15 (default 0)\n" |
474 | , name, name, name, DEFAULT_CHANNEL, 2405+5*(DEFAULT_CHANNEL-11), | |
475 | DEFAULT_POWER); | |
579 | , name, name, name, name, | |
580 | DEFAULT_CHANNEL, 2405+5*(DEFAULT_CHANNEL-11), DEFAULT_POWER); | |
476 | 581 | exit(1); |
477 | 582 | } |
478 | 583 | |
... | ... | |
482 | 587 | enum { |
483 | 588 | mode_msg, |
484 | 589 | mode_per, |
590 | mode_ping, | |
485 | 591 | mode_cont_tx, |
486 | 592 | } mode = mode_msg; |
487 | 593 | int channel = DEFAULT_CHANNEL; |
... | ... | |
496 | 602 | const char *pcap_file = NULL; |
497 | 603 | struct atrf_dsc *dsc; |
498 | 604 | |
499 | while ((c = getopt(argc, argv, "c:C:f:o:p:E:t:T:")) != EOF) | |
605 | while ((c = getopt(argc, argv, "c:C:f:o:p:E:Pt:T:")) != EOF) | |
500 | 606 | switch (c) { |
501 | 607 | case 'c': |
502 | 608 | channel = strtoul(optarg, &end, 0); |
... | ... | |
547 | 653 | if (*end) |
548 | 654 | usage(*argv); |
549 | 655 | break; |
656 | case 'P': | |
657 | mode = mode_ping; | |
658 | break; | |
550 | 659 | case 'T': |
551 | 660 | mode = mode_cont_tx; |
552 | 661 | if (!strcmp(optarg, "-2")) |
... | ... | |
576 | 685 | set_power(dsc, power, 0); |
577 | 686 | transmit_pattern(dsc, pause_s, 0); |
578 | 687 | break; |
688 | case mode_ping: | |
689 | set_power(dsc, power, 1); | |
690 | ping(dsc, pause_s, 0); | |
691 | break; | |
579 | 692 | case mode_cont_tx: |
580 | 693 | set_power(dsc, power, 0); |
581 | 694 | status = test_mode(dsc, cont_tx, NULL); |
... | ... | |
589 | 702 | case mode_msg: |
590 | 703 | break; |
591 | 704 | case mode_per: |
705 | case mode_ping: | |
592 | 706 | /* fall through */ |
593 | 707 | case mode_cont_tx: |
594 | 708 | usage(*argv); |
... | ... | |
614 | 728 | set_power(dsc, power, 0); |
615 | 729 | transmit_pattern(dsc, pause_s, times); |
616 | 730 | break; |
731 | case mode_ping: | |
732 | pause_s = strtof(argv[optind], &end); | |
733 | if (*end) | |
734 | usage(*argv); | |
735 | set_power(dsc, power, 1); | |
736 | ping(dsc, pause_s, 1); | |
737 | break; | |
617 | 738 | case mode_cont_tx: |
618 | 739 | set_power(dsc, power, 0); |
619 | 740 | status = test_mode(dsc, cont_tx, argv[optind]); |