Root/tools/atrf-txrx/atrf-txrx.c

Source at commit 624caeb00652f6118dc64698b7dad6fa3e5bdcc2 created 2 years 8 months ago.
By Werner Almesberger, atusb/: use VR, POWERED, and LED from kicad-libs
1/*
2 * atrf-txrx/atrf-txrx.c - ben-wpan AT86RF230 TX/RX
3 *
4 * Written 2010-2011, 2013 by Werner Almesberger
5 * Copyright 2010-2011, 2013 Werner Almesberger
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13
14#include <stdbool.h>
15#include <stdint.h>
16#include <stdlib.h>
17#include <stdio.h>
18#include <unistd.h>
19#include <string.h>
20#include <math.h>
21#include <signal.h>
22#include <sys/wait.h>
23#include <sys/time.h>
24
25#include "at86rf230.h"
26#include "atrf.h"
27#include "misctxrx.h"
28#include "cwtest.h"
29
30#include "pcap.h"
31
32
33/*
34 * According to IEEE 802.15.4-2003 section E.2.6, channel 15 is the only
35 * channel that falls into the 802.11 guard bands in North America an Europe.
36 */
37
38#define DEFAULT_CHANNEL 15 /* channel 15, 2425 MHz */
39
40#define DEFAULT_TRIM 8 /* trim range is 0-15, see also ECN0002 */
41
42
43/*
44 * Transmit power, dBm. IEEE 802.15.4-2003 section E.3.1.3 specifies a transmit
45 * power of 0 dBm for IEEE 802.15.4. We assume an antenna gain of 3 dB or
46 * better.
47 */
48
49#define DEFAULT_POWER -3.2 /* transmit power, dBm */
50
51
52struct ping {
53    uint32_t seq; /* sequence number from originator, > 0 */
54    uint32_t ack; /* last sequence number received, 0 if none */
55    uint8_t pad[117]; /* pad to 127 bytes */
56    uint16_t crc;
57} __attribute__((__packed__));
58
59enum rx_res {
60    rx_exit,
61    rx_good,
62    rx_bad,
63    rx_timeout,
64};
65
66enum mode {
67    mode_msg,
68    mode_hmac,
69    mode_per,
70    mode_ping,
71    mode_rtt,
72    mode_rtt_hmac,
73    mode_cont_tx,
74};
75
76
77static volatile int run = 1;
78static bool quick = 0;
79
80
81/* ----- Helper functions -------------------------------------------------- */
82
83
84/*
85 * mhz: 0 disable CLKM
86 * >0 output specified clock
87 */
88
89static struct atrf_dsc *init_txrx(const char *driver, int trim, unsigned mhz)
90{
91    struct atrf_dsc *dsc;
92
93    dsc = atrf_open(driver);
94    if (!dsc)
95        exit(1);
96    
97    atrf_reset_rf(dsc);
98    atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TRX_OFF);
99
100#if 1 // def HAVE_USB /* @@@ yeah, ugly */
101    atrf_reg_write(dsc, REG_XOSC_CTRL,
102        (XTAL_MODE_INT << XTAL_MODE_SHIFT) | trim);
103#else
104    atrf_reg_write(dsc, REG_XOSC_CTRL, XTAL_MODE_EXT << XTAL_MODE_SHIFT);
105#endif
106
107    if (!atrf_set_clkm(dsc, mhz))
108        if (mhz) {
109            atrf_close(dsc);
110            exit(1);
111        }
112
113    /* We want to see all interrupts, not only the ones we're expecting. */
114    atrf_reg_write(dsc, REG_IRQ_MASK, 0xff);
115
116    flush_interrupts(dsc);
117    if (atrf_identify(dsc) == atrf_at86rf231)
118        wait_for_interrupt(dsc, IRQ_CCA_ED_DONE, IRQ_CCA_ED_DONE, 1);
119            /* according to table 7-1, 37 us max */
120
121    return dsc;
122}
123
124
125static void set_channel(struct atrf_dsc *dsc, int channel)
126{
127    atrf_reg_write(dsc, REG_PHY_CC_CCA, (1 << CCA_MODE_SHIFT) | channel);
128}
129
130
131static void set_rate(struct atrf_dsc *dsc, uint8_t rate)
132{
133    if (!rate)
134        return;
135    switch (atrf_identify(dsc)) {
136    case atrf_at86rf230:
137        fprintf(stderr, "AT86RF230 only supports 250 kbps\n");
138        break;
139    case atrf_at86rf231:
140        atrf_reg_write(dsc, REG_TRX_CTRL_2, rate);
141        break;
142    default:
143        abort();
144    }
145}
146
147
148/* ----- Message transmit/receive ------------------------------------------ */
149
150
151static void receive_message(struct atrf_dsc *dsc, int hex)
152{
153    uint8_t buf[MAX_PSDU+1]; /* PSDU+LQI */
154    int n, ok, i;
155    uint8_t ed, lqi;
156
157    fprintf(stderr, "Ready.\n");
158    wait_for_interrupt(dsc, IRQ_TRX_END,
159        IRQ_TRX_END | IRQ_RX_START | IRQ_AMI, 0);
160    if (!run)
161        return;
162
163    n = atrf_buf_read(dsc, buf, sizeof(buf));
164    if (n < 0)
165        exit(1);
166    if (n < 3) {
167        fprintf(stderr, "%d bytes received\n", n);
168        exit(1);
169    }
170    ed = atrf_reg_read(dsc, REG_PHY_ED_LEVEL);
171    ok = !!(atrf_reg_read(dsc, REG_PHY_RSSI) & RX_CRC_VALID);
172    lqi = buf[n-1];
173    fprintf(stderr, "%d bytes payload, CRC %s, LQI %u, ED %d dBm\n",
174        n-3, ok ? "OK" : "BAD", lqi, -91+ed);
175    if (hex) {
176        for (i = 0; i != n-3; i++)
177            printf("%s%02x", i ? " " : "", buf[i]);
178    } else {
179        for (i = 0; i != n-3; i++)
180            putchar(buf[i] < ' ' || buf[i] > '~' ? '?' : buf[i]);
181    }
182    putchar('\n');
183}
184
185
186static void write_pcap_hdr(FILE *file)
187{
188    struct pcap_file_header hdr = {
189        .magic = PCAP_FILE_MAGIC,
190        .version_major = 2,
191        .version_minor = 4,
192        .thiszone = 0,
193        .sigfigs = 0,
194        .snaplen = MAX_PSDU,
195        .linktype = DLT_IEEE802_15_4
196    };
197
198    if (fwrite(&hdr, sizeof(hdr), 1, file) != 1) {
199        perror("fwrite");
200        exit(1);
201    }
202}
203
204
205static void write_pcap_rec(FILE *file, const struct timeval *tv,
206    const void *buf, int n)
207{
208    struct pcap_pkthdr hdr = {
209        .ts_sec = tv->tv_sec,
210        .ts_usec = tv->tv_usec,
211        .caplen = n,
212        .len = n
213    };
214
215    if (fwrite(&hdr, sizeof(hdr), 1, file) != 1) {
216        perror("fwrite");
217        exit(1);
218    }
219    if (fwrite(buf, n, 1, file) != 1) {
220        perror("fwrite");
221        exit(1);
222    }
223}
224
225
226static void receive_pcap(struct atrf_dsc *dsc, const char *name)
227{
228    FILE *file;
229    uint8_t buf[MAX_PSDU+1]; /* PSDU+LQI */
230    struct timeval now;
231    int n;
232    int count = 0;
233
234    file = fopen(name, "w");
235    if (!file) {
236        perror(name);
237        exit(1);
238    }
239    write_pcap_hdr(file);
240    while (run) {
241        wait_for_interrupt(dsc,
242            IRQ_TRX_END,
243            quick ? 0xff : IRQ_TRX_END | IRQ_RX_START | IRQ_AMI,
244            quick ? -1 : 0);
245        if (!run)
246            break;
247        gettimeofday(&now, NULL);
248        n = atrf_buf_read(dsc, buf, sizeof(buf));
249        if (n < 0)
250            exit(1);
251        if (n < 2) {
252            fprintf(stderr, "%d bytes received\n", n);
253            continue;
254        }
255        write_pcap_rec(file, &now, buf, n-1);
256        if (!quick)
257            (void) write(2, ".", 1);
258        count++;
259    }
260    if (fclose(file) == EOF) {
261        perror(name);
262        exit(1);
263    }
264    fprintf(stderr, "%sreceived %d message%s\n", count ? "\n" : "",
265        count, count == 1 ? "" : "s");
266}
267
268
269static void receive(struct atrf_dsc *dsc, const char *name, int hex)
270{
271    atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_RX_ON);
272    /*
273     * 180 us, according to AVR2001 section 4.2. We time out after
274     * nominally 200 us.
275     */
276    wait_for_interrupt(dsc, IRQ_PLL_LOCK, IRQ_PLL_LOCK, 1);
277
278    if (name)
279        receive_pcap(dsc, name);
280    else
281        receive_message(dsc, hex);
282}
283
284
285static int dehex(uint8_t *buf, const char *s)
286{
287    uint8_t *p;
288    int nibbles = 0;
289    uint8_t v = 0, nibble;
290    char cvt[2] = "?";
291    char *end;
292
293    for (p = buf; *s; s++) {
294        if (strchr(" \t,.:-", *s)) {
295            if (nibbles)
296                *p++ = v;
297            nibbles = 0;
298            continue;
299        }
300        cvt[0] = *s;
301        nibble = strtoul(cvt, &end, 16);
302        if (*end) {
303            fprintf(stderr, "invalid hex character \"%c\"\n", *s);
304            exit(1);
305        }
306        if (nibbles) {
307            *p++ = v << 4 | nibble;
308            nibbles = 0;
309        } else {
310            v = nibble;
311            nibbles++;
312        }
313    }
314    if (nibbles)
315        *p++ = v;
316    return p-buf;
317}
318
319
320static void transmit(struct atrf_dsc *dsc, const char *msg, int hex, int times)
321{
322    uint8_t buf[MAX_PSDU];
323    int len;
324
325    atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_PLL_ON);
326    /*
327     * 180 us, according to AVR2001 section 4.3. We time out after
328     * nominally 200 us.
329     */
330    wait_for_interrupt(dsc, IRQ_PLL_LOCK, IRQ_PLL_LOCK, 1);
331
332    /*
333     * We need to copy the message to append the CRC placeholders.
334     */
335    if (hex) {
336        len = dehex(buf, msg);
337    } else {
338        strcpy((void *) buf, msg);
339        len = strlen(msg);
340    }
341    atrf_buf_write(dsc, buf, len+2);
342
343    while (run && times--) {
344        /* @@@ should wait for clear channel */
345        atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TX_START);
346
347        /* wait up to 10 ms (nominally) */
348        wait_for_interrupt(dsc, IRQ_TRX_END,
349           IRQ_TRX_END | IRQ_PLL_LOCK, 10);
350    }
351}
352
353
354static void receive_hmac(struct atrf_dsc *dsc)
355{
356    uint8_t buf[MAX_PSDU];
357    uint8_t lqi;
358    int n, i;
359
360    atrf_rx_mode(dsc, 1);
361    n = atrf_rx(dsc, buf, sizeof(buf), 0, &lqi);
362    atrf_rx_mode(dsc, 0);
363
364    if (n < 2) {
365        fprintf(stderr, "%d bytes received\n", n);
366        exit(1);
367    }
368    for (i = 0; i != n-2; i++)
369        putchar(buf[i] < ' ' || buf[i] > '~' ? '?' : buf[i]);
370    putchar('\n');
371}
372
373
374static void transmit_hmac(struct atrf_dsc *dsc, const char *msg)
375{
376    atrf_rx_mode(dsc, 1);
377    atrf_tx(dsc, msg, strlen(msg));
378    atrf_rx_mode(dsc, 0);
379}
380
381
382/* ----- PER test ---------------------------------------------------------- */
383
384
385static void transmit_pattern(struct atrf_dsc *dsc, double pause_s, int times)
386{
387    uint8_t buf[MAX_PSDU];
388    uint8_t n = 0;
389    int us = fmod(pause_s, 1)*1000000;
390
391    atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_PLL_ON);
392    /*
393     * 180 us, according to AVR2001 section 4.3. We time out after
394     * nominally 200 us.
395     */
396    wait_for_interrupt(dsc, IRQ_PLL_LOCK, IRQ_PLL_LOCK, 1);
397
398    while (run) {
399        memset(buf, n, sizeof(buf));
400        atrf_buf_write(dsc, buf, sizeof(buf));
401
402        atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TX_START);
403
404        /* wait up to 10 ms (nominally) */
405        wait_for_interrupt(dsc, IRQ_TRX_END,
406           IRQ_TRX_END | IRQ_PLL_LOCK, 10);
407
408        if (pause_s >= 1)
409            sleep(pause_s);
410        if (us)
411            usleep(us);
412
413        if (times && !--times)
414            break;
415        n++;
416    }
417}
418
419
420/* ----- Ping -------------------------------------------------------------- */
421
422
423static void ping_tx(struct atrf_dsc *dsc, const struct ping *pck)
424{
425    atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_PLL_ON);
426    /*
427     * 180 us, according to AVR2001 section 4.3. We time out after
428     * nominally 200 us.
429     */
430    wait_for_interrupt(dsc, IRQ_PLL_LOCK, IRQ_PLL_LOCK, 1);
431
432    atrf_buf_write(dsc, pck, sizeof(*pck));
433    atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TX_START);
434
435    /* wait up to 10 ms (nominally) */
436    wait_for_interrupt(dsc, IRQ_TRX_END,
437       IRQ_TRX_END | IRQ_PLL_LOCK, 10);
438}
439
440
441static enum rx_res ping_rx(struct atrf_dsc *dsc, struct ping *pck, int wait_ms)
442{
443    uint8_t irq;
444    int n;
445
446    atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_RX_ON);
447    irq = wait_for_interrupt(dsc, IRQ_TRX_END,
448        IRQ_TRX_END | IRQ_RX_START | IRQ_PLL_LOCK, wait_ms);
449    if (!run)
450        return rx_exit;
451    if (!irq)
452        return rx_timeout;
453
454    n = atrf_buf_read(dsc, pck, sizeof(*pck));
455    if (n < 0)
456        exit(1);
457    if (n != sizeof(*pck)) {
458        fprintf(stderr, "%d bytes received\n", n);
459        return rx_bad;
460    }
461    return atrf_reg_read(dsc, REG_PHY_RSSI) & RX_CRC_VALID ?
462        rx_good : rx_bad;
463}
464
465
466static void ping(struct atrf_dsc *dsc, double max_wait_s, int master)
467{
468    static int first = 1;
469    struct ping tx_pck = {
470        .seq = 0,
471        .ack = 0,
472    };
473    struct ping rx_pck;
474    enum rx_res res;
475
476    while (run) {
477        tx_pck.seq++;
478        if (master || !first) {
479            ping_tx(dsc, &tx_pck);
480            if (!run)
481                break;
482        }
483        first = 0;
484        res = ping_rx(dsc, &rx_pck, master ? max_wait_s*1000 : 0);
485        switch (res) {
486        case rx_good:
487            tx_pck.ack = rx_pck.seq;
488            if (tx_pck.seq == rx_pck.ack)
489                write(2, ".", 1);
490            else
491                write(2, "*", 1);
492            break;
493        case rx_bad:
494            write(2, "-", 1);
495            break;
496        case rx_timeout:
497            write(2, "+", 1);
498            break;
499        case rx_exit:
500            return;
501        default:
502            abort();
503        }
504    }
505}
506
507
508/* ----- Round-trip time --------------------------------------------------- */
509
510
511static void rtt_slave(struct atrf_dsc *dsc)
512{
513    uint8_t buf[MAX_PSDU];
514    int n;
515
516    while (run) {
517        atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_RX_ON);
518        wait_for_interrupt(dsc, IRQ_TRX_END,
519            IRQ_TRX_END | IRQ_RX_START | IRQ_PLL_LOCK | IRQ_AMI, 0);
520        if (!run)
521            break;
522        n = atrf_buf_read(dsc, buf, sizeof(buf));
523        if (n < 0)
524            exit(1);
525        if (n < 2) {
526            fprintf(stderr, "%d bytes received\n", n);
527            continue;
528        }
529        atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_PLL_ON);
530        atrf_buf_write(dsc, buf, n);
531        atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TX_START);
532        wait_for_interrupt(dsc, IRQ_TRX_END,
533            IRQ_TRX_END | IRQ_PLL_LOCK, 10);
534    }
535}
536
537
538static void rtt_slave_hmac(struct atrf_dsc *dsc)
539{
540    uint8_t buf[MAX_PSDU];
541    int n;
542
543    atrf_rx_mode(dsc, 1);
544    while (run) {
545        n = atrf_rx(dsc, buf, sizeof(buf), 0, NULL);
546        if (n < 0)
547            exit(1);
548        atrf_tx(dsc, buf, n-2);
549    }
550    atrf_rx_mode(dsc, 0);
551}
552
553
554static void rtt_master(struct atrf_dsc *dsc, int packets, int size)
555{
556    uint8_t buf[size+2]; /* +CRC */
557    struct timeval t0, t1;
558    uint8_t irq;
559    int first = 1;
560    double min = 0, max = 0, sum = 0, sum2 = 0, d;
561    int lost = 0, n;
562    int i;
563
564    memset(buf, 0, size+2);
565    for (i = 0; i != packets; i++) {
566        atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_PLL_ON);
567        atrf_buf_write(dsc, buf, size+2);
568        gettimeofday(&t0, NULL);
569        atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TX_START);
570
571        /* prepare transition to RX_ON while still sending */
572        while ((atrf_reg_read(dsc, REG_TRX_STATUS) & TRX_STATUS_MASK)
573                   == TRX_STATUS_TRANSITION);
574        atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_RX_ON);
575
576        /* wait for transmission to end */
577        wait_for_interrupt(dsc, IRQ_TRX_END,
578            IRQ_TRX_END | IRQ_RX_START | IRQ_PLL_LOCK | IRQ_AMI, 1);
579
580        /* wait for reception */
581        irq = wait_for_interrupt(dsc, IRQ_TRX_END,
582            IRQ_TRX_END | IRQ_RX_START | IRQ_PLL_LOCK | IRQ_AMI, 1000);
583        if (irq) {
584            gettimeofday(&t1, NULL);
585            d = t1.tv_sec-t0.tv_sec+(t1.tv_usec-t0.tv_usec)*1e-6;
586            sum += d;
587            sum2 += d*d;
588            if (first || d < min)
589                min = d;
590            if (first || d > max)
591                max = d;
592            first = 0;
593            n = atrf_buf_read(dsc, buf, size);
594            if (n != size)
595                fprintf(stderr, "%d bytes received\n", n);
596        } else {
597            lost++;
598        }
599    }
600    n = packets-lost;
601    printf("%d sent, %d received, %d lost (%g%%)\n",
602        packets, n, lost, lost*100.0/packets);
603    if (n)
604        printf("rtt min/avg/max = %.3f/%.3f/%.3f ms, mdev = %.3f ms\n",
605            min*1000.0, sum*1000.0/n, max*1000.0,
606            sqrt((sum2-sum*sum/n)/n)*1000.0);
607}
608
609
610/* ----- Continuous wave test ---------------------------------------------- */
611
612
613static int test_mode(struct atrf_dsc *dsc, uint8_t cont_tx, const char *cmd)
614{
615    int status = 0;
616
617    cw_test_begin(dsc, cont_tx);
618
619    if (cmd)
620        status = system(cmd);
621    else {
622        while (run)
623            sleep(1);
624    }
625
626    cw_test_end(dsc);
627
628    return status;
629}
630
631
632/* ----- Command-line processing ------------------------------------------- */
633
634
635static void die(int sig)
636{
637    run = 0;
638}
639
640
641static void usage(const char *name)
642{
643    fprintf(stderr,
644"usage: %s [common_options] [-x] [message [repetitions]]\n"
645" %s [common_options] -H [message]\n"
646" %s [common_options] -E pause_s [repetitions]\n"
647" %s [common_options] -P [max_wait_s]\n"
648" %s [common_options] -R [-H|packets size]\n"
649" %s [common_options] -T offset [command]\n\n"
650" text message mode:\n"
651" -x message consists of hex bytes, optionally separated by\n"
652" ' ', '.', ',', ':', or '-'\n"
653" message message string to send (if absent, receive)\n"
654" repetitions number of times the message is sent (default 1)\n\n"
655" text message mode (hard MAC):\n"
656" -H use hard MAC mode\n"
657" message message string to send (if absent, receive)\n\n"
658" PER test mode (transmit only):\n"
659" -E pause_s seconds to pause between frames (floating-point)\n"
660" repetitions number of messages to send (default: infinite)\n\n"
661" Ping-pong mode:\n"
662" -P exchange packets between two stations\n"
663" max_wait_s generate a new packet if no response is received (master)\n\n"
664" Round-trip time measurement:\n"
665" -R send/receive RTT measurement packets\n"
666" packets number of packets to send (master)\n"
667" size size of packets in bytes\n\n"
668" constant wave test mode (transmit only):\n"
669" -T offset test mode. offset is the frequency offset of the constant\n"
670" wave in MHz: -2, -0.5, or +0.5\n"
671" command shell command to run while transmitting (default: wait for\n"
672" SIGINT instead)\n\n"
673" common options: [-c channel|-f freq] [-C mhz] [-d driver[:arg]] [-o file]\n"
674" [-p power] [-q] [-r rate] [-t trim]\n"
675" -c channel channel number, 11 to 26 (default %d)\n"
676" -C mhz output clock at 1, 2, 4, 8, or 16 MHz (default: off)\n"
677" -d driver[:arg]\n"
678" use the specified driver (default: %s)\n"
679" -f freq frequency in MHz, 2405 to 2480 (default %d)\n"
680" -o file write received data to a file in pcap format\n"
681" -p power transmit power, -17.2 to 3.0 dBm (default %.1f)\n"
682" -q quick and quiet - suppress progress reports and warnings,\n"
683" poll aggressively (currently only used when capturing)\n"
684" -r rate data rate, 250k, 500k, 1M, or 2M (default: 250k)\n"
685" -t trim trim capacitor, 0 to 15 (default %d)\n"
686        , name, name, name, name, name, name,
687        DEFAULT_CHANNEL, atrf_default_driver_name(),
688        2405+5*(DEFAULT_CHANNEL-11), DEFAULT_POWER,
689        DEFAULT_TRIM);
690    exit(1);
691}
692
693
694static void set_mode(enum mode *mode, enum mode new)
695{
696    if (*mode == mode_msg) {
697        *mode = new;
698        return;
699    }
700    if ((*mode == mode_hmac && new == mode_rtt) ||
701        (*mode == mode_rtt && new == mode_hmac)) {
702        *mode = mode_rtt_hmac;
703        return;
704    }
705    fprintf(stderr, "multiple mode selections\n");
706    exit(1);
707}
708
709
710int main(int argc, char *const *argv)
711{
712    enum mode mode = mode_msg;
713    const char *driver = NULL;
714    int channel = DEFAULT_CHANNEL;
715    double power = DEFAULT_POWER;
716    uint8_t rate = OQPSK_DATA_RATE_250;
717    int trim = DEFAULT_TRIM, times = 1, bytes;
718    uint8_t cont_tx = 0;
719    double pause_s = 0;
720    int hex = 0;
721    char *end;
722    int c, freq;
723    unsigned clkm = 0;
724    int status = 0;
725    const char *pcap_file = NULL;
726    struct atrf_dsc *dsc;
727
728    while ((c = getopt(argc, argv, "c:C:d:E:f:Ho:p:Pqr:Rt:T:x")) != EOF)
729        switch (c) {
730        case 'c':
731            channel = strtoul(optarg, &end, 0);
732            if (*end)
733                usage(*argv);
734            if (channel < 11 || channel > 26)
735                usage(*argv);
736            break;
737        case 'C':
738            clkm = strtol(optarg, &end, 0);
739            if (*end)
740                usage(*argv);
741            if (!clkm)
742                usage(*argv);
743            break;
744        case 'd':
745            driver = optarg;
746            break;
747        case 'E':
748            set_mode(&mode, mode_per);
749            pause_s = strtof(optarg, &end);
750            if (*end)
751                usage(*argv);
752            break;
753        case 'f':
754            freq = strtoul(optarg, &end, 0);
755            if (*end)
756                usage(*argv);
757            if (freq % 5)
758                usage(*argv);
759            channel = (freq-2405)/5+11;
760            if (channel < 11 || channel > 26)
761                usage(*argv);
762            break;
763        case 'H':
764            set_mode(&mode, mode_hmac);
765            break;
766        case 'o':
767            pcap_file = optarg;
768            break;
769        case 'p':
770            power = strtod(optarg, &end);
771            if (*end)
772                usage(*argv);
773            break;
774        case 'P':
775            set_mode(&mode, mode_ping);
776            break;
777        case 'q':
778            quick = 1;
779            break;
780        case 'r':
781            if (!strcmp(optarg, "250k"))
782                rate = OQPSK_DATA_RATE_250;
783            else if (!strcmp(optarg, "500k"))
784                rate = OQPSK_DATA_RATE_500;
785            else if (!strcmp(optarg, "1M"))
786                rate = OQPSK_DATA_RATE_1000;
787            else if (!strcmp(optarg, "2M"))
788                rate = OQPSK_DATA_RATE_2000;
789            else
790                usage(*argv);
791            break;
792        case 'R':
793            set_mode(&mode, mode_rtt);
794            break;
795        case 't':
796            trim = strtoul(optarg, &end, 0);
797            if (*end)
798                usage(*argv);
799            if (trim > 15)
800                usage(*argv);
801            break;
802        case 'T':
803            set_mode(&mode, mode_cont_tx);
804            if (!strcmp(optarg, "-2"))
805                cont_tx = CONT_TX_M2M;
806            else if (!strcmp(optarg, "-0.5"))
807                cont_tx = CONT_TX_M500K;
808            else if (!strcmp(optarg, "+0.5"))
809                cont_tx = CONT_TX_P500K;
810            else
811                usage(*argv);
812            break;
813        case 'x':
814            hex = 1;
815            break;
816        default:
817            usage(*argv);
818        }
819
820    signal(SIGINT, die);
821
822    switch (argc-optind) {
823    case 0:
824        dsc = init_txrx(driver, trim, clkm);
825        set_channel(dsc, channel);
826        set_rate(dsc, rate);
827        switch (mode) {
828        case mode_msg:
829            receive(dsc, pcap_file, hex);
830            break;
831        case mode_hmac:
832            receive_hmac(dsc);
833            break;
834        case mode_per:
835            set_power_dBm(dsc, power, 0);
836            transmit_pattern(dsc, pause_s, 0);
837            break;
838        case mode_ping:
839            set_power_dBm(dsc, power, 1);
840            ping(dsc, pause_s, 0);
841            break;
842        case mode_rtt:
843            set_power_dBm(dsc, power, 1);
844            rtt_slave(dsc);
845            break;
846        case mode_rtt_hmac:
847            set_power_dBm(dsc, power, 1);
848            rtt_slave_hmac(dsc);
849            break;
850        case mode_cont_tx:
851            set_power_dBm(dsc, power, 0);
852            status = test_mode(dsc, cont_tx, NULL);
853            break;
854        default:
855            abort();
856        }
857        break;
858    case 2:
859        switch (mode) {
860        case mode_msg:
861        case mode_hmac:
862            break;
863        case mode_per:
864        case mode_ping:
865        case mode_rtt_hmac:
866        case mode_cont_tx:
867            usage(*argv);
868        case mode_rtt:
869            times = strtoul(argv[optind], &end, 0);
870            if (*end)
871                usage(*argv);
872            bytes = strtoul(argv[optind+1], &end, 0);
873            if (*end)
874                usage(*argv);
875            dsc = init_txrx(driver, trim, clkm);
876            set_channel(dsc, channel);
877            set_rate(dsc, rate);
878            set_power_dBm(dsc, power, 1);
879            rtt_master(dsc, times, bytes);
880            goto done;
881        default:
882            abort();
883        }
884        times = strtoul(argv[optind+1], &end, 0);
885        if (*end)
886            usage(*argv);
887        /* fall through */
888    case 1:
889        dsc = init_txrx(driver, trim, clkm);
890        set_channel(dsc, channel);
891        set_rate(dsc, rate);
892        switch (mode) {
893        case mode_msg:
894            set_power_dBm(dsc, power, 1);
895            transmit(dsc, argv[optind], hex, times);
896            break;
897        case mode_hmac:
898            set_power_dBm(dsc, power, 1);
899            transmit_hmac(dsc, argv[optind]);
900            break;
901        case mode_per:
902            times = strtoul(argv[optind], &end, 0);
903            if (*end)
904                usage(*argv);
905            set_power_dBm(dsc, power, 0);
906            transmit_pattern(dsc, pause_s, times);
907            break;
908        case mode_ping:
909            pause_s = strtof(argv[optind], &end);
910            if (*end)
911                usage(*argv);
912            set_power_dBm(dsc, power, 1);
913            ping(dsc, pause_s, 1);
914            break;
915        case mode_rtt:
916        case mode_rtt_hmac:
917            usage(*argv);
918            break;
919        case mode_cont_tx:
920            set_power_dBm(dsc, power, 0);
921            status = test_mode(dsc, cont_tx, argv[optind]);
922            break;
923        default:
924            abort();
925        
926        }
927        break;
928    default:
929        usage(*argv);
930    }
931done:
932
933    atrf_close(dsc);
934
935    if (status) {
936        if (WIFEXITED(status))
937            return WEXITSTATUS(status);
938        if (WIFSIGNALED(status))
939            raise(WTERMSIG(status));
940        fprintf(stderr, "unexpected exit status %d\n", status);
941        abort();
942    }
943    return 0;
944}
945

Archive Download this file



interactive