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