Root/tools/atrf-xmit/atrf-xmit.c

1/*
2 * atrf-xmit/atrf-xmit.c - Fast transmission test
3 *
4 * Written 2011 by Werner Almesberger
5 * Copyright 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 <stdlib.h>
15#include <stdio.h>
16#include <unistd.h>
17
18#include "at86rf230.h"
19
20#include "misctxrx.h"
21#include "atrf.h"
22
23
24#define DEFAULT_CHANNEL 15
25#define DEFAULT_TRIM 8
26#define DEFAULT_POWER 15
27
28#define PSDU_SIZE 127
29
30
31static int verbose = 0;
32
33
34static void init_common(struct atrf_dsc *dsc, int trim, int channel)
35{
36    atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TRX_OFF);
37    atrf_reg_write(dsc, REG_XOSC_CTRL,
38        (XTAL_MODE_INT << XTAL_MODE_SHIFT) | trim);
39    atrf_set_clkm(dsc, 0);
40    atrf_reg_write(dsc, REG_PHY_CC_CCA, (1 << CCA_MODE_SHIFT) | channel);
41    atrf_reg_write(dsc, REG_IRQ_MASK, 0xff);
42    flush_interrupts(dsc);
43}
44
45
46static void init_tx(struct atrf_dsc *dsc, int trim, int channel, int power)
47{
48    uint8_t buf[PSDU_SIZE];
49    int i;
50
51    init_common(dsc, trim, channel);
52    set_power_step(dsc, power, 1);
53    for (i = 0; i != sizeof(buf); i++)
54        buf[i] = i;
55    atrf_buf_write(dsc, buf, sizeof(buf));
56    atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_PLL_ON);
57    wait_for_interrupt(dsc, IRQ_PLL_LOCK, IRQ_PLL_LOCK, 1);
58}
59
60
61static void init_rx(struct atrf_dsc *dsc, int trim, int channel)
62{
63    init_common(dsc, trim, channel);
64    atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_RX_ON);
65    wait_for_interrupt(dsc, IRQ_PLL_LOCK, IRQ_PLL_LOCK, 1);
66}
67
68
69static int xfer_one(struct atrf_dsc *tx, struct atrf_dsc *rx)
70{
71    uint8_t irq;
72    uint8_t buf[PSDU_SIZE+1]; /* +1 for LQI */
73    int n, i;
74
75    if (wait_for_interrupt(tx, IRQ_TRX_END, IRQ_TRX_END, 1)) {
76        fprintf(stderr, "unexpected sender interrupt\n");
77        exit(1);
78    }
79    if (wait_for_interrupt(rx, IRQ_TRX_END, IRQ_TRX_END, 1)) {
80        fprintf(stderr, "unexpected receiver interrupt\n");
81        exit(1);
82    }
83
84    atrf_slp_tr(tx, 1, 1);
85    irq = wait_for_interrupt(rx, IRQ_TRX_END, IRQ_TRX_END | IRQ_RX_START,
86        10);
87    if (!(irq & IRQ_TRX_END))
88        return 0;
89
90    irq = wait_for_interrupt(tx, IRQ_TRX_END, IRQ_TRX_END, 1);
91    if (!(irq & IRQ_TRX_END)) {
92        fprintf(stderr, "sender claims packet was not sent ?\n");
93        exit(1);
94    }
95
96    if (atrf_reg_read(rx, REG_PHY_RSSI) & RX_CRC_VALID)
97        return 1;
98    n = atrf_buf_read(rx, buf, sizeof(buf));
99    if (n <= 0)
100        return 0;
101    n--; /* we don't care about the LQI */
102    if (n != PSDU_SIZE) {
103        printf("0\n");
104        return 0;
105    }
106    for (i = 0; i != n-2; i++)
107        if (buf[i] != i)
108            break;
109    /*
110     * @@@ We should analyze the CRC here to see if the first or the second
111     * byte got corrupted.
112     */
113    if (verbose) {
114        printf("%d", i+1);
115        for (i = 0; i != n-2; i++)
116            printf("%s%02x", i ? " " : "\t", buf[i]);
117        printf("\n");
118    } else {
119        printf("%d\n", i+1);
120    }
121    return 0;
122}
123
124
125static void xfer(struct atrf_dsc *tx, struct atrf_dsc *rx, int packets)
126{
127    int got = 0;
128    int i;
129
130    for (i = 0; i != packets; i++)
131        got += xfer_one(tx, rx);
132    printf("%d/%d\n", got, packets);
133}
134
135
136static void usage(const char *name)
137{
138    fprintf(stderr,
139"usage: %s [-c channel] [-p power] [-t trim_tx [-t trim_rx]] [-v]\n"
140"%15s driver_tx[:arg] driver_rx[:arg] [packets]\n\n"
141" -c channel transmit/receive channel, 11 to 26 (default %d)\n"
142" -p power transmit power, 0 to 15 (default %d)\n"
143" -t trim trim capacitor, 0 to 15 (default %d)\n"
144" -v verbose reporting of transmission errors\n"
145    , name, "",
146    DEFAULT_CHANNEL, DEFAULT_POWER, DEFAULT_TRIM);
147    exit(1);
148}
149
150    
151int main(int argc, char **argv)
152{
153    const char *tx_drv, *rx_drv;
154    struct atrf_dsc *tx, *rx;
155    int trim_tx = -1, trim_rx = DEFAULT_TRIM;
156    int channel = DEFAULT_CHANNEL;
157    int power = DEFAULT_POWER;
158    int packets = 1;
159    unsigned long tmp;
160    char *end;
161    int c;
162
163    while ((c = getopt(argc, argv, "c:p:t:v")) != EOF)
164        switch (c) {
165        case 'c':
166            tmp = strtoul(optarg, &end, 0);
167            if (*end || tmp < 11 || tmp > 26)
168                usage(*argv);
169            channel = tmp;
170            break;
171        case 'v':
172            verbose++;
173            break;
174        case 'p':
175            tmp = strtoul(optarg, &end, 0);
176            if (*end || tmp > 15)
177                usage(*argv);
178            power = tmp;
179            break;
180        case 't':
181            tmp = strtoul(optarg, &end, 0);
182            if (*end || tmp > 15)
183                usage(*argv);
184            if (trim_tx == -1)
185                trim_tx = tmp;
186            else
187                trim_rx = tmp;
188            break;
189        default:
190            usage(*argv);
191        }
192
193    if (trim_tx == -1)
194        trim_tx = DEFAULT_TRIM;
195
196    switch (argc-optind) {
197    case 3:
198        packets = strtoul(argv[optind+2], &end, 0);
199        if (*end)
200            usage(*argv);
201        /* fall through */
202    case 2:
203        tx_drv = argv[optind];
204        rx_drv = argv[optind+1];
205        break;
206    default:
207        usage(*argv);
208    }
209
210    tx = atrf_open(tx_drv);
211    if (!tx)
212        return 1;
213    rx = atrf_open(rx_drv);
214    if (!rx)
215        return 1;
216
217    init_rx(rx, trim_rx, channel);
218    init_tx(tx, trim_tx, channel, 15-power);
219
220    xfer(tx, rx, packets);
221
222    atrf_reg_write(tx, REG_TRX_STATE, TRX_CMD_TRX_OFF);
223    atrf_reg_write(rx, REG_TRX_STATE, TRX_CMD_TRX_OFF);
224
225    atrf_close(tx);
226    atrf_close(rx);
227
228    return 0;
229}
230

Archive Download this file



interactive