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

Source at commit 7605d8c9c8cd95d6c628568db2580019b8027229 created 8 years 4 months ago.
By Werner Almesberger, tools/atrf-txrx/atrf-txrx.c (main): removed endless loop in mode_hmac
1/*
2 * atrf-txrx/atrf-txrx.c - ben-wpan AT86RF230 TX/RX
3 *
4 * Written 2010-2011 by Werner Almesberger
5 * Copyright 2010-2011 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 <stdint.h>
15#include <stdlib.h>
16#include <stdio.h>
17#include <unistd.h>
18#include <string.h>
19#include <math.h>
20#include <signal.h>
21#include <sys/wait.h>
22#include <sys/time.h>
23
24#include "at86rf230.h"
25#include "atrf.h"
26#include "misctxrx.h"
27#include "cwtest.h"
28
29#include "pcap.h"
30
31
32/*
33 * According to IEEE 802.15.4-2003 section E.2.6, channel 15 is the only
34 * channel that falls into the 802.11 guard bands in North America an Europe.
35 */
36
37#define DEFAULT_CHANNEL 15 /* channel 15, 2425 MHz */
38
39#define DEFAULT_TRIM 8 /* trim range is 0-15, see also ECN0002 */
40
41
42/*
43 * Transmit power, dBm. IEEE 802.15.4-2003 section E.3.1.3 specifies a transmit
44 * power of 0 dBm for IEEE 802.15.4. We assume an antenna gain of 3 dB or
45 * better.
46 */
47
48#define DEFAULT_POWER -3.2 /* transmit power, dBm */
49
50
51struct ping {
52    uint32_t seq; /* sequence number from originator, > 0 */
53    uint32_t ack; /* last sequence number received, 0 if none */
54    uint8_t pad[117]; /* pad to 127 bytes */
55    uint16_t crc;
56} __attribute__((__packed__));
57
58enum rx_res {
59    rx_exit,
60    rx_good,
61    rx_bad,
62    rx_timeout,
63};
64
65
66static volatile int run = 1;
67
68
69/*
70 * clkm: 0 disable CLKM
71 * >0 output 2^(clkm-1) MHz signal
72 */
73
74static struct atrf_dsc *init_txrx(const char *driver, int trim, unsigned mhz)
75{
76    struct atrf_dsc *dsc;
77
78    dsc = atrf_open(driver);
79    if (!dsc)
80        exit(1);
81    
82    atrf_reset_rf(dsc);
83    atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TRX_OFF);
84
85#if 1 // def HAVE_USB /* @@@ yeah, ugly */
86    atrf_reg_write(dsc, REG_XOSC_CTRL,
87        (XTAL_MODE_INT << XTAL_MODE_SHIFT) | trim);
88#else
89    atrf_reg_write(dsc, REG_XOSC_CTRL, XTAL_MODE_EXT << XTAL_MODE_SHIFT);
90#endif
91
92    if (!atrf_set_clkm(dsc, mhz))
93        if (mhz) {
94            atrf_close(dsc);
95            exit(1);
96        }
97
98    /* We want to see all interrupts, not only the ones we're expecting. */
99    atrf_reg_write(dsc, REG_IRQ_MASK, 0xff);
100
101    flush_interrupts(dsc);
102    if (atrf_identify(dsc) == artf_at86rf231)
103        wait_for_interrupt(dsc, IRQ_CCA_ED_DONE, IRQ_CCA_ED_DONE, 1);
104            /* according to table 7-1, 37 us max */
105
106    return dsc;
107}
108
109
110static void set_channel(struct atrf_dsc *dsc, int channel)
111{
112    atrf_reg_write(dsc, REG_PHY_CC_CCA, (1 << CCA_MODE_SHIFT) | channel);
113}
114
115
116static void set_rate(struct atrf_dsc *dsc, uint8_t rate)
117{
118    if (!rate)
119        return;
120    switch (atrf_identify(dsc)) {
121    case artf_at86rf230:
122        fprintf(stderr, "AT86RF230 only supports 250 kbps\n");
123        break;
124    case artf_at86rf231:
125        atrf_reg_write(dsc, REG_TRX_CTRL_2, rate);
126        break;
127    default:
128        abort();
129    }
130}
131
132
133static void receive_message(struct atrf_dsc *dsc)
134{
135    uint8_t buf[MAX_PSDU+1]; /* PSDU+LQI */
136    int n, ok, i;
137    uint8_t ed, lqi;
138
139    fprintf(stderr, "Ready.\n");
140    wait_for_interrupt(dsc, IRQ_TRX_END,
141        IRQ_TRX_END | IRQ_RX_START | IRQ_AMI, 0);
142    if (!run)
143        return;
144
145    n = atrf_buf_read(dsc, buf, sizeof(buf));
146    if (n < 0)
147        exit(1);
148    if (n < 3) {
149        fprintf(stderr, "%d bytes received\n", n);
150        exit(1);
151    }
152    ed = atrf_reg_read(dsc, REG_PHY_ED_LEVEL);
153    ok = !!(atrf_reg_read(dsc, REG_PHY_RSSI) & RX_CRC_VALID);
154    lqi = buf[n-1];
155    fprintf(stderr, "%d bytes payload, CRC %s, LQI %u, ED %d dBm\n",
156        n-3, ok ? "OK" : "BAD", lqi, -91+ed);
157    for (i = 0; i != n-3; i++)
158        putchar(buf[i] < ' ' || buf[i] > '~' ? '?' : buf[i]);
159    putchar('\n');
160}
161
162
163static void write_pcap_hdr(FILE *file)
164{
165    struct pcap_file_header hdr = {
166        .magic = PCAP_FILE_MAGIC,
167        .version_major = 2,
168        .version_minor = 4,
169        .thiszone = 0,
170        .sigfigs = 0,
171        .snaplen = MAX_PSDU,
172        .linktype = DLT_IEEE802_15_4
173    };
174
175    if (fwrite(&hdr, sizeof(hdr), 1, file) != 1) {
176        perror("fwrite");
177        exit(1);
178    }
179}
180
181
182static void write_pcap_rec(FILE *file, const struct timeval *tv,
183    const void *buf, int n)
184{
185    struct pcap_pkthdr hdr = {
186        .ts_sec = tv->tv_sec,
187        .ts_usec = tv->tv_usec,
188        .caplen = n,
189        .len = n
190    };
191
192    if (fwrite(&hdr, sizeof(hdr), 1, file) != 1) {
193        perror("fwrite");
194        exit(1);
195    }
196    if (fwrite(buf, n, 1, file) != 1) {
197        perror("fwrite");
198        exit(1);
199    }
200}
201
202
203static void receive_pcap(struct atrf_dsc *dsc, const char *name)
204{
205    FILE *file;
206    uint8_t buf[MAX_PSDU+1]; /* PSDU+LQI */
207    struct timeval now;
208    int n;
209    int count = 0;
210
211    file = fopen(name, "w");
212    if (!file) {
213        perror(name);
214        exit(1);
215    }
216    write_pcap_hdr(file);
217    while (run) {
218        wait_for_interrupt(dsc,
219            IRQ_TRX_END, IRQ_TRX_END | IRQ_RX_START | IRQ_AMI, 0);
220        if (!run)
221            break;
222        gettimeofday(&now, NULL);
223        n = atrf_buf_read(dsc, buf, sizeof(buf));
224        if (n < 0)
225            exit(1);
226        if (n < 2) {
227            fprintf(stderr, "%d bytes received\n", n);
228            continue;
229        }
230        write_pcap_rec(file, &now, buf, n-1);
231        (void) write(2, ".", 1);
232        count++;
233    }
234    if (fclose(file) == EOF) {
235        perror(name);
236        exit(1);
237    }
238    fprintf(stderr, "%sreceived %d message%s\n", count ? "\n" : "",
239        count, count == 1 ? "" : "s");
240}
241
242
243static void receive(struct atrf_dsc *dsc, const char *name)
244{
245    atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_RX_ON);
246    /*
247     * 180 us, according to AVR2001 section 4.2. We time out after
248     * nominally 200 us.
249     */
250    wait_for_interrupt(dsc, IRQ_PLL_LOCK, IRQ_PLL_LOCK, 1);
251
252    if (name)
253        receive_pcap(dsc, name);
254    else
255        receive_message(dsc);
256}
257
258
259static void transmit(struct atrf_dsc *dsc, const char *msg, int times)
260{
261    uint8_t buf[MAX_PSDU];
262
263    atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_PLL_ON);
264    /*
265     * 180 us, according to AVR2001 section 4.3. We time out after
266     * nominally 200 us.
267     */
268    wait_for_interrupt(dsc, IRQ_PLL_LOCK, IRQ_PLL_LOCK, 1);
269
270    /*
271     * We need to copy the message to append the CRC placeholders.
272     */
273    strcpy((void *) buf, msg);
274    atrf_buf_write(dsc, buf, strlen(msg)+2);
275
276    while (run && times--) {
277        /* @@@ should wait for clear channel */
278        atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TX_START);
279
280        /* wait up to 10 ms (nominally) */
281        wait_for_interrupt(dsc, IRQ_TRX_END,
282           IRQ_TRX_END | IRQ_PLL_LOCK, 10);
283    }
284}
285
286
287static void receive_hmac(struct atrf_dsc *dsc)
288{
289    uint8_t buf[MAX_PSDU];
290    uint8_t lqi;
291    int n, i;
292
293    atrf_rx_mode(dsc, 1);
294    n = atrf_rx(dsc, buf, sizeof(buf), &lqi);
295    atrf_rx_mode(dsc, 0);
296
297    if (n < 2) {
298        fprintf(stderr, "%d bytes received\n", n);
299        exit(1);
300    }
301    for (i = 0; i != n-2; i++)
302        putchar(buf[i] < ' ' || buf[i] > '~' ? '?' : buf[i]);
303    putchar('\n');
304}
305
306
307static void transmit_hmac(struct atrf_dsc *dsc, const char *msg)
308{
309    atrf_rx_mode(dsc, 1);
310    atrf_tx(dsc, msg, strlen(msg));
311    atrf_rx_mode(dsc, 0);
312}
313
314
315static void transmit_pattern(struct atrf_dsc *dsc, double pause_s, int times)
316{
317    uint8_t buf[MAX_PSDU];
318    uint8_t n = 0;
319    int us = fmod(pause_s, 1)*1000000;
320
321    atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_PLL_ON);
322    /*
323     * 180 us, according to AVR2001 section 4.3. We time out after
324     * nominally 200 us.
325     */
326    wait_for_interrupt(dsc, IRQ_PLL_LOCK, IRQ_PLL_LOCK, 1);
327
328    while (run) {
329        memset(buf, n, sizeof(buf));
330        atrf_buf_write(dsc, buf, sizeof(buf));
331
332        atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TX_START);
333
334        /* wait up to 10 ms (nominally) */
335        wait_for_interrupt(dsc, IRQ_TRX_END,
336           IRQ_TRX_END | IRQ_PLL_LOCK, 10);
337
338        if (pause_s >= 1)
339            sleep(pause_s);
340        if (us)
341            usleep(us);
342
343        if (times && !--times)
344            break;
345        n++;
346    }
347}
348
349
350static void ping_tx(struct atrf_dsc *dsc, const struct ping *pck)
351{
352    atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_PLL_ON);
353    /*
354     * 180 us, according to AVR2001 section 4.3. We time out after
355     * nominally 200 us.
356     */
357    wait_for_interrupt(dsc, IRQ_PLL_LOCK, IRQ_PLL_LOCK, 1);
358
359    atrf_buf_write(dsc, pck, sizeof(*pck));
360    atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TX_START);
361
362    /* wait up to 10 ms (nominally) */
363    wait_for_interrupt(dsc, IRQ_TRX_END,
364       IRQ_TRX_END | IRQ_PLL_LOCK, 10);
365}
366
367
368static enum rx_res ping_rx(struct atrf_dsc *dsc, struct ping *pck, int wait_ms)
369{
370    uint8_t irq;
371    int n;
372
373    atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_RX_ON);
374    irq = wait_for_interrupt(dsc, IRQ_TRX_END,
375        IRQ_TRX_END | IRQ_RX_START | IRQ_PLL_LOCK, wait_ms);
376    if (!run)
377        return rx_exit;
378    if (!irq)
379        return rx_timeout;
380
381    n = atrf_buf_read(dsc, pck, sizeof(*pck));
382    if (n < 0)
383        exit(1);
384    if (n != sizeof(*pck)) {
385        fprintf(stderr, "%d bytes received\n", n);
386        return rx_bad;
387    }
388    return atrf_reg_read(dsc, REG_PHY_RSSI) & RX_CRC_VALID ?
389        rx_good : rx_bad;
390}
391
392
393static void ping(struct atrf_dsc *dsc, double max_wait_s, int master)
394{
395    static int first = 1;
396    struct ping tx_pck = {
397        .seq = 0,
398        .ack = 0,
399    };
400    struct ping rx_pck;
401    enum rx_res res;
402
403    while (run) {
404        tx_pck.seq++;
405        if (master || !first) {
406            ping_tx(dsc, &tx_pck);
407            if (!run)
408                break;
409        }
410        first = 0;
411        res = ping_rx(dsc, &rx_pck, master ? max_wait_s*1000 : 0);
412        switch (res) {
413        case rx_good:
414            tx_pck.ack = rx_pck.seq;
415            if (tx_pck.seq == rx_pck.ack)
416                write(2, ".", 1);
417            else
418                write(2, "*", 1);
419            break;
420        case rx_bad:
421            write(2, "-", 1);
422            break;
423        case rx_timeout:
424            write(2, "+", 1);
425            break;
426        case rx_exit:
427            return;
428        default:
429            abort();
430        }
431    }
432}
433
434
435static int test_mode(struct atrf_dsc *dsc, uint8_t cont_tx, const char *cmd)
436{
437    int status = 0;
438
439    cw_test_begin(dsc, cont_tx);
440
441    if (cmd)
442        status = system(cmd);
443    else {
444        while (run)
445            sleep(1);
446    }
447
448    cw_test_end(dsc);
449
450    return status;
451}
452
453
454static void die(int sig)
455{
456    run = 0;
457}
458
459
460static void usage(const char *name)
461{
462    fprintf(stderr,
463"usage: %s [common_options] [message [repetitions]]\n"
464" %s [common_options] -H [message]\n"
465" %s [common_options] -E pause_s [repetitions]\n"
466" %s [common_options] -P [max_wait_s]\n"
467" %s [common_options] -T offset [command]\n\n"
468" text message mode:\n"
469" message message string to send (if absent, receive)\n"
470" repetitions number of times the message is sent (default 1)\n\n"
471" text message mode (hard MAC):\n"
472" -H use hard MAC mode\n"
473" message message string to send (if absent, receive)\n"
474" PER test mode (transmit only):\n"
475" -E pause_s seconds to pause between frames (floating-point)\n"
476" repetitions number of messages to send (default: infinite)\n\n"
477" Ping-pong mode:\n"
478" -P exchange packets between two stations\n"
479" max_wait_s generate a new packet if no response is received (master)\n\n"
480" constant wave test mode (transmit only):\n"
481" -T offset test mode. offset is the frequency offset of the constant\n"
482" wave in MHz: -2, -0.5, or +0.5\n"
483" command shell command to run while transmitting (default: wait for\n"
484" SIGINT instead)\n\n"
485" common options: [-c channel|-f freq] [-C mhz] [-d driver[:arg]] [-o file]\n"
486" [-p power] [-r rate] [-t trim]\n"
487" -c channel channel number, 11 to 26 (default %d)\n"
488" -C mhz output clock at 1, 2, 4, 8, or 16 MHz (default: off)\n"
489" -d driver[:arg]\n"
490" use the specified driver (default: %s)\n"
491" -f freq frequency in MHz, 2405 to 2480 (default %d)\n"
492" -o file write received data to a file in pcap format\n"
493" -p power transmit power, -17.2 to 3.0 dBm (default %.1f)\n"
494" -r rate data rate, 250k, 500k, 1M, or 2M (default: 250k)\n"
495" -t trim trim capacitor, 0 to 15 (default %d)\n"
496        , name, name, name, name, name,
497        DEFAULT_CHANNEL, atrf_default_driver_name(),
498        2405+5*(DEFAULT_CHANNEL-11), DEFAULT_POWER,
499        DEFAULT_TRIM);
500    exit(1);
501}
502
503
504int main(int argc, char *const *argv)
505{
506    enum {
507        mode_msg,
508        mode_hmac,
509        mode_per,
510        mode_ping,
511        mode_cont_tx,
512    } mode = mode_msg;
513    const char *driver = NULL;
514    int channel = DEFAULT_CHANNEL;
515    double power = DEFAULT_POWER;
516    uint8_t rate = OQPSK_DATA_RATE_250;
517    int trim = DEFAULT_TRIM, times = 1;
518    uint8_t cont_tx = 0;
519    double pause_s = 0;
520    char *end;
521    int c, freq;
522    unsigned clkm = 0;
523    int status = 0;
524    const char *pcap_file = NULL;
525    struct atrf_dsc *dsc;
526
527    while ((c = getopt(argc, argv, "c:C:d:f:Ho:p:r:E:Pt:T:")) != EOF)
528        switch (c) {
529        case 'c':
530            channel = strtoul(optarg, &end, 0);
531            if (*end)
532                usage(*argv);
533            if (channel < 11 || channel > 26)
534                usage(*argv);
535            break;
536        case 'd':
537            driver = optarg;
538            break;
539        case 'f':
540            freq = strtoul(optarg, &end, 0);
541            if (*end)
542                usage(*argv);
543            if (freq % 5)
544                usage(*argv);
545            channel = (freq-2405)/5+11;
546            if (channel < 11 || channel > 26)
547                usage(*argv);
548            break;
549        case 'H':
550            mode = mode_hmac;
551            break;
552        case 'o':
553            pcap_file = optarg;
554            break;
555        case 'p':
556            power = strtod(optarg, &end);
557            if (*end)
558                usage(*argv);
559            break;
560        case 'r':
561            if (!strcmp(optarg, "250k"))
562                rate = OQPSK_DATA_RATE_250;
563            else if (!strcmp(optarg, "500k"))
564                rate = OQPSK_DATA_RATE_500;
565            else if (!strcmp(optarg, "1M"))
566                rate = OQPSK_DATA_RATE_1000;
567            else if (!strcmp(optarg, "2M"))
568                rate = OQPSK_DATA_RATE_2000;
569            else
570                usage(*argv);
571            break;
572        case 't':
573            trim = strtoul(optarg, &end, 0);
574            if (*end)
575                usage(*argv);
576            if (trim > 15)
577                usage(*argv);
578            break;
579        case 'C':
580            clkm = strtol(optarg, &end, 0);
581            if (*end)
582                usage(*argv);
583            if (!clkm)
584                usage(*argv);
585            break;
586        case 'E':
587            mode = mode_per;
588            pause_s = strtof(optarg, &end);
589            if (*end)
590                usage(*argv);
591            break;
592        case 'P':
593            mode = mode_ping;
594            break;
595        case 'T':
596            mode = mode_cont_tx;
597            if (!strcmp(optarg, "-2"))
598                cont_tx = CONT_TX_M2M;
599            else if (!strcmp(optarg, "-0.5"))
600                cont_tx = CONT_TX_M500K;
601            else if (!strcmp(optarg, "+0.5"))
602                cont_tx = CONT_TX_P500K;
603            else
604                usage(*argv);
605            break;
606        default:
607            usage(*argv);
608        }
609
610    signal(SIGINT, die);
611
612    switch (argc-optind) {
613    case 0:
614        dsc = init_txrx(driver, trim, clkm);
615        set_channel(dsc, channel);
616        set_rate(dsc, rate);
617        switch (mode) {
618        case mode_msg:
619            receive(dsc, pcap_file);
620            break;
621        case mode_hmac:
622            receive_hmac(dsc);
623            break;
624        case mode_per:
625            set_power_dBm(dsc, power, 0);
626            transmit_pattern(dsc, pause_s, 0);
627            break;
628        case mode_ping:
629            set_power_dBm(dsc, power, 1);
630            ping(dsc, pause_s, 0);
631            break;
632        case mode_cont_tx:
633            set_power_dBm(dsc, power, 0);
634            status = test_mode(dsc, cont_tx, NULL);
635            break;
636        default:
637            abort();
638        }
639        break;
640    case 2:
641        switch (mode) {
642        case mode_msg:
643        case mode_hmac:
644            break;
645        case mode_per:
646        case mode_ping:
647            /* fall through */
648        case mode_cont_tx:
649            usage(*argv);
650        default:
651            abort();
652        }
653        times = strtoul(argv[optind+1], &end, 0);
654        if (*end)
655            usage(*argv);
656        /* fall through */
657    case 1:
658        dsc = init_txrx(driver, trim, clkm);
659        set_channel(dsc, channel);
660        set_rate(dsc, rate);
661        switch (mode) {
662        case mode_msg:
663            set_power_dBm(dsc, power, 1);
664            transmit(dsc, argv[optind], times);
665            break;
666        case mode_hmac:
667            set_power_dBm(dsc, power, 1);
668            transmit_hmac(dsc, argv[optind]);
669            break;
670        case mode_per:
671            times = strtoul(argv[optind], &end, 0);
672            if (*end)
673                usage(*argv);
674            set_power_dBm(dsc, power, 0);
675            transmit_pattern(dsc, pause_s, times);
676            break;
677        case mode_ping:
678            pause_s = strtof(argv[optind], &end);
679            if (*end)
680                usage(*argv);
681            set_power_dBm(dsc, power, 1);
682            ping(dsc, pause_s, 1);
683            break;
684        case mode_cont_tx:
685            set_power_dBm(dsc, power, 0);
686            status = test_mode(dsc, cont_tx, argv[optind]);
687            break;
688        default:
689            abort();
690        
691        }
692        break;
693    default:
694        usage(*argv);
695    }
696
697    atrf_close(dsc);
698
699    if (status) {
700        if (WIFEXITED(status))
701            return WEXITSTATUS(status);
702        if (WIFSIGNALED(status))
703            raise(WTERMSIG(status));
704        fprintf(stderr, "unexpected exit status %d\n", status);
705        abort();
706    }
707    return 0;
708}
709

Archive Download this file



interactive