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