IEEE 802.15.4 subsystem
Sign in or create your account | Project List | Help
IEEE 802.15.4 subsystem Git Source Tree
Root/
Source at commit 624caeb00652f6118dc64698b7dad6fa3e5bdcc2 created 7 years 5 days ago. By Werner Almesberger, atusb/: use VR, POWERED, and LED from kicad-libs | |
---|---|
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 | |
31 | static int verbose = 0; |
32 | |
33 | |
34 | static 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 | |
46 | static 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 | |
61 | static 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 | |
69 | static 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 | |
125 | static 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 | |
136 | static 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 | |
151 | int 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 |