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