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