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