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

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

Archive Download this file



interactive