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