Switch from GPLv2 to GPLv2+
[fw/altos] / src / drivers / ao_cc1200.c
1 /*
2  * Copyright © 2012 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18
19 #include <ao.h>
20 #include <ao_cc1200.h>
21 #include <ao_exti.h>
22 #include <ao_fec.h>
23 #include <ao_packet.h>
24 #if HAS_PAD
25 #include <ao_pad.h>
26 #endif
27
28 static uint8_t ao_radio_mutex;
29
30 static uint8_t ao_radio_wake;           /* radio ready. Also used as sleep address */
31 static uint8_t ao_radio_abort;          /* radio operation should abort */
32
33 int8_t  ao_radio_rssi;                  /* Last received RSSI value */
34
35 #ifndef CC1200_DEBUG
36 #define CC1200_DEBUG            0
37 #endif
38
39 #ifndef CC1200_LOW_LEVEL_DEBUG
40 #define CC1200_LOW_LEVEL_DEBUG  0
41 #endif
42
43 #define CC1200_TRACE            0
44 #define CC1200_APRS_TRACE       0
45
46 extern const uint32_t   ao_radio_cal;
47
48 #ifdef AO_CC1200_FOSC
49 #define FOSC    AO_CC1200_FOSC
50 #else
51 #define FOSC    40000000
52 #endif
53
54 #define ao_radio_select()       ao_spi_get_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS,AO_SPI_SPEED_FAST)
55 #define ao_radio_deselect()     ao_spi_put_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS)
56 #define ao_radio_spi_send(d,l)  ao_spi_send((d), (l), AO_CC1200_SPI_BUS)
57 #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1200_SPI_BUS)
58 #define ao_radio_spi_recv(d,l)  ao_spi_recv((d), (l), AO_CC1200_SPI_BUS)
59 #define ao_radio_duplex(o,i,l)  ao_spi_duplex((o), (i), (l), AO_CC1200_SPI_BUS)
60
61 static uint8_t
62 ao_radio_reg_read(uint16_t addr)
63 {
64         uint8_t data[2];
65         uint8_t d;
66
67 #if CC1200_TRACE
68         printf("\t\tao_radio_reg_read (%04x): ", addr); flush();
69 #endif
70         if (CC1200_IS_EXTENDED(addr)) {
71                 data[0] = ((1 << CC1200_READ)  |
72                            (0 << CC1200_BURST) |
73                            CC1200_EXTENDED);
74                 data[1] = addr;
75                 d = 2;
76         } else {
77                 data[0] = ((1 << CC1200_READ)  |
78                            (0 << CC1200_BURST) |
79                            addr);
80                 d = 1;
81         }
82         ao_radio_select();
83         ao_radio_spi_send(data, d);
84         ao_radio_spi_recv(data, 1);
85         ao_radio_deselect();
86 #if CC1200_TRACE
87         printf (" %02x\n", data[0]);
88 #endif
89         return data[0];
90 }
91
92 static void
93 ao_radio_reg_write(uint16_t addr, uint8_t value)
94 {
95         uint8_t data[3];
96         uint8_t d;
97
98 #if CC1200_TRACE
99         printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value);
100 #endif
101         if (CC1200_IS_EXTENDED(addr)) {
102                 data[0] = ((0 << CC1200_READ)  |
103                            (0 << CC1200_BURST) |
104                            CC1200_EXTENDED);
105                 data[1] = addr;
106                 d = 2;
107         } else {
108                 data[0] = ((0 << CC1200_READ)  |
109                            (0 << CC1200_BURST) |
110                            addr);
111                 d = 1;
112         }
113         data[d] = value;
114         ao_radio_select();
115         ao_radio_spi_send(data, d+1);
116         ao_radio_deselect();
117 #if CC1200_TRACE
118         (void) ao_radio_reg_read(addr);
119 #endif
120 }
121
122 static uint8_t
123 ao_radio_strobe(uint8_t addr)
124 {
125         uint8_t in;
126
127 #if CC1200_TRACE
128         printf("\t\tao_radio_strobe (%02x): ", addr); flush();
129 #endif
130         ao_radio_select();
131         ao_radio_duplex(&addr, &in, 1);
132         ao_radio_deselect();
133 #if CC1200_TRACE
134         printf("%02x\n", in); flush();
135 #endif
136         return in;
137 }
138
139 static uint8_t
140 ao_radio_fifo_read(uint8_t *data, uint8_t len)
141 {
142         uint8_t addr = ((1 << CC1200_READ)  |
143                         (1 << CC1200_BURST) |
144                         CC1200_FIFO);
145         uint8_t status;
146
147         ao_radio_select();
148         ao_radio_duplex(&addr, &status, 1);
149         ao_radio_spi_recv(data, len);
150         ao_radio_deselect();
151         return status;
152 }
153
154 static uint8_t
155 ao_radio_fifo_write_start(void)
156 {
157         uint8_t addr = ((0 << CC1200_READ)  |
158                         (1 << CC1200_BURST) |
159                         CC1200_FIFO);
160         uint8_t status;
161
162         ao_radio_select();
163         ao_radio_duplex(&addr, &status, 1);
164         return status;
165 }
166
167 static inline uint8_t ao_radio_fifo_write_stop(uint8_t status) {
168         ao_radio_deselect();
169         return status;
170 }
171
172 static uint8_t
173 ao_radio_fifo_write(const uint8_t *data, uint8_t len)
174 {
175         uint8_t status = ao_radio_fifo_write_start();
176         ao_radio_spi_send(data, len);
177         return ao_radio_fifo_write_stop(status);
178 }
179
180 static uint8_t
181 ao_radio_fifo_write_fixed(uint8_t data, uint8_t len)
182 {
183         uint8_t status = ao_radio_fifo_write_start();
184         ao_radio_spi_send_fixed(data, len);
185         return ao_radio_fifo_write_stop(status);
186 }
187
188 static uint8_t
189 ao_radio_int_pin(void)
190 {
191         return ao_gpio_get(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_CC1200_INT);
192 }
193
194 static uint8_t
195 ao_radio_status(void)
196 {
197         return ao_radio_strobe (CC1200_SNOP);
198 }
199
200 void
201 ao_radio_recv_abort(void)
202 {
203         ao_radio_abort = 1;
204         ao_wakeup(&ao_radio_wake);
205 }
206
207 #define ao_radio_rdf_value 0x55
208
209 static void
210 ao_radio_isr(void)
211 {
212         ao_exti_disable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
213         ao_radio_wake = 1;
214         ao_wakeup(&ao_radio_wake);
215 }
216
217 static void
218 ao_radio_start_tx(void)
219 {
220         ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
221         ao_radio_strobe(CC1200_STX);
222 }
223
224 static void
225 ao_radio_start_rx(void)
226 {
227         ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
228         ao_radio_strobe(CC1200_SRX);
229 }
230
231 static void
232 ao_radio_idle(void)
233 {
234         for (;;) {
235                 uint8_t state = (ao_radio_strobe(CC1200_SIDLE) >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK;
236                 if (state == CC1200_STATUS_STATE_IDLE)
237                         break;
238                 if (state == CC1200_STATUS_STATE_TX_FIFO_ERROR)
239                         ao_radio_strobe(CC1200_SFTX);
240                 if (state == CC1200_STATUS_STATE_RX_FIFO_ERROR)
241                         ao_radio_strobe(CC1200_SFRX);
242         }
243         /* Flush any pending data in the fifos */
244         ao_radio_strobe(CC1200_SFTX);
245         ao_radio_strobe(CC1200_SFRX);
246         /* Make sure the RF calibration is current */
247         ao_radio_strobe(CC1200_SCAL);
248 }
249
250 /*
251  * Packet deviation
252  *
253  *      fdev = fosc >> 22 * (256 + dev_m) << dev_e
254  *
255  * Deviation for 38400 baud should be 20.5kHz:
256  *
257  *      40e6 / (2 ** 22) * (256 + 13) * (2 ** 3) = 20523Hz
258  *
259  * Deviation for 9600 baud should be 5.125kHz:
260  *
261  *      40e6 / (2 ** 22) * (256 + 13) * (2 ** 1) = 5131Hz
262  *
263  * Deviation for 2400 baud should be 1.28125kHz, but cc1111 and
264  * cc115l can't do that, so we'll use 1.5kHz instead:
265  *
266  *      40e6 / (2 ** 21) * (79) = 1506Hz
267  */
268
269 #define PACKET_DEV_M_384        13
270 #define PACKET_DEV_E_384        3
271
272 #define PACKET_DEV_M_96         13
273 #define PACKET_DEV_E_96         1
274
275 #define PACKET_DEV_M_24         79
276 #define PACKET_DEV_E_24         0
277
278 /*
279  * For our packet data
280  *
281  *              (2**20 + DATARATE_M) * 2 ** DATARATE_E
282  *      Rdata = -------------------------------------- * fosc
283  *                           2 ** 39
284  *
285  * Given the bit period of the baseband, T, the bandwidth of the
286  * baseband signal is B = 1/(2T).  The overall bandwidth of the
287  * modulated signal is then Channel bandwidth = 2Δf + 2B.
288  *
289  * 38400 -- 2 * 20500 + 38400 = 79.4 kHz
290  *  9600 -- 2 * 5.125 +  9600 = 19.9 kHz
291  *  2400 -- 2 * 1.5   +  2400 =  5.4 khz
292  *
293  * Symbol rate 38400 Baud:
294  *
295  *      DATARATE_M = 1013008
296  *      DATARATE_E = 8
297  *      CHANBW = 104.16667
298  *
299  * Symbol rate 9600 Baud:
300  *
301  *      DATARATE_M = 1013008
302  *      DATARATE_E = 6
303  *      CHANBW = 26.042 (round to 19.8)
304  *
305  * Symbol rate 2400 Baud:
306  *
307  *      DATARATE_M = 1013008
308  *      DATARATE_E = 4
309  *      CHANBW = 5.0 (round to 9.5)
310  */
311
312 #if FOSC == 40000000
313 #define PACKET_SYMBOL_RATE_M            1013008
314 #define PACKET_SYMBOL_RATE_E_384        8
315 #define PACKET_SYMBOL_RATE_E_96         6
316 #define PACKET_SYMBOL_RATE_E_24         4
317 #endif
318
319 #if FOSC == 32000000
320 #define PACKET_SYMBOL_RATE_M            239914
321 #define PACKET_SYMBOL_RATE_E_384        9
322 #define PACKET_SYMBOL_RATE_E_96         7
323 #define PACKET_SYMBOL_RATE_E_24         5
324 #endif
325
326 /* 200 / 2 = 100 */
327 #define PACKET_CHAN_BW_384      ((CC1200_CHAN_BW_ADC_CIC_DECFACT_12 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
328                                  (16 << CC1200_CHAN_BW_BB_CIC_DECFACT))
329
330 /* 200 / 10 = 20 */
331 #define PACKET_CHAN_BW_96       ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
332                                  (16 << CC1200_CHAN_BW_BB_CIC_DECFACT))
333
334 /* 200 / 25 = 8 */
335 #define PACKET_CHAN_BW_24       ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
336                                  (44 << CC1200_CHAN_BW_BB_CIC_DECFACT))
337
338 static const uint16_t packet_setup[] = {
339         CC1200_SYMBOL_RATE1,            ((PACKET_SYMBOL_RATE_M >> 8) & 0xff),
340         CC1200_SYMBOL_RATE0,            ((PACKET_SYMBOL_RATE_M >> 0) & 0xff),
341         CC1200_PKT_CFG2,                                 /* Packet Configuration Reg. 2 */
342                 ((0 << CC1200_PKT_CFG2_FG_MODE_EN) |
343                  (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
344                  (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
345         CC1200_PKT_CFG1,                                 /* Packet Configuration Reg. 1 */
346                 ((1 << CC1200_PKT_CFG1_FEC_EN) |
347                  (1 << CC1200_PKT_CFG1_WHITE_DATA) |
348                  (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) |
349                  (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
350                  (CC1200_PKT_CFG1_CRC_CFG_CRC16_INIT_ONES << CC1200_PKT_CFG1_CRC_CFG) |
351                  (1 << CC1200_PKT_CFG1_APPEND_STATUS)),
352         CC1200_PREAMBLE_CFG1,   ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
353                                  (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
354 };
355
356 static const uint16_t packet_setup_384[] = {
357         CC1200_DEVIATION_M,     PACKET_DEV_M_384,
358         CC1200_MODCFG_DEV_E,    ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
359                                  (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
360                                  (PACKET_DEV_E_384 << CC1200_MODCFG_DEV_E_DEV_E)),
361         CC1200_SYMBOL_RATE2,    ((PACKET_SYMBOL_RATE_E_384 << CC1200_SYMBOL_RATE2_DATARATE_E) |
362                                  (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
363         CC1200_CHAN_BW,         PACKET_CHAN_BW_384,
364         CC1200_MDMCFG2,                                  /* General Modem Parameter Configuration Reg. 2 */
365                 ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
366                  (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
367                  (CC1200_MDMCFG2_UPSAMPLER_P_8 << CC1200_MDMCFG2_UPSAMPLER_P) |
368                  (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
369 };
370
371 static const uint16_t packet_setup_96[] = {
372         CC1200_DEVIATION_M,     PACKET_DEV_M_96,
373         CC1200_MODCFG_DEV_E,    ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
374                                  (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
375                                  (PACKET_DEV_E_96 << CC1200_MODCFG_DEV_E_DEV_E)),
376         CC1200_SYMBOL_RATE2,    ((PACKET_SYMBOL_RATE_E_96 << CC1200_SYMBOL_RATE2_DATARATE_E) |
377                                  (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
378         CC1200_CHAN_BW,         PACKET_CHAN_BW_96,
379         CC1200_MDMCFG2,                                  /* General Modem Parameter Configuration Reg. 2 */
380                 ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
381                  (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
382                  (CC1200_MDMCFG2_UPSAMPLER_P_32 << CC1200_MDMCFG2_UPSAMPLER_P) |
383                  (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
384 };
385
386 static const uint16_t packet_setup_24[] = {
387         CC1200_DEVIATION_M,     PACKET_DEV_M_24,
388         CC1200_MODCFG_DEV_E,    ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
389                                  (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
390                                  (PACKET_DEV_E_24 << CC1200_MODCFG_DEV_E_DEV_E)),
391         CC1200_SYMBOL_RATE2,    ((PACKET_SYMBOL_RATE_E_24 << CC1200_SYMBOL_RATE2_DATARATE_E) |
392                                  (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
393         CC1200_CHAN_BW,         PACKET_CHAN_BW_24,
394         CC1200_MDMCFG2,                                  /* General Modem Parameter Configuration Reg. 2 */
395                 ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
396                  (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
397                  (CC1200_MDMCFG2_UPSAMPLER_P_64 << CC1200_MDMCFG2_UPSAMPLER_P) |
398                  (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
399 };
400
401 /*
402  * RDF deviation is 3kHz
403  *
404  *      fdev = fosc >> 22 * (256 + dev_m) << dev_e      dev_e != 0
405  *      fdev = fosc >> 21 * dev_m                       dev_e == 0
406  *
407  *      40e6 / (2 ** 21) * 157 = 2995Hz
408  */
409
410 #define RDF_DEV_E       0
411 #define RDF_DEV_M       157
412
413 /*
414  * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
415  *
416  *              (2**20 + DATARATE_M) * 2 ** DATARATE_E
417  *      Rdata = -------------------------------------- * fosc
418  *                           2 ** 39
419  *
420  *      DATARATE_M = 669411
421  *      DATARATE_E = 4
422  *
423  * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
424  */
425 #define RDF_SYMBOL_RATE_E       4
426 #define RDF_SYMBOL_RATE_M       669411
427 #define RDF_PACKET_LEN  50
428
429 static const uint16_t rdf_setup[] = {
430         CC1200_DEVIATION_M,     RDF_DEV_M,
431         CC1200_MODCFG_DEV_E,    ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
432                                  (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
433                                  (RDF_DEV_E << CC1200_MODCFG_DEV_E_DEV_E)),
434         CC1200_SYMBOL_RATE2,    ((RDF_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) |
435                                  (((RDF_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
436         CC1200_SYMBOL_RATE1,    ((RDF_SYMBOL_RATE_M >> 8) & 0xff),
437         CC1200_SYMBOL_RATE0,    ((RDF_SYMBOL_RATE_M >> 0) & 0xff),
438         CC1200_PKT_CFG2,                                 /* Packet Configuration Reg. 2 */
439                 ((0 << CC1200_PKT_CFG2_FG_MODE_EN) |
440                  (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
441                  (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
442         CC1200_PKT_CFG1,                                 /* Packet Configuration Reg. 1 */
443                 ((0 << CC1200_PKT_CFG1_FEC_EN) |
444                  (0 << CC1200_PKT_CFG1_WHITE_DATA) |
445                  (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) |
446                  (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
447                  (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) |
448                  (0 << CC1200_PKT_CFG1_APPEND_STATUS)),
449         CC1200_PREAMBLE_CFG1,
450                 ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
451                  (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
452         CC1200_MDMCFG2,                                  /* General Modem Parameter Configuration Reg. 2 */
453                 ((0 << CC1200_MDMCFG2_ASK_SHAPE) |
454                  (0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
455                  (12 << CC1200_MDMCFG2_UPSAMPLER_P) |
456                  (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
457 };
458
459 /*
460  * APRS deviation is 3kHz
461  *
462  *      fdev = fosc >> 22 * (256 + dev_m) << dev_e      dev_e != 0
463  *      fdev = fosc >> 21 * dev_m                       dev_e == 0
464  *
465  *      40e6 / (2 ** 21) * 157 = 2995Hz
466  */
467
468 #define APRS_DEV_E      0
469 #define APRS_DEV_M      157
470
471 /*
472  * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate)
473  *
474  *              (2**20 + DATARATE_M) * 2 ** DATARATE_E
475  *      Rdata = -------------------------------------- * fosc
476  *                           2 ** 39
477  *
478  *      DATARATE_M = 1013008
479  *      DATARATE_E = 6
480  *
481  *      Rdata = 9599.998593330383301
482  *
483  */
484 #define APRS_SYMBOL_RATE_E      6
485 #define APRS_SYMBOL_RATE_M      1013008
486 #define APRS_BUFFER_SIZE        64
487
488 static const uint16_t aprs_setup[] = {
489         CC1200_DEVIATION_M,     APRS_DEV_M,
490         CC1200_MODCFG_DEV_E,    ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
491                                  (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
492                                  (APRS_DEV_E << CC1200_MODCFG_DEV_E_DEV_E)),
493         CC1200_SYMBOL_RATE2,    ((APRS_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) |
494                                  (((APRS_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
495         CC1200_SYMBOL_RATE1,    ((APRS_SYMBOL_RATE_M >> 8) & 0xff),
496         CC1200_SYMBOL_RATE0,    ((APRS_SYMBOL_RATE_M >> 0) & 0xff),
497         CC1200_PKT_CFG2,                                 /* Packet Configuration Reg. 2 */
498                 ((0 << CC1200_PKT_CFG2_FG_MODE_EN) |
499                  (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
500                  (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
501         CC1200_PKT_CFG1,                                 /* Packet Configuration Reg. 1 */
502                 ((0 << CC1200_PKT_CFG1_FEC_EN) |
503                  (0 << CC1200_PKT_CFG1_WHITE_DATA) |
504                  (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) |
505                  (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
506                  (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) |
507                  (0 << CC1200_PKT_CFG1_APPEND_STATUS)),
508         CC1200_PKT_CFG0,                                 /* Packet Configuration Reg. 0 */
509                 ((CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) |
510                  (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) |
511                  (0 << CC1200_PKT_CFG0_UART_MODE_EN) |
512                  (0 << CC1200_PKT_CFG0_UART_SWAP_EN)),
513         CC1200_PREAMBLE_CFG1,
514                 ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
515                  (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
516         CC1200_MDMCFG2,                                  /* General Modem Parameter Configuration Reg. 2 */
517                 ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
518                  (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
519                  (CC1200_MDMCFG2_UPSAMPLER_P_8 << CC1200_MDMCFG2_UPSAMPLER_P) |
520                  (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
521         CC1200_FIFO_CFG,
522                 ((0 << CC1200_FIFO_CFG_CRC_AUTOFLUSH) |
523                  (APRS_BUFFER_SIZE << CC1200_FIFO_CFG_FIFO_THR)),
524 };
525
526 /*
527  * For Test mode, we want an unmodulated carrier. To do that, we
528  * set the deviation to zero and enable a preamble so that the radio
529  * turns on before we send any data
530  */
531
532 static const uint16_t test_setup[] = {
533         CC1200_DEVIATION_M,     0,
534         CC1200_MODCFG_DEV_E,    ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
535                                  (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
536                                  (0 << CC1200_MODCFG_DEV_E_DEV_E)),
537         CC1200_SYMBOL_RATE2,            ((APRS_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) |
538                                  (((APRS_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
539         CC1200_SYMBOL_RATE1,            ((APRS_SYMBOL_RATE_M >> 8) & 0xff),
540         CC1200_SYMBOL_RATE0,            ((APRS_SYMBOL_RATE_M >> 0) & 0xff),
541         CC1200_PKT_CFG2,        ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
542                                  (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
543         CC1200_PKT_CFG1,        ((0 << CC1200_PKT_CFG1_WHITE_DATA) |
544                                  (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
545                                  (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) |
546                                  (0 << CC1200_PKT_CFG1_APPEND_STATUS)),
547         CC1200_PREAMBLE_CFG1,   ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
548                                  (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
549 };
550
551 #define AO_PKT_CFG0_INFINITE ((CC1200_PKT_CFG0_LENGTH_CONFIG_INFINITE << CC1200_PKT_CFG0_LENGTH_CONFIG) | \
552                               (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) |      \
553                               (0 << CC1200_PKT_CFG0_UART_MODE_EN) |     \
554                               (0 << CC1200_PKT_CFG0_UART_SWAP_EN))
555
556 #define AO_PKT_CFG0_FIXED ((CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) | \
557                            (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) |         \
558                            (0 << CC1200_PKT_CFG0_UART_MODE_EN) |        \
559                            (0 << CC1200_PKT_CFG0_UART_SWAP_EN))
560
561 static uint16_t ao_radio_mode;
562
563 #define AO_RADIO_MODE_BITS_PACKET       1
564 #define AO_RADIO_MODE_BITS_TX_BUF       4
565 #define AO_RADIO_MODE_BITS_TX_FINISH    8
566 #define AO_RADIO_MODE_BITS_RX           16
567 #define AO_RADIO_MODE_BITS_RDF          32
568 #define AO_RADIO_MODE_BITS_APRS         64
569 #define AO_RADIO_MODE_BITS_TEST         128
570 #define AO_RADIO_MODE_BITS_INFINITE     256
571 #define AO_RADIO_MODE_BITS_FIXED        512
572
573 #define AO_RADIO_MODE_NONE              0
574 #define AO_RADIO_MODE_PACKET_TX         (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_FIXED    | AO_RADIO_MODE_BITS_TX_FINISH)
575 #define AO_RADIO_MODE_PACKET_RX         (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_FIXED    | AO_RADIO_MODE_BITS_RX)
576 #define AO_RADIO_MODE_RDF               (AO_RADIO_MODE_BITS_RDF    | AO_RADIO_MODE_BITS_FIXED    | AO_RADIO_MODE_BITS_TX_FINISH)
577 #define AO_RADIO_MODE_APRS_BUF          (AO_RADIO_MODE_BITS_APRS   | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
578 #define AO_RADIO_MODE_APRS_LAST_BUF     (AO_RADIO_MODE_BITS_APRS   | AO_RADIO_MODE_BITS_FIXED    | AO_RADIO_MODE_BITS_TX_BUF)
579 #define AO_RADIO_MODE_APRS_FINISH       (AO_RADIO_MODE_BITS_APRS   | AO_RADIO_MODE_BITS_FIXED    | AO_RADIO_MODE_BITS_TX_FINISH)
580 #define AO_RADIO_MODE_TEST              (AO_RADIO_MODE_BITS_TEST   | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
581
582 static void
583 _ao_radio_set_regs(const uint16_t *regs, int nreg)
584 {
585         int i;
586
587         for (i = 0; i < nreg; i++) {
588                 ao_radio_reg_write(regs[0], regs[1]);
589                 regs += 2;
590         }
591 }
592
593 #define ao_radio_set_regs(setup) _ao_radio_set_regs(setup, (sizeof (setup) / sizeof(setup[0])) >> 1)
594
595 static void
596 ao_radio_set_mode(uint16_t new_mode)
597 {
598         uint16_t changes;
599
600         if (new_mode == ao_radio_mode)
601                 return;
602
603         changes = new_mode & (~ao_radio_mode);
604
605         if (changes & AO_RADIO_MODE_BITS_PACKET) {
606                 ao_radio_set_regs(packet_setup);
607
608                 switch (ao_config.radio_rate) {
609                 default:
610                 case AO_RADIO_RATE_38400:
611                         ao_radio_set_regs(packet_setup_384);
612                         break;
613                 case AO_RADIO_RATE_9600:
614                         ao_radio_set_regs(packet_setup_96);
615                         break;
616                 case AO_RADIO_RATE_2400:
617                         ao_radio_set_regs(packet_setup_24);
618                         break;
619                 }
620         }
621
622         if (changes & AO_RADIO_MODE_BITS_TX_BUF) {
623                 ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_TXFIFO_THR);
624                 ao_exti_set_mode(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
625         }
626
627         if (changes & AO_RADIO_MODE_BITS_TX_FINISH) {
628                 ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_PKT_SYNC_RXTX);
629                 ao_exti_set_mode(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
630         }
631
632         if (changes & AO_RADIO_MODE_BITS_RX) {
633                 ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP);
634                 ao_exti_set_mode(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_HIGH);
635         }
636
637         if (changes & AO_RADIO_MODE_BITS_RDF)
638                 ao_radio_set_regs(rdf_setup);
639
640         if (changes & AO_RADIO_MODE_BITS_APRS)
641                 ao_radio_set_regs(aprs_setup);
642
643         if (changes & AO_RADIO_MODE_BITS_TEST)
644                 ao_radio_set_regs(test_setup);
645
646         if (changes & AO_RADIO_MODE_BITS_INFINITE)
647                 ao_radio_reg_write(CC1200_PKT_CFG0, AO_PKT_CFG0_INFINITE);
648
649         if (changes & AO_RADIO_MODE_BITS_FIXED)
650                 ao_radio_reg_write(CC1200_PKT_CFG0, AO_PKT_CFG0_FIXED);
651
652         ao_radio_mode = new_mode;
653 }
654
655 static const uint16_t radio_setup[] = {
656 #include "ao_cc1200_CC1200.h"
657 };
658
659 static uint8_t  ao_radio_configured = 0;
660
661 static void
662 ao_radio_setup(void)
663 {
664         ao_radio_strobe(CC1200_SRES);
665
666         ao_radio_set_regs(radio_setup);
667
668         ao_radio_mode = 0;
669
670         ao_radio_idle();
671
672         ao_config_get();
673
674         ao_radio_configured = 1;
675 }
676
677 static void
678 ao_radio_set_len(uint8_t len)
679 {
680         static uint8_t  last_len;
681
682         if (len != last_len) {
683                 ao_radio_reg_write(CC1200_PKT_LEN, len);
684                 last_len = len;
685         }
686 }
687
688 static void
689 ao_radio_get(uint8_t len)
690 {
691         static uint32_t last_radio_setting;
692         static uint8_t  last_radio_rate;
693
694         ao_mutex_get(&ao_radio_mutex);
695
696         if (!ao_radio_configured)
697                 ao_radio_setup();
698         if (ao_config.radio_setting != last_radio_setting) {
699                 ao_radio_reg_write(CC1200_FREQ2, ao_config.radio_setting >> 16);
700                 ao_radio_reg_write(CC1200_FREQ1, ao_config.radio_setting >> 8);
701                 ao_radio_reg_write(CC1200_FREQ0, ao_config.radio_setting);
702                 last_radio_setting = ao_config.radio_setting;
703                 ao_radio_strobe(CC1200_SCAL);
704         }
705         if (ao_config.radio_rate != last_radio_rate) {
706                 ao_radio_mode &= ~AO_RADIO_MODE_BITS_PACKET;
707                 last_radio_rate = ao_config.radio_rate;
708         }
709         ao_radio_set_len(len);
710 }
711
712 #define ao_radio_put()  ao_mutex_put(&ao_radio_mutex)
713
714 static inline uint8_t
715 ao_radio_state(void)
716 {
717         return (ao_radio_status() >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK;
718 }
719
720 #if CC1200_DEBUG
721 void
722 ao_radio_show_state(char *where)
723 {
724         printf("%s: state %d len %d rxbytes %d\n",
725                where, ao_radio_state(),
726                ao_radio_reg_read(CC1200_PKT_LEN),
727                ao_radio_reg_read(CC1200_NUM_RXBYTES));
728 }
729 #else
730 #define ao_radio_show_state(where)
731 #endif
732
733 /* Wait for the radio to signal an interrupt
734  */
735 static void
736 ao_radio_wait_isr(uint16_t timeout)
737 {
738         ao_arch_block_interrupts();
739         while (!ao_radio_wake && !ao_radio_abort)
740                 if (ao_sleep_for(&ao_radio_wake, timeout))
741                         ao_radio_abort = 1;
742         ao_arch_release_interrupts();
743 }
744
745 static void
746 ao_rdf_start(uint8_t len)
747 {
748         ao_radio_abort = 0;
749         ao_radio_get(len);
750
751         ao_radio_set_mode(AO_RADIO_MODE_RDF);
752         ao_radio_wake = 0;
753 }
754
755 static void
756 ao_radio_run(void)
757 {
758         ao_radio_wake = 0;
759         ao_radio_abort = 0;
760         ao_radio_start_tx();
761         ao_radio_wait_isr(0);
762         if (!ao_radio_wake)
763                 ao_radio_idle();
764         ao_radio_put();
765 }
766
767 void
768 ao_radio_rdf(void)
769 {
770         ao_rdf_start(AO_RADIO_RDF_LEN);
771
772         ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN);
773
774         ao_radio_run();
775 }
776
777 void
778 ao_radio_continuity(uint8_t c)
779 {
780         uint8_t i;
781         uint8_t status;
782
783         ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN);
784
785         status = ao_radio_fifo_write_start();
786         for (i = 0; i < 3; i++) {
787                 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
788                 if (i < c)
789                         ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN);
790                 else
791                         ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN);
792         }
793         ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
794         status = ao_radio_fifo_write_stop(status);
795         (void) status;
796         ao_radio_run();
797 }
798
799 void
800 ao_radio_rdf_abort(void)
801 {
802         ao_radio_abort = 1;
803         ao_wakeup(&ao_radio_wake);
804 }
805
806 static void
807 ao_radio_test_cmd(void)
808 {
809         uint8_t mode = 2;
810         static uint8_t radio_on;
811         ao_cmd_white();
812         if (ao_cmd_lex_c != '\n') {
813                 ao_cmd_decimal();
814                 mode = (uint8_t) ao_cmd_lex_u32;
815         }
816         mode++;
817         if ((mode & 2) && !radio_on) {
818 #if HAS_MONITOR
819                 ao_monitor_disable();
820 #endif
821 #if PACKET_HAS_SLAVE
822                 ao_packet_slave_stop();
823 #endif
824 #if HAS_PAD
825                 ao_pad_disable();
826 #endif
827                 ao_radio_get(0xff);
828                 ao_radio_set_mode(AO_RADIO_MODE_TEST);
829                 ao_radio_strobe(CC1200_STX);
830 #if CC1200_TRACE
831                 { int t;
832                         for (t = 0; t < 10; t++) {
833                                 printf ("status: %02x\n", ao_radio_status());
834                                 ao_delay(AO_MS_TO_TICKS(100));
835                         }
836                 }
837 #endif
838                 radio_on = 1;
839         }
840         if (mode == 3) {
841                 printf ("Hit a character to stop..."); flush();
842                 getchar();
843                 putchar('\n');
844         }
845         if ((mode & 1) && radio_on) {
846                 ao_radio_idle();
847                 ao_radio_put();
848                 radio_on = 0;
849 #if HAS_MONITOR
850                 ao_monitor_enable();
851 #endif
852 #if HAS_PAD
853                 ao_pad_enable();
854 #endif
855         }
856 }
857
858 void
859 ao_radio_send(const void *d, uint8_t size)
860 {
861         ao_radio_get(size);
862         ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX);
863
864         ao_radio_fifo_write(d, size);
865
866         ao_radio_run();
867 }
868
869 void
870 ao_radio_send_aprs(ao_radio_fill_func fill)
871 {
872         uint8_t buf[APRS_BUFFER_SIZE];
873         int     cnt;
874         int     total = 0;
875         uint8_t done = 0;
876         uint8_t started = 0;
877
878         ao_radio_abort = 0;
879         ao_radio_get(0xff);
880         ao_radio_wake = 0;
881         while (!done && !ao_radio_abort) {
882                 cnt = (*fill)(buf, sizeof(buf));
883                 if (cnt < 0) {
884                         done = 1;
885                         cnt = -cnt;
886                 }
887                 total += cnt;
888
889                 /* At the last buffer, set the total length */
890                 if (done)
891                         ao_radio_set_len(total & 0xff);
892
893                 /* Wait for some space in the fifo */
894                 while (started && ao_radio_int_pin() != 0 && !ao_radio_abort) {
895                         ao_radio_wake = 0;
896                         ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
897                         ao_radio_wait_isr(AO_MS_TO_TICKS(1000));
898                 }
899                 if (ao_radio_abort)
900                         break;
901
902                 if (done)
903                         ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
904                 else
905                         ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
906
907                 ao_radio_fifo_write(buf, cnt);
908                 if (!started) {
909                         ao_radio_strobe(CC1200_STX);
910                         started = 1;
911                 }
912         }
913         /* Wait for the transmitter to go idle */
914         while (started && ao_radio_int_pin() != 0 && !ao_radio_abort) {
915                 ao_radio_wake = 0;
916                 ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
917                 ao_radio_wait_isr(AO_MS_TO_TICKS(1000));
918         }
919         if (ao_radio_abort)
920                 ao_radio_idle();
921         ao_radio_put();
922 }
923
924 #if 0
925 static uint8_t
926 ao_radio_marc_state(void)
927 {
928         return ao_radio_reg_read(CC1200_MARCSTATE);
929 }
930
931 static uint8_t
932 ao_radio_modem_status1(void)
933 {
934         return ao_radio_reg_read(CC1200_MODEM_STATUS1);
935 }
936
937 static uint8_t
938 ao_radio_modem_status0(void)
939 {
940         return ao_radio_reg_read(CC1200_MODEM_STATUS0);
941 }
942
943 struct ao_radio_state {
944         char    where[4];
945         uint8_t marc_state;
946         uint8_t marc_status1;
947         uint8_t marc_status0;
948         uint8_t modem_status1;
949         uint8_t modem_status0;
950 };
951
952 static void
953 ao_radio_fill_state(char *where, struct ao_radio_state *s)
954 {
955         strcpy(s->where, where);
956         s->marc_state = ao_radio_marc_state();
957         s->marc_status1 = ao_radio_reg_read(CC1200_MARC_STATUS1);
958         s->marc_status0 = ao_radio_reg_read(CC1200_MARC_STATUS0);
959         s->modem_status1 = ao_radio_modem_status1();
960         s->modem_status0 = ao_radio_modem_status0();
961 }
962
963 static void
964 ao_radio_dump_state(struct ao_radio_state *s)
965 {
966         printf ("%s: marc %2x marc1 %2x marc0 %2x modem1 %2x modem0 %2x\n",
967                 s->where, s->marc_state, s->marc_status1, s->marc_status0, s->modem_status1, s->modem_status0);
968 }
969 #endif
970
971 uint8_t
972 ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout)
973 {
974         uint8_t success = 0;
975
976         ao_radio_abort = 0;
977         ao_radio_get(size - 2);
978         ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
979         ao_radio_wake = 0;
980         ao_radio_start_rx();
981
982         while (!ao_radio_abort) {
983                 ao_radio_wait_isr(timeout);
984                 if (ao_radio_wake) {
985                         uint8_t         marc_status1 = ao_radio_reg_read(CC1200_MARC_STATUS1);
986
987                         /* Check the receiver status to see what happened
988                          */
989                         switch (marc_status1) {
990                         case CC1200_MARC_STATUS1_RX_FINISHED:
991                         case CC1200_MARC_STATUS1_ADDRESS:
992                         case CC1200_MARC_STATUS1_CRC:
993                                 /* Normal return, go fetch the bytes from the FIFO
994                                  * and give them back to the caller
995                                  */
996                                 success = 1;
997                                 break;
998                         case CC1200_MARC_STATUS1_RX_TIMEOUT:
999                         case CC1200_MARC_STATUS1_RX_TERMINATION:
1000                         case CC1200_MARC_STATUS1_EWOR_SYNC_LOST:
1001                         case CC1200_MARC_STATUS1_MAXIMUM_LENGTH:
1002                         case CC1200_MARC_STATUS1_RX_FIFO_OVERFLOW:
1003                         case CC1200_MARC_STATUS1_RX_FIFO_UNDERFLOW:
1004                                 /* Something weird happened; reset the radio and
1005                                  * return failure
1006                                  */
1007                                 success = 0;
1008                                 break;
1009                         default:
1010                                 /* some other status; go wait for the radio to do something useful
1011                                  */
1012                                 continue;
1013                         }
1014                         break;
1015                 } else {
1016                         uint8_t modem_status1 = ao_radio_reg_read(CC1200_MODEM_STATUS1);
1017
1018                         /* Check to see if the packet header has been seen, in which case we'll
1019                          * want to keep waiting for the rest of the packet to appear
1020                          */
1021                         if (modem_status1 & (1 << CC1200_MODEM_STATUS1_SYNC_FOUND))
1022                         {
1023                                 ao_radio_abort = 0;
1024
1025                                 /* Set a timeout based on the packet length so that we make sure to
1026                                  * wait long enough to receive the whole thing.
1027                                  *
1028                                  * timeout = bits * FEC expansion / rate
1029                                  */
1030                                 switch (ao_config.radio_rate) {
1031                                 default:
1032                                 case AO_RADIO_RATE_38400:
1033                                         timeout = AO_MS_TO_TICKS(size * (8 * 2 * 10) / 384) + 1;
1034                                         break;
1035                                 case AO_RADIO_RATE_9600:
1036                                         timeout = AO_MS_TO_TICKS(size * (8 * 2 * 10) / 96) + 1;
1037                                         break;
1038                                 case AO_RADIO_RATE_2400:
1039                                         timeout = AO_MS_TO_TICKS(size * (8 * 2 * 10) / 24) + 1;
1040                                         break;
1041                                 }
1042                         }
1043                 }
1044         }
1045
1046         if (success) {
1047                 int8_t  rssi;
1048                 uint8_t status;
1049
1050                 status = ao_radio_fifo_read(d, size);
1051                 (void) status;
1052                 rssi = ((int8_t *) d)[size - 2];
1053                 ao_radio_rssi = rssi;
1054
1055                 /* Bound it to the representable range */
1056                 if (rssi > -11)
1057                         rssi = -11;
1058
1059                 /* Write it back to the packet */
1060                 ((int8_t *) d)[size-2] = AO_RADIO_FROM_RSSI(rssi);
1061         } else {
1062                 ao_radio_idle();
1063                 ao_radio_rssi = 0;
1064         }
1065
1066         ao_radio_put();
1067         return success;
1068 }
1069
1070
1071 #if CC1200_DEBUG
1072 static char *cc1200_state_name[] = {
1073         [CC1200_STATUS_STATE_IDLE] = "IDLE",
1074         [CC1200_STATUS_STATE_RX] = "RX",
1075         [CC1200_STATUS_STATE_TX] = "TX",
1076         [CC1200_STATUS_STATE_FSTXON] = "FSTXON",
1077         [CC1200_STATUS_STATE_CALIBRATE] = "CALIBRATE",
1078         [CC1200_STATUS_STATE_SETTLING] = "SETTLING",
1079         [CC1200_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
1080         [CC1200_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
1081 };
1082
1083 struct ao_cc1200_reg {
1084         uint16_t        addr;
1085         char            *name;
1086 };
1087
1088 static const struct ao_cc1200_reg ao_cc1200_reg[] = {
1089         { .addr = CC1200_IOCFG3,        .name = "IOCFG3" },
1090         { .addr = CC1200_IOCFG2,        .name = "IOCFG2" },
1091         { .addr = CC1200_IOCFG1,        .name = "IOCFG1" },
1092         { .addr = CC1200_IOCFG0,        .name = "IOCFG0" },
1093         { .addr = CC1200_SYNC3, .name = "SYNC3" },
1094         { .addr = CC1200_SYNC2, .name = "SYNC2" },
1095         { .addr = CC1200_SYNC1, .name = "SYNC1" },
1096         { .addr = CC1200_SYNC0, .name = "SYNC0" },
1097         { .addr = CC1200_SYNC_CFG1,     .name = "SYNC_CFG1" },
1098         { .addr = CC1200_SYNC_CFG0,     .name = "SYNC_CFG0" },
1099         { .addr = CC1200_DEVIATION_M,   .name = "DEVIATION_M" },
1100         { .addr = CC1200_MODCFG_DEV_E,  .name = "MODCFG_DEV_E" },
1101         { .addr = CC1200_DCFILT_CFG,    .name = "DCFILT_CFG" },
1102         { .addr = CC1200_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
1103         { .addr = CC1200_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
1104         { .addr = CC1200_IQIC,  .name = "IQIC" },
1105         { .addr = CC1200_CHAN_BW,       .name = "CHAN_BW" },
1106         { .addr = CC1200_MDMCFG2,       .name = "MDMCFG2" },
1107         { .addr = CC1200_MDMCFG1,       .name = "MDMCFG1" },
1108         { .addr = CC1200_MDMCFG0,       .name = "MDMCFG0" },
1109         { .addr = CC1200_SYMBOL_RATE2,  .name = "SYMBOL_RATE2" },
1110         { .addr = CC1200_SYMBOL_RATE1,  .name = "SYMBOL_RATE1" },
1111         { .addr = CC1200_SYMBOL_RATE0,  .name = "SYMBOL_RATE0" },
1112         { .addr = CC1200_AGC_REF,       .name = "AGC_REF" },
1113         { .addr = CC1200_AGC_CS_THR,    .name = "AGC_CS_THR" },
1114         { .addr = CC1200_AGC_GAIN_ADJUST,       .name = "AGC_GAIN_ADJUST" },
1115         { .addr = CC1200_AGC_CFG3,      .name = "AGC_CFG3" },
1116         { .addr = CC1200_AGC_CFG2,      .name = "AGC_CFG2" },
1117         { .addr = CC1200_AGC_CFG1,      .name = "AGC_CFG1" },
1118         { .addr = CC1200_AGC_CFG0,      .name = "AGC_CFG0" },
1119         { .addr = CC1200_FIFO_CFG,      .name = "FIFO_CFG" },
1120         { .addr = CC1200_DEV_ADDR,      .name = "DEV_ADDR" },
1121         { .addr = CC1200_SETTLING_CFG,  .name = "SETTLING_CFG" },
1122         { .addr = CC1200_FS_CFG,        .name = "FS_CFG" },
1123         { .addr = CC1200_WOR_CFG1,      .name = "WOR_CFG1" },
1124         { .addr = CC1200_WOR_CFG0,      .name = "WOR_CFG0" },
1125         { .addr = CC1200_WOR_EVENT0_MSB,        .name = "WOR_EVENT0_MSB" },
1126         { .addr = CC1200_WOR_EVENT0_LSB,        .name = "WOR_EVENT0_LSB" },
1127         { .addr = CC1200_RXDCM_TIME,            .name = "RXDCM_TIME" },
1128         { .addr = CC1200_PKT_CFG2,      .name = "PKT_CFG2" },
1129         { .addr = CC1200_PKT_CFG1,      .name = "PKT_CFG1" },
1130         { .addr = CC1200_PKT_CFG0,      .name = "PKT_CFG0" },
1131         { .addr = CC1200_RFEND_CFG1,    .name = "RFEND_CFG1" },
1132         { .addr = CC1200_RFEND_CFG0,    .name = "RFEND_CFG0" },
1133         { .addr = CC1200_PA_CFG1,       .name = "PA_CFG1" },
1134         { .addr = CC1200_PA_CFG0,       .name = "PA_CFG0" },
1135         { .addr = CC1200_PKT_LEN,       .name = "PKT_LEN" },
1136         { .addr = CC1200_IF_MIX_CFG,    .name = "IF_MIX_CFG" },
1137         { .addr = CC1200_FREQOFF_CFG,   .name = "FREQOFF_CFG" },
1138         { .addr = CC1200_TOC_CFG,       .name = "TOC_CFG" },
1139         { .addr = CC1200_MARC_SPARE,    .name = "MARC_SPARE" },
1140         { .addr = CC1200_ECG_CFG,       .name = "ECG_CFG" },
1141         { .addr = CC1200_EXT_CTRL,      .name = "EXT_CTRL" },
1142         { .addr = CC1200_RCCAL_FINE,    .name = "RCCAL_FINE" },
1143         { .addr = CC1200_RCCAL_COARSE,  .name = "RCCAL_COARSE" },
1144         { .addr = CC1200_RCCAL_OFFSET,  .name = "RCCAL_OFFSET" },
1145         { .addr = CC1200_FREQOFF1,      .name = "FREQOFF1" },
1146         { .addr = CC1200_FREQOFF0,      .name = "FREQOFF0" },
1147         { .addr = CC1200_FREQ2, .name = "FREQ2" },
1148         { .addr = CC1200_FREQ1, .name = "FREQ1" },
1149         { .addr = CC1200_FREQ0, .name = "FREQ0" },
1150         { .addr = CC1200_IF_ADC2,       .name = "IF_ADC2" },
1151         { .addr = CC1200_IF_ADC1,       .name = "IF_ADC1" },
1152         { .addr = CC1200_IF_ADC0,       .name = "IF_ADC0" },
1153         { .addr = CC1200_FS_DIG1,       .name = "FS_DIG1" },
1154         { .addr = CC1200_FS_DIG0,       .name = "FS_DIG0" },
1155         { .addr = CC1200_FS_CAL3,       .name = "FS_CAL3" },
1156         { .addr = CC1200_FS_CAL2,       .name = "FS_CAL2" },
1157         { .addr = CC1200_FS_CAL1,       .name = "FS_CAL1" },
1158         { .addr = CC1200_FS_CAL0,       .name = "FS_CAL0" },
1159         { .addr = CC1200_FS_CHP,        .name = "FS_CHP" },
1160         { .addr = CC1200_FS_DIVTWO,     .name = "FS_DIVTWO" },
1161         { .addr = CC1200_FS_DSM1,       .name = "FS_DSM1" },
1162         { .addr = CC1200_FS_DSM0,       .name = "FS_DSM0" },
1163         { .addr = CC1200_FS_DVC1,       .name = "FS_DVC1" },
1164         { .addr = CC1200_FS_DVC0,       .name = "FS_DVC0" },
1165         { .addr = CC1200_FS_LBI,        .name = "FS_LBI" },
1166         { .addr = CC1200_FS_PFD,        .name = "FS_PFD" },
1167         { .addr = CC1200_FS_PRE,        .name = "FS_PRE" },
1168         { .addr = CC1200_FS_REG_DIV_CML,        .name = "FS_REG_DIV_CML" },
1169         { .addr = CC1200_FS_SPARE,      .name = "FS_SPARE" },
1170         { .addr = CC1200_FS_VCO4,       .name = "FS_VCO4" },
1171         { .addr = CC1200_FS_VCO3,       .name = "FS_VCO3" },
1172         { .addr = CC1200_FS_VCO2,       .name = "FS_VCO2" },
1173         { .addr = CC1200_FS_VCO1,       .name = "FS_VCO1" },
1174         { .addr = CC1200_FS_VCO0,       .name = "FS_VCO0" },
1175         { .addr = CC1200_GBIAS6,        .name = "GBIAS6" },
1176         { .addr = CC1200_GBIAS5,        .name = "GBIAS5" },
1177         { .addr = CC1200_GBIAS4,        .name = "GBIAS4" },
1178         { .addr = CC1200_GBIAS3,        .name = "GBIAS3" },
1179         { .addr = CC1200_GBIAS2,        .name = "GBIAS2" },
1180         { .addr = CC1200_GBIAS1,        .name = "GBIAS1" },
1181         { .addr = CC1200_GBIAS0,        .name = "GBIAS0" },
1182         { .addr = CC1200_IFAMP, .name = "IFAMP" },
1183         { .addr = CC1200_LNA,   .name = "LNA" },
1184         { .addr = CC1200_RXMIX, .name = "RXMIX" },
1185         { .addr = CC1200_XOSC5, .name = "XOSC5" },
1186         { .addr = CC1200_XOSC4, .name = "XOSC4" },
1187         { .addr = CC1200_XOSC3, .name = "XOSC3" },
1188         { .addr = CC1200_XOSC2, .name = "XOSC2" },
1189         { .addr = CC1200_XOSC1, .name = "XOSC1" },
1190         { .addr = CC1200_XOSC0, .name = "XOSC0" },
1191         { .addr = CC1200_ANALOG_SPARE,  .name = "ANALOG_SPARE" },
1192         { .addr = CC1200_PA_CFG3,       .name = "PA_CFG3" },
1193         { .addr = CC1200_WOR_TIME1,     .name = "WOR_TIME1" },
1194         { .addr = CC1200_WOR_TIME0,     .name = "WOR_TIME0" },
1195         { .addr = CC1200_WOR_CAPTURE1,  .name = "WOR_CAPTURE1" },
1196         { .addr = CC1200_WOR_CAPTURE0,  .name = "WOR_CAPTURE0" },
1197         { .addr = CC1200_BIST,  .name = "BIST" },
1198         { .addr = CC1200_DCFILTOFFSET_I1,       .name = "DCFILTOFFSET_I1" },
1199         { .addr = CC1200_DCFILTOFFSET_I0,       .name = "DCFILTOFFSET_I0" },
1200         { .addr = CC1200_DCFILTOFFSET_Q1,       .name = "DCFILTOFFSET_Q1" },
1201         { .addr = CC1200_DCFILTOFFSET_Q0,       .name = "DCFILTOFFSET_Q0" },
1202         { .addr = CC1200_IQIE_I1,       .name = "IQIE_I1" },
1203         { .addr = CC1200_IQIE_I0,       .name = "IQIE_I0" },
1204         { .addr = CC1200_IQIE_Q1,       .name = "IQIE_Q1" },
1205         { .addr = CC1200_IQIE_Q0,       .name = "IQIE_Q0" },
1206         { .addr = CC1200_RSSI1, .name = "RSSI1" },
1207         { .addr = CC1200_RSSI0, .name = "RSSI0" },
1208         { .addr = CC1200_MARCSTATE,     .name = "MARCSTATE" },
1209         { .addr = CC1200_LQI_VAL,       .name = "LQI_VAL" },
1210         { .addr = CC1200_PQT_SYNC_ERR,  .name = "PQT_SYNC_ERR" },
1211         { .addr = CC1200_DEM_STATUS,    .name = "DEM_STATUS" },
1212         { .addr = CC1200_FREQOFF_EST1,  .name = "FREQOFF_EST1" },
1213         { .addr = CC1200_FREQOFF_EST0,  .name = "FREQOFF_EST0" },
1214         { .addr = CC1200_AGC_GAIN3,     .name = "AGC_GAIN3" },
1215         { .addr = CC1200_AGC_GAIN2,     .name = "AGC_GAIN2" },
1216         { .addr = CC1200_AGC_GAIN1,     .name = "AGC_GAIN1" },
1217         { .addr = CC1200_AGC_GAIN0,     .name = "AGC_GAIN0" },
1218         { .addr = CC1200_SOFT_RX_DATA_OUT,      .name = "SOFT_RX_DATA_OUT" },
1219         { .addr = CC1200_SOFT_TX_DATA_IN,       .name = "SOFT_TX_DATA_IN" },
1220         { .addr = CC1200_ASK_SOFT_RX_DATA,      .name = "ASK_SOFT_RX_DATA" },
1221         { .addr = CC1200_RNDGEN,        .name = "RNDGEN" },
1222         { .addr = CC1200_MAGN2, .name = "MAGN2" },
1223         { .addr = CC1200_MAGN1, .name = "MAGN1" },
1224         { .addr = CC1200_MAGN0, .name = "MAGN0" },
1225         { .addr = CC1200_ANG1,  .name = "ANG1" },
1226         { .addr = CC1200_ANG0,  .name = "ANG0" },
1227         { .addr = CC1200_CHFILT_I2,     .name = "CHFILT_I2" },
1228         { .addr = CC1200_CHFILT_I1,     .name = "CHFILT_I1" },
1229         { .addr = CC1200_CHFILT_I0,     .name = "CHFILT_I0" },
1230         { .addr = CC1200_CHFILT_Q2,     .name = "CHFILT_Q2" },
1231         { .addr = CC1200_CHFILT_Q1,     .name = "CHFILT_Q1" },
1232         { .addr = CC1200_CHFILT_Q0,     .name = "CHFILT_Q0" },
1233         { .addr = CC1200_GPIO_STATUS,   .name = "GPIO_STATUS" },
1234         { .addr = CC1200_FSCAL_CTRL,    .name = "FSCAL_CTRL" },
1235         { .addr = CC1200_PHASE_ADJUST,  .name = "PHASE_ADJUST" },
1236         { .addr = CC1200_PARTNUMBER,    .name = "PARTNUMBER" },
1237         { .addr = CC1200_PARTVERSION,   .name = "PARTVERSION" },
1238         { .addr = CC1200_SERIAL_STATUS, .name = "SERIAL_STATUS" },
1239         { .addr = CC1200_MODEM_STATUS1, .name = "MODEM_STATUS1" },
1240         { .addr = CC1200_MODEM_STATUS0, .name = "MODEM_STATUS0" },
1241         { .addr = CC1200_MARC_STATUS1,  .name = "MARC_STATUS1" },
1242         { .addr = CC1200_MARC_STATUS0,  .name = "MARC_STATUS0" },
1243         { .addr = CC1200_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
1244         { .addr = CC1200_FSRF_TEST,     .name = "FSRF_TEST" },
1245         { .addr = CC1200_PRE_TEST,      .name = "PRE_TEST" },
1246         { .addr = CC1200_PRE_OVR,       .name = "PRE_OVR" },
1247         { .addr = CC1200_ADC_TEST,      .name = "ADC_TEST" },
1248         { .addr = CC1200_DVC_TEST,      .name = "DVC_TEST" },
1249         { .addr = CC1200_ATEST, .name = "ATEST" },
1250         { .addr = CC1200_ATEST_LVDS,    .name = "ATEST_LVDS" },
1251         { .addr = CC1200_ATEST_MODE,    .name = "ATEST_MODE" },
1252         { .addr = CC1200_XOSC_TEST1,    .name = "XOSC_TEST1" },
1253         { .addr = CC1200_XOSC_TEST0,    .name = "XOSC_TEST0" },
1254         { .addr = CC1200_RXFIRST,       .name = "RXFIRST" },
1255         { .addr = CC1200_TXFIRST,       .name = "TXFIRST" },
1256         { .addr = CC1200_RXLAST,        .name = "RXLAST" },
1257         { .addr = CC1200_TXLAST,        .name = "TXLAST" },
1258         { .addr = CC1200_NUM_TXBYTES,   .name = "NUM_TXBYTES" },
1259         { .addr = CC1200_NUM_RXBYTES,   .name = "NUM_RXBYTES" },
1260         { .addr = CC1200_FIFO_NUM_TXBYTES,      .name = "FIFO_NUM_TXBYTES" },
1261         { .addr = CC1200_FIFO_NUM_RXBYTES,      .name = "FIFO_NUM_RXBYTES" },
1262 };
1263
1264 #define AO_NUM_CC1200_REG       (sizeof ao_cc1200_reg / sizeof ao_cc1200_reg[0])
1265
1266 static uint8_t
1267 ao_radio_get_marc_status(void)
1268 {
1269         return ao_radio_reg_read(CC1200_MARC_STATUS1);
1270 }
1271
1272 static void ao_radio_show(void) {
1273         uint8_t status;
1274         unsigned int    i;
1275
1276         ao_mutex_get(&ao_radio_mutex);
1277         status = ao_radio_status();
1278         printf ("Status:   %02x\n", status);
1279         printf ("CHIP_RDY: %d\n", (status >> CC1200_STATUS_CHIP_RDY) & 1);
1280         printf ("STATE:    %s\n", cc1200_state_name[(status >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK]);
1281         printf ("MARC:     %02x\n", ao_radio_get_marc_status());
1282
1283         for (i = 0; i < AO_NUM_CC1200_REG; i++)
1284                 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1200_reg[i].addr), ao_cc1200_reg[i].name);
1285
1286         ao_radio_put();
1287 }
1288
1289 static void ao_radio_beep(void) {
1290         ao_radio_rdf();
1291 }
1292
1293 static void ao_radio_packet(void) {
1294         static const uint8_t packet[] = {
1295 #if 1
1296                 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1297                 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1298                 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1299                 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1300 #else
1301                 3, 1, 2, 3
1302 #endif
1303         };
1304
1305         ao_radio_send(packet, sizeof (packet));
1306 }
1307
1308 void
1309 ao_radio_test_recv(void)
1310 {
1311         uint8_t bytes[34];
1312         uint8_t b;
1313
1314         if (ao_radio_recv(bytes, 34, 0)) {
1315                 if (bytes[33] & 0x80)
1316                         printf ("CRC OK");
1317                 else
1318                         printf ("CRC BAD");
1319                 printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32]));
1320                 for (b = 0; b < 32; b++)
1321                         printf (" %02x", bytes[b]);
1322
1323                 printf (" RSSI %02x LQI %02x", bytes[32], bytes[33]);
1324                 printf ("\n");
1325         }
1326 }
1327
1328 #if HAS_APRS
1329 #include <ao_aprs.h>
1330
1331 static void
1332 ao_radio_aprs(void)
1333 {
1334 #if PACKET_HAS_SLAVE
1335         ao_packet_slave_stop();
1336 #endif
1337         ao_aprs_send();
1338 }
1339 #endif
1340 #endif
1341
1342 #if CC1200_LOW_LEVEL_DEBUG
1343 static void
1344 ao_radio_strobe_test(void)
1345 {
1346         uint8_t r;
1347
1348         ao_cmd_hex();
1349         if (ao_cmd_status != ao_cmd_success)
1350                 return;
1351         r = ao_radio_strobe(ao_cmd_lex_i);
1352         printf ("Strobe %02x -> %02x (rdy %d state %d)\n",
1353                 ao_cmd_lex_i,
1354                 r,
1355                 r >> 7,
1356                 (r >> 4) & 0x7);
1357 }
1358
1359 static void
1360 ao_radio_write_test(void)
1361 {
1362         uint16_t        addr;
1363         uint8_t         data;
1364
1365         ao_cmd_hex();
1366         if (ao_cmd_status != ao_cmd_success)
1367                 return;
1368         addr = ao_cmd_lex_i;
1369         ao_cmd_hex();
1370         if (ao_cmd_status != ao_cmd_success)
1371                 return;
1372         data = ao_cmd_lex_i;
1373         printf ("Write %04x = %02x\n", addr, data);
1374         ao_radio_reg_write(addr, data);
1375 }
1376
1377 static void
1378 ao_radio_read_test(void)
1379 {
1380         uint16_t        addr;
1381         uint8_t         data;
1382
1383         ao_cmd_hex();
1384         if (ao_cmd_status != ao_cmd_success)
1385                 return;
1386         addr = ao_cmd_lex_i;
1387         data = ao_radio_reg_read(addr);
1388         printf ("Read %04x = %02x\n", addr, data);
1389 }
1390 #endif
1391
1392 static const struct ao_cmds ao_radio_cmds[] = {
1393         { ao_radio_test_cmd,    "C <1 start, 0 stop, none both>\0Radio carrier test" },
1394 #if CC1200_DEBUG
1395 #if HAS_APRS
1396         { ao_radio_aprs,        "G\0Send APRS packet" },
1397 #endif
1398         { ao_radio_show,        "R\0Show CC1200 status" },
1399         { ao_radio_beep,        "b\0Emit an RDF beacon" },
1400         { ao_radio_packet,      "p\0Send a test packet" },
1401         { ao_radio_test_recv,   "q\0Recv a test packet" },
1402 #endif
1403 #if CC1200_LOW_LEVEL_DEBUG
1404         { ao_radio_strobe_test, "A <value>\0Strobe radio" },
1405         { ao_radio_write_test,  "W <addr> <value>\0Write radio reg" },
1406         { ao_radio_read_test,   "B <addr>\0Read radio reg" },
1407 #endif
1408         { 0, NULL }
1409 };
1410
1411 void
1412 ao_radio_init(void)
1413 {
1414         ao_radio_configured = 0;
1415         ao_spi_init_cs (AO_CC1200_SPI_CS_PORT, (1 << AO_CC1200_SPI_CS_PIN));
1416
1417 #if 0
1418         AO_CC1200_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1200_SPI_CS_PIN));
1419         for (i = 0; i < 10000; i++) {
1420                 if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0)
1421                         break;
1422         }
1423         AO_CC1200_SPI_CS_PORT->bsrr = (1 << AO_CC1200_SPI_CS_PIN);
1424         if (i == 10000)
1425                 ao_panic(AO_PANIC_SELF_TEST_CC1200);
1426 #endif
1427
1428         /* Enable the EXTI interrupt for the appropriate pin */
1429         ao_enable_port(AO_CC1200_INT_PORT);
1430         ao_exti_setup(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN,
1431                       AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
1432                       ao_radio_isr);
1433
1434         ao_cmd_register(&ao_radio_cmds[0]);
1435 }