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