Root/tools/atrf-path/atrf-path.c

Source at commit 5f153ca4b8fb15713c1967073e04c8b6be0aefe8 created 9 years 5 months ago.
By Werner Almesberger, atrf-path/atrf-path.c: initialize the receiver only once, not for each sweep
1/*
2 * atrf-path/atrf-path.c - Measure path characteristics
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 "cwtest.h"
22#include "atrf.h"
23
24#include "gui.h"
25#include "sweep.h"
26
27
28#define DEFAULT_TRIM 8
29#define DEFAULT_POWER 15
30
31
32static void set_channel(struct atrf_dsc *dsc, int chan)
33{
34    atrf_reg_write(dsc, REG_PHY_CC_CCA, (1 << CCA_MODE_SHIFT) | chan);
35}
36
37
38static void init_common(struct atrf_dsc *dsc, int trim)
39{
40    atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TRX_OFF);
41    atrf_reg_write(dsc, REG_XOSC_CTRL,
42        (XTAL_MODE_INT << XTAL_MODE_SHIFT) | trim);
43    atrf_set_clkm(dsc, 0);
44}
45
46
47static void init_tx(struct atrf_dsc *dsc, int trim, int power)
48{
49    init_common(dsc, trim);
50    set_power_step(dsc, power, 0);
51}
52
53
54static void init_rx(struct atrf_dsc *dsc, int trim)
55{
56    init_common(dsc, trim);
57    atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_RX_ON);
58}
59
60
61static double rssi_to_dBm(double rssi)
62{
63    return -91+3*(rssi-1);
64}
65
66
67static void sample(const struct sweep *sweep, int chan, int cont_tx,
68    struct sample *res)
69{
70    int i, rssi;
71    int sum = 0, min = -1, max = -1;
72    double offset = tx_power_step2dBm(sweep->tx, sweep->power);
73
74    init_tx(sweep->tx, sweep->trim_tx, sweep->power);
75    set_channel(sweep->tx, chan);
76    usleep(155); /* table 7-2, tTR19 */
77
78    cw_test_begin(sweep->tx, cont_tx);
79    /* table 7-1, tTR10, doubling since it's a "typical" value */
80    usleep(2*16);
81
82    for (i = 0; i != sweep->samples; i++) {
83        /* according to 8.3.2, PHY_RSSI is updated every 2 us */
84        usleep(2);
85
86        rssi = atrf_reg_read(sweep->rx, REG_PHY_RSSI) & RSSI_MASK;
87        sum += rssi;
88        if (min == -1 || rssi < min)
89            min = rssi;
90        if (rssi > max)
91            max = rssi;
92    }
93
94    cw_test_end(sweep->tx);
95
96    res->avg = rssi_to_dBm((double) sum/sweep->samples)-offset;
97    res->min = rssi_to_dBm(min)-offset;
98    res->max = rssi_to_dBm(max)-offset;
99}
100
101
102void do_sweep(const struct sweep *sweep, struct sample *res)
103{
104    int chan;
105
106    for (chan = 11; chan <= 26; chan++) {
107        set_channel(sweep->rx, chan);
108        sample(sweep, chan, CONT_TX_M500K, res++);
109        sample(sweep, chan, CONT_TX_P500K, res++);
110    }
111}
112
113
114static void print_sweep(const struct sweep *sweep, const struct sample *res)
115{
116    int chan;
117
118    for (chan = 11; chan <= 26; chan++) {
119        printf("%.1f %.2f %.0f %.0f\n",
120            2350+5*chan-0.5, res->avg, res->min, res->max);
121        res++;
122        printf("%.1f %.2f %.0f %.0f\n",
123            2350+5*chan+0.5, res->avg, res->min, res->max);
124        res++;
125    }
126}
127
128
129static void do_sweeps(const struct sweep *sweep, int sweeps)
130{
131    struct sample res[16*2]; /* 16 channels, 2 offsets */
132    int i;
133
134    for (i = 0; i != sweeps; i++) {
135        if (i)
136            putchar('\n');
137        do_sweep(sweep, res);
138        print_sweep(sweep, res);
139    }
140}
141
142
143static void usage(const char *name)
144{
145    fprintf(stderr,
146"usage: %s [-p power] [-t trim_tx [-t trim_rx]] driver_tx[:arg]\n"
147"%16s driver_rx[:arg] [sweeps [samples]]\n"
148
149#ifdef HAVE_GFX
150"%6s %s -g [-p power] [-t trim_tx [-t trim_rx]] driver_tx[:arg]\n"
151"%16s driver_rx[:arg] [[sweeps] samples]\n"
152#endif
153    "\n"
154
155#ifdef HAVE_GFX
156" -g display results graphically\n"
157#endif
158" -p power transmit power, 0 to 15 (default %d)\n"
159" -t trim trim capacitor, 0 to 15 (default %d)\n"
160
161    , name, "",
162#ifdef HAVE_GFX
163    "", name, "",
164#endif
165    DEFAULT_POWER, DEFAULT_TRIM);
166
167    exit(1);
168}
169
170    
171int main(int argc, char **argv)
172{
173    const char *tx_drv, *rx_drv;
174    struct sweep sweep = {
175        .trim_tx = -1,
176        .trim_rx = DEFAULT_TRIM,
177        .samples = 1,
178    };
179    int graphical = 0;
180    int power = DEFAULT_POWER;
181    int sweeps = 1;
182    unsigned long tmp;
183    char *end;
184    int c;
185
186    while ((c = getopt(argc, argv, "gp:t:")) != EOF)
187        switch (c) {
188        case'g':
189            graphical = 1;
190            sweeps = 0;
191            break;
192        case 'p':
193            tmp = strtoul(optarg, &end, 0);
194            if (*end || tmp > 15)
195                usage(*argv);
196            power = tmp;
197            break;
198        case 't':
199            tmp = strtoul(optarg, &end, 0);
200            if (*end || tmp > 15)
201                usage(*argv);
202            if (sweep.trim_tx == -1)
203                sweep.trim_tx = tmp;
204            else
205                sweep.trim_rx = tmp;
206            break;
207        default:
208            usage(*argv);
209        }
210
211    if (sweep.trim_tx == -1)
212        sweep.trim_tx = DEFAULT_TRIM;
213
214    switch (argc-optind) {
215    case 4:
216        sweep.samples = strtoul(argv[optind+3], &end, 0);
217        if (*end)
218            usage(*argv);
219        /* fall through */
220    case 3:
221        sweeps = strtoul(argv[optind+2], &end, 0);
222        if (*end)
223            usage(*argv);
224        if (graphical && argc-optind == 3) {
225            sweep.samples = sweeps;
226            sweeps = 0;
227        }
228        /* fall through */
229    case 2:
230        tx_drv = argv[optind];
231        rx_drv = argv[optind+1];
232        break;
233    default:
234        usage(*argv);
235    }
236
237    sweep.tx = atrf_open(tx_drv);
238    if (!sweep.tx)
239        return 1;
240    sweep.rx = atrf_open(rx_drv);
241    if (!sweep.rx)
242        return 1;
243
244    sweep.power = 15-power;
245    init_rx(sweep.rx, sweep.trim_rx);
246    if (graphical)
247        gui(&sweep, sweeps);
248    else
249        do_sweeps(&sweep, sweeps);
250
251    atrf_reg_write(sweep.tx, REG_TRX_STATE, TRX_CMD_TRX_OFF);
252    atrf_reg_write(sweep.rx, REG_TRX_STATE, TRX_CMD_TRX_OFF);
253
254    atrf_close(sweep.tx);
255    atrf_close(sweep.rx);
256
257    return 0;
258}
259

Archive Download this file



interactive