2 * Copyright © 2012 Keith Packard <keithp@keithp.com>
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.
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.
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.
19 #include <ao_cc1200.h>
22 #include <ao_packet.h>
27 static uint8_t ao_radio_mutex;
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 */
32 int8_t ao_radio_rssi; /* Last received RSSI value */
35 #define CC1200_DEBUG 0
38 #ifndef CC1200_LOW_LEVEL_DEBUG
39 #define CC1200_LOW_LEVEL_DEBUG 0
42 #define CC1200_TRACE 0
43 #define CC1200_APRS_TRACE 0
45 extern const uint32_t ao_radio_cal;
48 #define FOSC AO_CC1200_FOSC
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)
61 ao_radio_reg_read(uint16_t addr)
67 printf("\t\tao_radio_reg_read (%04x): ", addr); flush();
69 if (CC1200_IS_EXTENDED(addr)) {
70 data[0] = ((1 << CC1200_READ) |
76 data[0] = ((1 << CC1200_READ) |
82 ao_radio_spi_send(data, d);
83 ao_radio_spi_recv(data, 1);
86 printf (" %02x\n", data[0]);
92 ao_radio_reg_write(uint16_t addr, uint8_t value)
98 printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value);
100 if (CC1200_IS_EXTENDED(addr)) {
101 data[0] = ((0 << CC1200_READ) |
102 (0 << CC1200_BURST) |
107 data[0] = ((0 << CC1200_READ) |
108 (0 << CC1200_BURST) |
114 ao_radio_spi_send(data, d+1);
117 (void) ao_radio_reg_read(addr);
122 ao_radio_strobe(uint8_t addr)
127 printf("\t\tao_radio_strobe (%02x): ", addr); flush();
130 ao_radio_duplex(&addr, &in, 1);
133 printf("%02x\n", in); flush();
139 ao_radio_fifo_read(uint8_t *data, uint8_t len)
141 uint8_t addr = ((1 << CC1200_READ) |
142 (1 << CC1200_BURST) |
147 ao_radio_duplex(&addr, &status, 1);
148 ao_radio_spi_recv(data, len);
154 ao_radio_fifo_write_start(void)
156 uint8_t addr = ((0 << CC1200_READ) |
157 (1 << CC1200_BURST) |
162 ao_radio_duplex(&addr, &status, 1);
166 static inline uint8_t ao_radio_fifo_write_stop(uint8_t status) {
172 ao_radio_fifo_write(const uint8_t *data, uint8_t len)
174 uint8_t status = ao_radio_fifo_write_start();
175 ao_radio_spi_send(data, len);
176 return ao_radio_fifo_write_stop(status);
180 ao_radio_fifo_write_fixed(uint8_t data, uint8_t len)
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);
188 ao_radio_tx_fifo_space(void)
190 return CC1200_FIFO_SIZE - ao_radio_reg_read(CC1200_NUM_TXBYTES);
194 ao_radio_status(void)
196 return ao_radio_strobe (CC1200_SNOP);
200 ao_radio_recv_abort(void)
203 ao_wakeup(&ao_radio_wake);
206 #define ao_radio_rdf_value 0x55
211 ao_exti_disable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
213 ao_wakeup(&ao_radio_wake);
217 ao_radio_start_tx(void)
219 ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
220 ao_radio_strobe(CC1200_STX);
224 ao_radio_start_rx(void)
226 ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
227 ao_radio_strobe(CC1200_SRX);
234 uint8_t state = (ao_radio_strobe(CC1200_SIDLE) >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK;
235 if (state == CC1200_STATUS_STATE_IDLE)
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);
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);
252 * fdev = fosc >> 22 * (256 + dev_m) << dev_e
254 * Deviation for 38400 baud should be 20.5kHz:
256 * 40e6 / (2 ** 22) * (256 + 13) * (2 ** 3) = 20523Hz
258 * Deviation for 9600 baud should be 5.125kHz:
260 * 40e6 / (2 ** 22) * (256 + 13) * (2 ** 1) = 5131Hz
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:
265 * 40e6 / (2 ** 21) * (79) = 1506Hz
268 #define PACKET_DEV_M_384 13
269 #define PACKET_DEV_E_384 3
271 #define PACKET_DEV_M_96 13
272 #define PACKET_DEV_E_96 1
274 #define PACKET_DEV_M_24 79
275 #define PACKET_DEV_E_24 0
278 * For our packet data
280 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
281 * Rdata = -------------------------------------- * fosc
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.
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
292 * Symbol rate 38400 Baud:
294 * DATARATE_M = 1013008
298 * Symbol rate 9600 Baud:
300 * DATARATE_M = 1013008
302 * CHANBW = 26.042 (round to 19.8)
304 * Symbol rate 2400 Baud:
306 * DATARATE_M = 1013008
308 * CHANBW = 5.0 (round to 9.5)
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
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
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))
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))
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))
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)),
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)),
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)),
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)),
401 * RDF deviation is 3kHz
403 * fdev = fosc >> 22 * (256 + dev_m) << dev_e dev_e != 0
404 * fdev = fosc >> 21 * dev_m dev_e == 0
406 * 40e6 / (2 ** 21) * 157 = 2995Hz
410 #define RDF_DEV_M 157
413 * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
415 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
416 * Rdata = -------------------------------------- * fosc
419 * DATARATE_M = 669411
422 * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
424 #define RDF_SYMBOL_RATE_E 4
425 #define RDF_SYMBOL_RATE_M 669411
426 #define RDF_PACKET_LEN 50
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)),
459 * APRS deviation is 3kHz
461 * fdev = fosc >> 22 * (256 + dev_m) << dev_e dev_e != 0
462 * fdev = fosc >> 21 * dev_m dev_e == 0
464 * 40e6 / (2 ** 21) * 157 = 2995Hz
468 #define APRS_DEV_M 157
471 * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate)
473 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
474 * Rdata = -------------------------------------- * fosc
477 * DATARATE_M = 1013008
480 * Rdata = 9599.998593330383301
483 #define APRS_SYMBOL_RATE_E 6
484 #define APRS_SYMBOL_RATE_M 1013008
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)),
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
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)),
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))
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))
556 static uint16_t ao_radio_mode;
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
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)
578 _ao_radio_set_regs(const uint16_t *regs, int nreg)
582 for (i = 0; i < nreg; i++) {
583 ao_radio_reg_write(regs[0], regs[1]);
588 #define ao_radio_set_regs(setup) _ao_radio_set_regs(setup, (sizeof (setup) / sizeof(setup[0])) >> 1)
591 ao_radio_set_mode(uint16_t new_mode)
595 if (new_mode == ao_radio_mode)
598 changes = new_mode & (~ao_radio_mode);
600 if (changes & AO_RADIO_MODE_BITS_PACKET) {
601 ao_radio_set_regs(packet_setup);
603 switch (ao_config.radio_rate) {
605 case AO_RADIO_RATE_38400:
606 ao_radio_set_regs(packet_setup_384);
608 case AO_RADIO_RATE_9600:
609 ao_radio_set_regs(packet_setup_96);
611 case AO_RADIO_RATE_2400:
612 ao_radio_set_regs(packet_setup_24);
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);
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);
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);
632 if (changes & AO_RADIO_MODE_BITS_RDF)
633 ao_radio_set_regs(rdf_setup);
635 if (changes & AO_RADIO_MODE_BITS_APRS)
636 ao_radio_set_regs(aprs_setup);
638 if (changes & AO_RADIO_MODE_BITS_TEST)
639 ao_radio_set_regs(test_setup);
641 if (changes & AO_RADIO_MODE_BITS_INFINITE)
642 ao_radio_reg_write(CC1200_PKT_CFG0, AO_PKT_CFG0_INFINITE);
644 if (changes & AO_RADIO_MODE_BITS_FIXED)
645 ao_radio_reg_write(CC1200_PKT_CFG0, AO_PKT_CFG0_FIXED);
647 ao_radio_mode = new_mode;
650 static const uint16_t radio_setup[] = {
651 #include "ao_cc1200_CC1200.h"
654 static uint8_t ao_radio_configured = 0;
659 ao_radio_strobe(CC1200_SRES);
661 ao_radio_set_regs(radio_setup);
669 ao_radio_configured = 1;
673 ao_radio_set_len(uint8_t len)
675 static uint8_t last_len;
677 if (len != last_len) {
678 ao_radio_reg_write(CC1200_PKT_LEN, len);
684 ao_radio_get(uint8_t len)
686 static uint32_t last_radio_setting;
687 static uint8_t last_radio_rate;
689 ao_mutex_get(&ao_radio_mutex);
691 if (!ao_radio_configured)
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);
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;
704 ao_radio_set_len(len);
707 #define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
709 static inline uint8_t
712 return (ao_radio_status() >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK;
717 ao_radio_show_state(char *where)
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));
725 #define ao_radio_show_state(where)
728 /* Wait for the radio to signal an interrupt
731 ao_radio_wait_isr(uint16_t timeout)
733 ao_arch_block_interrupts();
734 while (!ao_radio_wake && !ao_radio_abort)
735 if (ao_sleep_for(&ao_radio_wake, timeout))
737 ao_arch_release_interrupts();
741 ao_rdf_start(uint8_t len)
746 ao_radio_set_mode(AO_RADIO_MODE_RDF);
756 ao_radio_wait_isr(0);
765 ao_rdf_start(AO_RADIO_RDF_LEN);
767 ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN);
773 ao_radio_continuity(uint8_t c)
778 ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN);
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);
784 ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN);
786 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN);
788 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
789 status = ao_radio_fifo_write_stop(status);
795 ao_radio_rdf_abort(void)
798 ao_wakeup(&ao_radio_wake);
802 ao_radio_test_cmd(void)
805 static uint8_t radio_on;
807 if (ao_cmd_lex_c != '\n') {
809 mode = (uint8_t) ao_cmd_lex_u32;
812 if ((mode & 2) && !radio_on) {
814 ao_monitor_disable();
817 ao_packet_slave_stop();
823 ao_radio_set_mode(AO_RADIO_MODE_TEST);
824 ao_radio_strobe(CC1200_STX);
827 for (t = 0; t < 10; t++) {
828 printf ("status: %02x\n", ao_radio_status());
829 ao_delay(AO_MS_TO_TICKS(100));
836 printf ("Hit a character to stop..."); flush();
840 if ((mode & 1) && radio_on) {
854 ao_radio_send(const void *d, uint8_t size)
857 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX);
859 ao_radio_fifo_write(d, size);
865 #define AO_RADIO_LOTS 64
868 ao_radio_send_aprs(ao_radio_fill_func fill)
870 uint8_t buf[AO_RADIO_LOTS], *b;
879 fifo_space = CC1200_FIFO_SIZE;
881 cnt = (*fill)(buf, sizeof(buf));
886 #if CC1200_APRS_TRACE
887 printf("APRS fill %d bytes done %d\n", cnt, done);
891 /* At the last buffer, set the total length */
893 ao_radio_set_len(total & 0xff);
897 uint8_t this_len = cnt;
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();
905 ao_radio_wait_isr(AO_MS_TO_TICKS(1000));
909 if (this_len > fifo_space)
910 this_len = fifo_space;
916 ao_radio_set_mode(AO_RADIO_MODE_APRS_LAST_BUF);
918 ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
920 ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
922 ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
924 ao_radio_fifo_write(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());
930 #if CC1200_APRS_TRACE
931 printf("APRS start\n");
933 ao_radio_strobe(CC1200_STX);
934 #if CC1200_APRS_TRACE
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)
942 ao_delay(AO_MS_TO_TICKS(0));
949 if (ao_radio_abort) {
954 /* Wait for the transmitter to go idle */
956 #if CC1200_APRS_TRACE
957 printf("APRS wait idle\n"); flush();
959 ao_radio_wait_isr(AO_MS_TO_TICKS(1000));
960 #if CC1200_APRS_TRACE
961 printf("APRS abort %d\n", ao_radio_abort);
968 ao_radio_marc_state(void)
970 return ao_radio_reg_read(CC1200_MARCSTATE);
974 ao_radio_modem_status1(void)
976 return ao_radio_reg_read(CC1200_MODEM_STATUS1);
980 ao_radio_modem_status0(void)
982 return ao_radio_reg_read(CC1200_MODEM_STATUS0);
985 struct ao_radio_state {
988 uint8_t marc_status1;
989 uint8_t marc_status0;
990 uint8_t modem_status1;
991 uint8_t modem_status0;
995 ao_radio_fill_state(char *where, struct ao_radio_state *s)
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();
1006 ao_radio_dump_state(struct ao_radio_state *s)
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);
1014 ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout)
1016 uint8_t success = 0;
1019 ao_radio_get(size - 2);
1020 ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
1022 ao_radio_start_rx();
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);
1029 /* Check the receiver status to see what happened
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
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
1052 /* some other status; go wait for the radio to do something useful
1058 uint8_t modem_status1 = ao_radio_reg_read(CC1200_MODEM_STATUS1);
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
1063 if (modem_status1 & (1 << CC1200_MODEM_STATUS1_SYNC_FOUND))
1067 /* Set a timeout based on the packet length so that we make sure to
1068 * wait long enough to receive the whole thing.
1070 * timeout = bits * FEC expansion / rate
1072 switch (ao_config.radio_rate) {
1074 case AO_RADIO_RATE_38400:
1075 timeout = AO_MS_TO_TICKS(size * (8 * 2 * 10) / 384) + 1;
1077 case AO_RADIO_RATE_9600:
1078 timeout = AO_MS_TO_TICKS(size * (8 * 2 * 10) / 96) + 1;
1080 case AO_RADIO_RATE_2400:
1081 timeout = AO_MS_TO_TICKS(size * (8 * 2 * 10) / 24) + 1;
1092 status = ao_radio_fifo_read(d, size);
1094 rssi = ((int8_t *) d)[size - 2];
1095 ao_radio_rssi = rssi;
1097 /* Bound it to the representable range */
1101 /* Write it back to the packet */
1102 ((int8_t *) d)[size-2] = AO_RADIO_FROM_RSSI(rssi);
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",
1125 struct ao_cc1200_reg {
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" },
1306 #define AO_NUM_CC1200_REG (sizeof ao_cc1200_reg / sizeof ao_cc1200_reg[0])
1309 ao_radio_get_marc_status(void)
1311 return ao_radio_reg_read(CC1200_MARC_STATUS1);
1314 static void ao_radio_show(void) {
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());
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);
1331 static void ao_radio_beep(void) {
1335 static void ao_radio_packet(void) {
1336 static const uint8_t packet[] = {
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,
1347 ao_radio_send(packet, sizeof (packet));
1351 ao_radio_test_recv(void)
1356 if (ao_radio_recv(bytes, 34, 0)) {
1357 if (bytes[33] & 0x80)
1361 printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32]));
1362 for (b = 0; b < 32; b++)
1363 printf (" %02x", bytes[b]);
1365 printf (" RSSI %02x LQI %02x", bytes[32], bytes[33]);
1371 #include <ao_aprs.h>
1376 #if PACKET_HAS_SLAVE
1377 ao_packet_slave_stop();
1384 #if CC1200_LOW_LEVEL_DEBUG
1386 ao_radio_strobe_test(void)
1391 if (ao_cmd_status != ao_cmd_success)
1393 r = ao_radio_strobe(ao_cmd_lex_i);
1394 printf ("Strobe %02x -> %02x (rdy %d state %d)\n",
1402 ao_radio_write_test(void)
1408 if (ao_cmd_status != ao_cmd_success)
1410 addr = ao_cmd_lex_i;
1412 if (ao_cmd_status != ao_cmd_success)
1414 data = ao_cmd_lex_i;
1415 printf ("Write %04x = %02x\n", addr, data);
1416 ao_radio_reg_write(addr, data);
1420 ao_radio_read_test(void)
1426 if (ao_cmd_status != ao_cmd_success)
1428 addr = ao_cmd_lex_i;
1429 data = ao_radio_reg_read(addr);
1430 printf ("Read %04x = %02x\n", addr, data);
1434 static const struct ao_cmds ao_radio_cmds[] = {
1435 { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
1438 { ao_radio_aprs, "G\0Send APRS packet" },
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" },
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" },
1456 ao_radio_configured = 0;
1457 ao_spi_init_cs (AO_CC1200_SPI_CS_PORT, (1 << AO_CC1200_SPI_CS_PIN));
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)
1465 AO_CC1200_SPI_CS_PORT->bsrr = (1 << AO_CC1200_SPI_CS_PIN);
1467 ao_panic(AO_PANIC_SELF_TEST_CC1200);
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,
1476 ao_cmd_register(&ao_radio_cmds[0]);