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