Root/tools/atspi-txrx/atspi-txrx.c

Source at commit d4fe0277c28563f870334b68dde373751ace8197 created 8 years 11 months ago.
By Werner Almesberger, atspi-txrx: option -T <delta_MHz> to emit a constant wave
1/*
2 * atspi-txrx/atspi-txrx.c - ben-wpan AT86RF230 TX/RX
3 *
4 * Written 2010 by Werner Almesberger
5 * Copyright 2010 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
22#include "at86rf230.h"
23#include "atspi.h"
24#include "misctxrx.h"
25
26
27/*
28 * According to IEEE 802.15.4-2003 section E.2.6, channel 15 is the only
29 * channel that falls into the 802.11 guard bands in North America an Europe.
30 */
31
32#define DEFAULT_CHANNEL 15 /* channel 15, 2425 MHz */
33
34/*
35 * Transmit power, dBm. IEEE 802.15.4-2003 section E.3.1.3 specifies a transmit
36 * power of 0 dBm for IEEE 802.15.4. We assume an antenna gain of 3 dB or
37 * better.
38 */
39
40#define DEFAULT_POWER -3.2 /* transmit power, dBm */
41
42
43static double tx_pwr[] = {
44     3.0, 2.6, 2.1, 1.6,
45     1.1, 0.5, -0.2, -1.2,
46    -2.2, -3.2, -4.2, -5.2,
47    -7.2, -9.2, -12.2, -17.2
48};
49
50
51static volatile int run = 1;
52
53
54static struct atspi_dsc *init_txrx(int trim)
55{
56    struct atspi_dsc *dsc;
57
58    dsc = atspi_open();
59    if (!dsc)
60        exit(1);
61    
62    atspi_reset_rf(dsc);
63    atspi_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TRX_OFF);
64#ifdef HAVE_USB /* @@@ yeah, ugly */
65    atspi_reg_write(dsc, REG_XOSC_CTRL,
66        (XTAL_MODE_INT << XTAL_MODE_SHIFT) | trim);
67#else
68    atspi_reg_write(dsc, REG_XOSC_CTRL, XTAL_MODE_EXT << XTAL_MODE_SHIFT);
69#endif
70    atspi_reg_write(dsc, REG_TRX_CTRL_0, 0); /* disable CLKM */
71
72    (void) atspi_reg_read(dsc, REG_IRQ_STATUS);
73
74    return dsc;
75}
76
77
78static void set_channel(struct atspi_dsc *dsc, int channel)
79{
80    atspi_reg_write(dsc, REG_PHY_CC_CCA, (1 << CCA_MODE_SHIFT) | channel);
81}
82
83
84static void set_power(struct atspi_dsc *dsc, double power, int crc)
85{
86    int n;
87
88    for (n = 0; n != sizeof(tx_pwr)/sizeof(*tx_pwr)-1; n++)
89        if (tx_pwr[n] <= power)
90            break;
91    if (fabs(tx_pwr[n]-power) > 0.01)
92        fprintf(stderr, "TX power %.1f dBm\n", tx_pwr[n]);
93    atspi_reg_write(dsc, REG_PHY_TX_PWR, (crc ? TX_AUTO_CRC_ON : 0) | n);
94}
95
96
97static void receive(struct atspi_dsc *dsc)
98{
99    uint8_t buf[MAX_PSDU+1]; /* PSDU+LQI */
100    int n, ok, i;
101    uint8_t ed, lqi;
102
103    atspi_reg_write(dsc, REG_TRX_STATE, TRX_CMD_RX_ON);
104    /*
105     * 180 us, according to AVR2001 section 4.2. We time out after
106     * nominally 200 us.
107     */
108    wait_for_interrupt(dsc, IRQ_PLL_LOCK, IRQ_PLL_LOCK, 10, 20);
109
110    fprintf(stderr, "Ready.\n");
111    wait_for_interrupt(dsc, IRQ_TRX_END, IRQ_TRX_END | IRQ_RX_START,
112        10, 0);
113    if (!run)
114        return;
115
116    n = atspi_buf_read(dsc, buf, sizeof(buf));
117    if (n < 0)
118        exit(1);
119    if (n < 3) {
120        fprintf(stderr, "%d bytes received\n", n);
121        exit(1);
122    }
123    ed = atspi_reg_read(dsc, REG_PHY_ED_LEVEL);
124    ok = !!(atspi_reg_read(dsc, REG_PHY_RSSI) & RX_CRC_VALID);
125    lqi = buf[n-1];
126    fprintf(stderr, "%d bytes payload, CRC %s, LQI %u, ED %d dBm\n",
127        n-3, ok ? "OK" : "BAD", lqi, -91+ed);
128    for (i = 0; i != n-3; i++)
129        putchar(buf[i] < ' ' || buf[i] > '~' ? '?' : buf[i]);
130    putchar('\n');
131}
132
133
134static void transmit(struct atspi_dsc *dsc, const char *msg, int times)
135{
136    uint8_t buf[MAX_PSDU];
137
138    atspi_reg_write(dsc, REG_TRX_STATE, TRX_CMD_PLL_ON);
139    /*
140     * 180 us, according to AVR2001 section 4.3. We time out after
141     * nominally 200 us.
142     */
143    wait_for_interrupt(dsc, IRQ_PLL_LOCK, IRQ_PLL_LOCK, 10, 20);
144
145    /*
146     * We need to copy the message to append the CRC placeholders.
147     */
148    strcpy((void *) buf, msg);
149    atspi_buf_write(dsc, buf, strlen(msg)+2);
150
151    while (run && times--) {
152        /* @@@ should wait for clear channel */
153        atspi_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TX_START);
154
155        /* wait up to 10 ms (nominally) */
156        wait_for_interrupt(dsc, IRQ_TRX_END,
157           IRQ_TRX_END | IRQ_PLL_LOCK, 10, 1000);
158    }
159}
160
161
162static void test_mode(struct atspi_dsc *dsc, uint8_t cont_tx)
163{
164    atspi_buf_write(dsc, "", 1);
165    atspi_reg_write(dsc, REG_CONT_TX_0, CONT_TX_MAGIC);
166    atspi_reg_write(dsc, REG_CONT_TX_1, cont_tx);
167
168    if (!atspi_test_mode(dsc)) {
169        atspi_reset_rf(dsc);
170        fprintf(stderr, "device does not support test mode\n");
171        exit(1);
172    }
173
174    atspi_reg_write(dsc, REG_TRX_STATE, TRX_CMD_PLL_ON);
175    wait_for_interrupt(dsc, IRQ_PLL_LOCK, IRQ_PLL_LOCK, 10, 20);
176
177    atspi_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TX_START);
178
179    while (run)
180        sleep(1);
181    atspi_reset_rf(dsc);
182}
183
184
185static void die(int sig)
186{
187    run = 0;
188}
189
190
191static void usage(const char *name)
192{
193    fprintf(stderr,
194"usage: %s [-c channel] [-p power] [-t trim] [message [repetitions]]\n"
195" %s [-c channel] [-p power] [-t trim] -T delta\n"
196" -c channel channel number, 11 to 26 (default %d)\n"
197" -p power transmit power, -17.2 to 3.0 dBm (default %.1f)\n"
198" -t trim trim capacitor, 0 to 15 (default 0)\n"
199" -t trim trim capacitor, 0 to 15 (default 0)\n"
200" -T delta_MHz test mode. delta_MHz is -2, -0.5, or +0.5\n"
201        , name, name, DEFAULT_CHANNEL, DEFAULT_POWER);
202    exit(1);
203}
204
205
206int main(int argc, char *const *argv)
207{
208    int channel = DEFAULT_CHANNEL;
209    double power = DEFAULT_POWER;
210    int trim = 0, times = 1;
211    uint8_t cont_tx = 0;
212    char *end;
213    int c;
214    struct atspi_dsc *dsc;
215
216    while ((c = getopt(argc, argv, "c:p:t:T:")) != EOF)
217        switch (c) {
218        case 'c':
219            channel = strtoul(optarg, &end, 0);
220            if (*end)
221                usage(*argv);
222            if (channel < 11 || channel > 26)
223                usage(*argv);
224            break;
225        case 'p':
226            power = strtod(optarg, &end);
227            if (*end)
228                usage(*argv);
229            break;
230        case 't':
231            trim = strtoul(optarg, &end, 0);
232            if (*end)
233                usage(*argv);
234            if (trim > 15)
235                usage(*argv);
236            break;
237        case 'T':
238            if (!strcmp(optarg, "-2"))
239                cont_tx = CONT_TX_M2M;
240            else if (!strcmp(optarg, "-0.5"))
241                cont_tx = CONT_TX_M500K;
242            else if (!strcmp(optarg, "+0.5"))
243                cont_tx = CONT_TX_P500K;
244            else
245                usage(*argv);
246            break;
247        default:
248            usage(*argv);
249        }
250
251    signal(SIGINT, die);
252
253    switch (argc-optind) {
254    case 0:
255        dsc = init_txrx(trim);
256        set_channel(dsc, channel);
257        if (!cont_tx)
258            receive(dsc);
259        else {
260            set_power(dsc, power, 0);
261            test_mode(dsc, cont_tx);
262        }
263        break;
264    case 2:
265        times = strtoul(argv[optind+1], &end, 0);
266        if (*end)
267            usage(*argv);
268        /* fall through */
269    case 1:
270        if (cont_tx)
271            usage(*argv);
272        dsc = init_txrx(trim);
273        set_channel(dsc, channel);
274        set_power(dsc, power, 1);
275        transmit(dsc, argv[optind], times);
276        break;
277    default:
278        usage(*argv);
279    }
280
281    atspi_close(dsc);
282
283    return 0;
284}
285

Archive Download this file



interactive