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