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