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