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