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

Source at commit 598582c26a877b5135f9b6dbc47a185e3ed9b151 created 8 years 8 months ago.
By Werner Almesberger, atrf-path.c (do_half_sweep, do_sweep): don't duplicate the loop - use a function
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 cont_tx,
68    struct sample *res, int first)
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/*
75 * For the 230, we don't have reset-less exit from test mode (yet ?) and
76 * need to set up things from scratch:
77 *
78 * init_tx(sweep->tx, sweep->trim_tx, sweep->power);
79 * set_channel(sweep->tx, chan);
80 * usleep(155); / * table 7-2, tTR19 * /
81 */
82    if (first)
83        cw_test_begin(sweep->tx, cont_tx);
84    else
85        cw_test_resume(sweep->tx);
86    /* table 7-1, tTR10, doubling since it's a "typical" value */
87    usleep(2*16);
88
89    for (i = 0; i != sweep->samples; i++) {
90        /* according to 8.3.2, PHY_RSSI is updated every 2 us */
91        usleep(2);
92
93        rssi = atrf_reg_read(sweep->rx, REG_PHY_RSSI) & RSSI_MASK;
94        sum += rssi;
95        if (min == -1 || rssi < min)
96            min = rssi;
97        if (rssi > max)
98            max = rssi;
99    }
100
101    cw_test_end(sweep->tx);
102
103    res->avg = rssi_to_dBm((double) sum/sweep->samples)-offset;
104    res->min = rssi_to_dBm(min)-offset;
105    res->max = rssi_to_dBm(max)-offset;
106}
107
108
109static void do_half_sweep(const struct sweep *sweep, int cont_tx,
110    struct sample *res)
111{
112    int chan;
113
114    for (chan = 11; chan <= 26; chan++) {
115        set_channel(sweep->rx, chan);
116        set_channel(sweep->tx, chan);
117        usleep(155); /* table 7-2, tTR19 */
118
119        sample(sweep, cont_tx, res, chan == 11);
120        res += 2;
121    }
122}
123
124
125void do_sweep(const struct sweep *sweep, struct sample *res)
126{
127    do_half_sweep(sweep, CONT_TX_M500K, res);
128    do_half_sweep(sweep, CONT_TX_P500K, res+1);
129}
130
131
132static void print_sweep(const struct sweep *sweep, const struct sample *res)
133{
134    int chan;
135
136    for (chan = 11; chan <= 26; chan++) {
137        printf("%.1f %.2f %.0f %.0f\n",
138            2350+5*chan-0.5, res->avg, res->min, res->max);
139        res++;
140        printf("%.1f %.2f %.0f %.0f\n",
141            2350+5*chan+0.5, res->avg, res->min, res->max);
142        res++;
143    }
144}
145
146
147static void do_sweeps(const struct sweep *sweep, int sweeps)
148{
149    struct sample res[16*2]; /* 16 channels, 2 offsets */
150    int i;
151
152    for (i = 0; i != sweeps; i++) {
153        if (i)
154            putchar('\n');
155        do_sweep(sweep, res);
156        print_sweep(sweep, res);
157    }
158}
159
160
161static void usage(const char *name)
162{
163    fprintf(stderr,
164"usage: %s common_args [sweeps [samples]]\n"
165
166#ifdef HAVE_GFX
167"%6s %s -g common_args [[sweeps] samples]\n"
168#endif
169    "\n"
170" common args: [-p power] [-t trim_tx [-t trim_rx]] driver_tx[:arg]\n"
171" driver_rx[:arg]\n\n"
172
173#ifdef HAVE_GFX
174" -g display results graphically\n"
175#endif
176" -p power transmit power, 0 to 15 (default %d)\n"
177" -t trim trim capacitor, 0 to 15 (default %d)\n"
178
179    , name,
180#ifdef HAVE_GFX
181    "", name,
182#endif
183    DEFAULT_POWER, DEFAULT_TRIM);
184
185    exit(1);
186}
187
188    
189int main(int argc, char **argv)
190{
191    const char *tx_drv, *rx_drv;
192    struct sweep sweep = {
193        .trim_tx = -1,
194        .trim_rx = DEFAULT_TRIM,
195        .samples = 1,
196    };
197    int graphical = 0;
198    int power = DEFAULT_POWER;
199    int sweeps = 1;
200    unsigned long tmp;
201    char *end;
202    int c;
203
204    while ((c = getopt(argc, argv, "gp:t:")) != EOF)
205        switch (c) {
206        case'g':
207            graphical = 1;
208            sweeps = 0;
209            break;
210        case 'p':
211            tmp = strtoul(optarg, &end, 0);
212            if (*end || tmp > 15)
213                usage(*argv);
214            power = tmp;
215            break;
216        case 't':
217            tmp = strtoul(optarg, &end, 0);
218            if (*end || tmp > 15)
219                usage(*argv);
220            if (sweep.trim_tx == -1)
221                sweep.trim_tx = tmp;
222            else
223                sweep.trim_rx = tmp;
224            break;
225        default:
226            usage(*argv);
227        }
228
229    if (sweep.trim_tx == -1)
230        sweep.trim_tx = DEFAULT_TRIM;
231
232    switch (argc-optind) {
233    case 4:
234        sweep.samples = strtoul(argv[optind+3], &end, 0);
235        if (*end)
236            usage(*argv);
237        /* fall through */
238    case 3:
239        sweeps = strtoul(argv[optind+2], &end, 0);
240        if (*end)
241            usage(*argv);
242        if (graphical && argc-optind == 3) {
243            sweep.samples = sweeps;
244            sweeps = 0;
245        }
246        /* fall through */
247    case 2:
248        tx_drv = argv[optind];
249        rx_drv = argv[optind+1];
250        break;
251    default:
252        usage(*argv);
253    }
254
255    sweep.tx = atrf_open(tx_drv);
256    if (!sweep.tx)
257        return 1;
258    sweep.rx = atrf_open(rx_drv);
259    if (!sweep.rx)
260        return 1;
261
262    sweep.power = 15-power;
263    init_rx(sweep.rx, sweep.trim_rx);
264    init_tx(sweep.tx, sweep.trim_tx, sweep.power);
265    if (graphical)
266        gui(&sweep, sweeps);
267    else
268        do_sweeps(&sweep, sweeps);
269
270    atrf_reg_write(sweep.tx, REG_TRX_STATE, TRX_CMD_TRX_OFF);
271    atrf_reg_write(sweep.rx, REG_TRX_STATE, TRX_CMD_TRX_OFF);
272
273    atrf_close(sweep.tx);
274    atrf_close(sweep.rx);
275
276    return 0;
277}
278

Archive Download this file



interactive