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_cc1120.h>
22 #include <ao_packet.h>
24 uint8_t ao_radio_wake;
25 uint8_t ao_radio_mutex;
26 uint8_t ao_radio_abort;
28 #define CC1120_DEBUG 1
29 #define CC1120_TRACE 0
32 #define fec_dump_bytes(b,l,n) ao_fec_dump_bytes(b,l,n)
34 #define fec_dump_bytes(b,l,n)
37 uint32_t ao_radio_cal = 0x6ca333;
41 #define ao_radio_select() ao_spi_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS)
42 #define ao_radio_deselect() ao_spi_put_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS)
43 #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1120_SPI_BUS)
44 #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1120_SPI_BUS)
45 #define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1120_SPI_BUS)
46 #define ao_radio_duplex(o,i,l) ao_spi_duplex((o), (i), (l), AO_CC1120_SPI_BUS)
49 ao_radio_reg_read(uint16_t addr)
55 printf("\t\tao_radio_reg_read (%04x): ", addr); flush();
57 if (CC1120_IS_EXTENDED(addr)) {
58 data[0] = ((1 << CC1120_READ) |
64 data[0] = ((1 << CC1120_READ) |
70 ao_radio_spi_send(data, d);
71 ao_radio_spi_recv(data, 1);
74 printf (" %02x\n", data[0]);
80 ao_radio_reg_write(uint16_t addr, uint8_t value)
86 printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value);
88 if (CC1120_IS_EXTENDED(addr)) {
89 data[0] = ((0 << CC1120_READ) |
95 data[0] = ((0 << CC1120_READ) |
102 ao_radio_spi_send(data, d+1);
107 ao_radio_burst_read_start (uint16_t addr)
112 if (CC1120_IS_EXTENDED(addr)) {
113 data[0] = ((1 << CC1120_READ) |
114 (1 << CC1120_BURST) |
119 data[0] = ((1 << CC1120_READ) |
120 (1 << CC1120_BURST) |
125 ao_radio_spi_send(data, d);
129 ao_radio_burst_read_stop (void)
136 ao_radio_strobe(uint8_t addr)
141 printf("\t\tao_radio_strobe (%02x): ", addr); flush();
144 ao_radio_duplex(&addr, &in, 1);
147 printf("%02x\n", in); flush();
153 ao_radio_fifo_read(uint8_t *data, uint8_t len)
155 uint8_t addr = ((1 << CC1120_READ) |
156 (1 << CC1120_BURST) |
161 ao_radio_duplex(&addr, &status, 1);
162 ao_radio_spi_recv(data, len);
168 ao_radio_fifo_write(uint8_t *data, uint8_t len)
170 uint8_t addr = ((0 << CC1120_READ) |
171 (1 << CC1120_BURST) |
176 ao_radio_duplex(&addr, &status, 1);
177 ao_radio_spi_send(data, len);
183 ao_radio_fifo_write_fixed(uint8_t data, uint8_t len)
185 uint8_t addr = ((0 << CC1120_READ) |
186 (1 << CC1120_BURST) |
191 ao_radio_duplex(&addr, &status, 1);
192 ao_radio_spi_send_fixed(data, len);
198 ao_radio_status(void)
200 return ao_radio_strobe (CC1120_SNOP);
204 ao_radio_recv_abort(void)
207 ao_wakeup(&ao_radio_wake);
210 #define ao_radio_rdf_value 0x55
213 * RDF deviation is 5kHz
215 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
217 * 32e6Hz / (2 ** 24) * (256 + 71) * (2 ** 3) = 4989
222 #define RDF_PACKET_LEN 50
225 * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
227 * (2**20 - DATARATE_M) * 2 ** DATARATE_E
228 * Rdata = -------------------------------------- * fosc
231 * DATARATE_M = 511705
234 * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
236 #define RDF_DRATE_E 5
237 #define RDF_DRATE_M 25166
238 #define RDF_PACKET_LEN 50
240 static const uint16_t rdf_setup[] = {
241 CC1120_DEVIATION_M, RDF_DEV_M,
242 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
243 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
244 (RDF_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
245 CC1120_DRATE2, ((RDF_DRATE_E << CC1120_DRATE2_DATARATE_E) |
246 (((RDF_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
247 CC1120_DRATE1, ((RDF_DRATE_M >> 8) & 0xff),
248 CC1120_DRATE0, ((RDF_DRATE_M >> 0) & 0xff),
249 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
250 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
251 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
252 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
253 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
254 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
255 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
256 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
257 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
258 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
259 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
263 ao_radio_marc_status(void)
265 return ao_radio_reg_read(CC1120_MARC_STATUS1);
269 ao_radio_tx_done(void)
271 return ao_radio_marc_status() == CC1120_MARC_STATUS1_TX_FINISHED;
275 ao_radio_rx_done(void)
277 return ao_radio_marc_status() == CC1120_MARC_STATUS1_RX_FINISHED;
281 ao_radio_tx_isr(void)
283 ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
285 ao_wakeup(&ao_radio_wake);
289 ao_radio_start_tx(void)
291 ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG);
292 ao_exti_set_callback(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_tx_isr);
293 ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
294 ao_radio_strobe(CC1120_STX);
298 ao_radio_rdf(uint8_t len)
304 for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2)
305 ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]);
307 ao_radio_fifo_write_fixed(ao_radio_rdf_value, len);
312 while (!ao_radio_wake && !ao_radio_abort)
313 ao_sleep(&ao_radio_wake);
316 if (!ao_radio_tx_done())
318 ao_radio_set_packet();
323 ao_radio_rdf_abort(void)
326 ao_wakeup(&ao_radio_wake);
335 if (ao_cmd_lex_c != '\n') {
337 mode = (uint8_t) ao_cmd_lex_u32;
340 if ((mode & 2) && !radio_on) {
342 ao_monitor_disable();
345 ao_packet_slave_stop();
348 ao_radio_strobe(CC1120_STX);
351 for (t = 0; t < 10; t++) {
352 printf ("status: %02x\n", ao_radio_status());
353 ao_delay(AO_MS_TO_TICKS(100));
360 printf ("Hit a character to stop..."); flush();
364 if ((mode & 1) && radio_on) {
375 ao_radio_send(void *d, uint8_t size)
378 uint8_t encode[size + AO_FEC_PREPARE_EXTRA];
381 encode_len = ao_fec_encode(d, size, encode);
383 ao_radio_get(encode_len);
384 ao_radio_fifo_write(encode, encode_len);
391 while (!ao_radio_wake && !ao_radio_abort)
392 ao_sleep(&ao_radio_wake);
394 if (!ao_radio_tx_done())
399 #define AO_RADIO_MAX_RECV 90
401 static uint8_t rx_data[2048];
402 static uint16_t rx_data_count;
403 static uint16_t rx_data_cur;
404 static uint8_t rx_started;
407 ao_radio_rx_isr(void)
410 rx_data[rx_data_cur++] = stm_spi2.dr;
411 if (rx_data_cur >= rx_data_count) {
412 ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
414 ao_wakeup(&ao_radio_wake);
424 ao_radio_recv(__xdata void *d, uint8_t size)
426 uint8_t len = ((size - 2) + 4) * 2; /* two bytes for status */
429 rx_data_count = sizeof (rx_data);
433 printf ("len %d rx_data_count %d\n", len, rx_data_count);
435 /* configure interrupt pin */
440 ao_radio_reg_write(CC1120_PKT_CFG2,
441 (CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
442 (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT));
444 ao_radio_reg_write(CC1120_EXT_CTRL, 0);
446 ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT);
453 ao_exti_set_callback(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
454 ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
456 ao_radio_strobe(CC1120_SRX);
458 ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
461 while (!ao_radio_wake && !ao_radio_abort)
462 ao_sleep(&ao_radio_wake);
466 printf ("Hit a character to stop..."); flush();
469 ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
471 ao_radio_burst_read_stop();
473 ao_radio_strobe(CC1120_SIDLE);
477 printf ("Received data:");
478 for (i = 0; i < rx_data_cur; i++) {
481 printf (" %02x", rx_data[i]);
488 * Packet deviation is 20.5kHz
490 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
492 * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz
495 #define PACKET_DEV_E 5
496 #define PACKET_DEV_M 80
499 * For our packet data, set the symbol rate to 38360 Baud
501 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
502 * Rdata = -------------------------------------- * fosc
506 * DATARATE_M = 239914
509 #define PACKET_DRATE_E 9
510 #define PACKET_DRATE_M 239914
512 static const uint16_t packet_setup[] = {
513 CC1120_DEVIATION_M, PACKET_DEV_M,
514 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
515 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
516 (PACKET_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
517 CC1120_DRATE2, ((PACKET_DRATE_E << CC1120_DRATE2_DATARATE_E) |
518 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
519 CC1120_DRATE1, ((PACKET_DRATE_M >> 8) & 0xff),
520 CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff),
521 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
522 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
523 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
524 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
525 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
526 (1 << CC1120_PKT_CFG1_APPEND_STATUS)),
527 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
528 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
529 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
530 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
531 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
535 ao_radio_set_packet(void)
539 for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2)
540 ao_radio_reg_write(packet_setup[i], packet_setup[i+1]);
547 uint8_t state = ao_radio_strobe(CC1120_SIDLE);
548 if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_IDLE)
551 ao_radio_strobe(CC1120_SFTX);
552 ao_radio_strobe(CC1120_SFRX);
555 static const uint16_t radio_setup[] = {
556 #include "ao_cc1120_CC1120.h"
559 static uint8_t ao_radio_configured = 0;
567 ao_radio_strobe(CC1120_SRES);
569 for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2)
570 ao_radio_reg_write(radio_setup[i], radio_setup[i+1]);
572 ao_radio_set_packet();
576 ao_radio_configured = 1;
580 ao_radio_get(uint8_t len)
582 ao_mutex_get(&ao_radio_mutex);
583 if (!ao_radio_configured)
585 ao_radio_reg_write(CC1120_FREQ2, ao_config.radio_setting >> 16);
586 ao_radio_reg_write(CC1120_FREQ1, ao_config.radio_setting >> 8);
587 ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting);
588 ao_radio_reg_write(CC1120_PKT_LEN, len);
592 static char *cc1120_state_name[] = {
593 [CC1120_STATUS_STATE_IDLE] = "IDLE",
594 [CC1120_STATUS_STATE_RX] = "RX",
595 [CC1120_STATUS_STATE_TX] = "TX",
596 [CC1120_STATUS_STATE_FSTXON] = "FSTXON",
597 [CC1120_STATUS_STATE_CALIBRATE] = "CALIBRATE",
598 [CC1120_STATUS_STATE_SETTLING] = "SETTLING",
599 [CC1120_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
600 [CC1120_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
603 struct ao_cc1120_reg {
608 const static struct ao_cc1120_reg ao_cc1120_reg[] = {
609 { .addr = CC1120_IOCFG3, .name = "IOCFG3" },
610 { .addr = CC1120_IOCFG2, .name = "IOCFG2" },
611 { .addr = CC1120_IOCFG1, .name = "IOCFG1" },
612 { .addr = CC1120_IOCFG0, .name = "IOCFG0" },
613 { .addr = CC1120_SYNC3, .name = "SYNC3" },
614 { .addr = CC1120_SYNC2, .name = "SYNC2" },
615 { .addr = CC1120_SYNC1, .name = "SYNC1" },
616 { .addr = CC1120_SYNC0, .name = "SYNC0" },
617 { .addr = CC1120_SYNC_CFG1, .name = "SYNC_CFG1" },
618 { .addr = CC1120_SYNC_CFG0, .name = "SYNC_CFG0" },
619 { .addr = CC1120_DEVIATION_M, .name = "DEVIATION_M" },
620 { .addr = CC1120_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
621 { .addr = CC1120_DCFILT_CFG, .name = "DCFILT_CFG" },
622 { .addr = CC1120_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
623 { .addr = CC1120_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
624 { .addr = CC1120_FREQ_IF_CFG, .name = "FREQ_IF_CFG" },
625 { .addr = CC1120_IQIC, .name = "IQIC" },
626 { .addr = CC1120_CHAN_BW, .name = "CHAN_BW" },
627 { .addr = CC1120_MDMCFG1, .name = "MDMCFG1" },
628 { .addr = CC1120_MDMCFG0, .name = "MDMCFG0" },
629 { .addr = CC1120_DRATE2, .name = "DRATE2" },
630 { .addr = CC1120_DRATE1, .name = "DRATE1" },
631 { .addr = CC1120_DRATE0, .name = "DRATE0" },
632 { .addr = CC1120_AGC_REF, .name = "AGC_REF" },
633 { .addr = CC1120_AGC_CS_THR, .name = "AGC_CS_THR" },
634 { .addr = CC1120_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
635 { .addr = CC1120_AGC_CFG3, .name = "AGC_CFG3" },
636 { .addr = CC1120_AGC_CFG2, .name = "AGC_CFG2" },
637 { .addr = CC1120_AGC_CFG1, .name = "AGC_CFG1" },
638 { .addr = CC1120_AGC_CFG0, .name = "AGC_CFG0" },
639 { .addr = CC1120_FIFO_CFG, .name = "FIFO_CFG" },
640 { .addr = CC1120_DEV_ADDR, .name = "DEV_ADDR" },
641 { .addr = CC1120_SETTLING_CFG, .name = "SETTLING_CFG" },
642 { .addr = CC1120_FS_CFG, .name = "FS_CFG" },
643 { .addr = CC1120_WOR_CFG1, .name = "WOR_CFG1" },
644 { .addr = CC1120_WOR_CFG0, .name = "WOR_CFG0" },
645 { .addr = CC1120_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
646 { .addr = CC1120_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
647 { .addr = CC1120_PKT_CFG2, .name = "PKT_CFG2" },
648 { .addr = CC1120_PKT_CFG1, .name = "PKT_CFG1" },
649 { .addr = CC1120_PKT_CFG0, .name = "PKT_CFG0" },
650 { .addr = CC1120_RFEND_CFG1, .name = "RFEND_CFG1" },
651 { .addr = CC1120_RFEND_CFG0, .name = "RFEND_CFG0" },
652 { .addr = CC1120_PA_CFG2, .name = "PA_CFG2" },
653 { .addr = CC1120_PA_CFG1, .name = "PA_CFG1" },
654 { .addr = CC1120_PA_CFG0, .name = "PA_CFG0" },
655 { .addr = CC1120_PKT_LEN, .name = "PKT_LEN" },
656 { .addr = CC1120_IF_MIX_CFG, .name = "IF_MIX_CFG" },
657 { .addr = CC1120_FREQOFF_CFG, .name = "FREQOFF_CFG" },
658 { .addr = CC1120_TOC_CFG, .name = "TOC_CFG" },
659 { .addr = CC1120_MARC_SPARE, .name = "MARC_SPARE" },
660 { .addr = CC1120_ECG_CFG, .name = "ECG_CFG" },
661 { .addr = CC1120_SOFT_TX_DATA_CFG, .name = "SOFT_TX_DATA_CFG" },
662 { .addr = CC1120_EXT_CTRL, .name = "EXT_CTRL" },
663 { .addr = CC1120_RCCAL_FINE, .name = "RCCAL_FINE" },
664 { .addr = CC1120_RCCAL_COARSE, .name = "RCCAL_COARSE" },
665 { .addr = CC1120_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
666 { .addr = CC1120_FREQOFF1, .name = "FREQOFF1" },
667 { .addr = CC1120_FREQOFF0, .name = "FREQOFF0" },
668 { .addr = CC1120_FREQ2, .name = "FREQ2" },
669 { .addr = CC1120_FREQ1, .name = "FREQ1" },
670 { .addr = CC1120_FREQ0, .name = "FREQ0" },
671 { .addr = CC1120_IF_ADC2, .name = "IF_ADC2" },
672 { .addr = CC1120_IF_ADC1, .name = "IF_ADC1" },
673 { .addr = CC1120_IF_ADC0, .name = "IF_ADC0" },
674 { .addr = CC1120_FS_DIG1, .name = "FS_DIG1" },
675 { .addr = CC1120_FS_DIG0, .name = "FS_DIG0" },
676 { .addr = CC1120_FS_CAL3, .name = "FS_CAL3" },
677 { .addr = CC1120_FS_CAL2, .name = "FS_CAL2" },
678 { .addr = CC1120_FS_CAL1, .name = "FS_CAL1" },
679 { .addr = CC1120_FS_CAL0, .name = "FS_CAL0" },
680 { .addr = CC1120_FS_CHP, .name = "FS_CHP" },
681 { .addr = CC1120_FS_DIVTWO, .name = "FS_DIVTWO" },
682 { .addr = CC1120_FS_DSM1, .name = "FS_DSM1" },
683 { .addr = CC1120_FS_DSM0, .name = "FS_DSM0" },
684 { .addr = CC1120_FS_DVC1, .name = "FS_DVC1" },
685 { .addr = CC1120_FS_DVC0, .name = "FS_DVC0" },
686 { .addr = CC1120_FS_LBI, .name = "FS_LBI" },
687 { .addr = CC1120_FS_PFD, .name = "FS_PFD" },
688 { .addr = CC1120_FS_PRE, .name = "FS_PRE" },
689 { .addr = CC1120_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
690 { .addr = CC1120_FS_SPARE, .name = "FS_SPARE" },
691 { .addr = CC1120_FS_VCO4, .name = "FS_VCO4" },
692 { .addr = CC1120_FS_VCO3, .name = "FS_VCO3" },
693 { .addr = CC1120_FS_VCO2, .name = "FS_VCO2" },
694 { .addr = CC1120_FS_VCO1, .name = "FS_VCO1" },
695 { .addr = CC1120_FS_VCO0, .name = "FS_VCO0" },
696 { .addr = CC1120_GBIAS6, .name = "GBIAS6" },
697 { .addr = CC1120_GBIAS5, .name = "GBIAS5" },
698 { .addr = CC1120_GBIAS4, .name = "GBIAS4" },
699 { .addr = CC1120_GBIAS3, .name = "GBIAS3" },
700 { .addr = CC1120_GBIAS2, .name = "GBIAS2" },
701 { .addr = CC1120_GBIAS1, .name = "GBIAS1" },
702 { .addr = CC1120_GBIAS0, .name = "GBIAS0" },
703 { .addr = CC1120_IFAMP, .name = "IFAMP" },
704 { .addr = CC1120_LNA, .name = "LNA" },
705 { .addr = CC1120_RXMIX, .name = "RXMIX" },
706 { .addr = CC1120_XOSC5, .name = "XOSC5" },
707 { .addr = CC1120_XOSC4, .name = "XOSC4" },
708 { .addr = CC1120_XOSC3, .name = "XOSC3" },
709 { .addr = CC1120_XOSC2, .name = "XOSC2" },
710 { .addr = CC1120_XOSC1, .name = "XOSC1" },
711 { .addr = CC1120_XOSC0, .name = "XOSC0" },
712 { .addr = CC1120_ANALOG_SPARE, .name = "ANALOG_SPARE" },
713 { .addr = CC1120_PA_CFG3, .name = "PA_CFG3" },
714 { .addr = CC1120_WOR_TIME1, .name = "WOR_TIME1" },
715 { .addr = CC1120_WOR_TIME0, .name = "WOR_TIME0" },
716 { .addr = CC1120_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
717 { .addr = CC1120_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
718 { .addr = CC1120_BIST, .name = "BIST" },
719 { .addr = CC1120_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
720 { .addr = CC1120_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
721 { .addr = CC1120_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
722 { .addr = CC1120_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
723 { .addr = CC1120_IQIE_I1, .name = "IQIE_I1" },
724 { .addr = CC1120_IQIE_I0, .name = "IQIE_I0" },
725 { .addr = CC1120_IQIE_Q1, .name = "IQIE_Q1" },
726 { .addr = CC1120_IQIE_Q0, .name = "IQIE_Q0" },
727 { .addr = CC1120_RSSI1, .name = "RSSI1" },
728 { .addr = CC1120_RSSI0, .name = "RSSI0" },
729 { .addr = CC1120_MARCSTATE, .name = "MARCSTATE" },
730 { .addr = CC1120_LQI_VAL, .name = "LQI_VAL" },
731 { .addr = CC1120_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
732 { .addr = CC1120_DEM_STATUS, .name = "DEM_STATUS" },
733 { .addr = CC1120_FREQOFF_EST1, .name = "FREQOFF_EST1" },
734 { .addr = CC1120_FREQOFF_EST0, .name = "FREQOFF_EST0" },
735 { .addr = CC1120_AGC_GAIN3, .name = "AGC_GAIN3" },
736 { .addr = CC1120_AGC_GAIN2, .name = "AGC_GAIN2" },
737 { .addr = CC1120_AGC_GAIN1, .name = "AGC_GAIN1" },
738 { .addr = CC1120_AGC_GAIN0, .name = "AGC_GAIN0" },
739 { .addr = CC1120_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
740 { .addr = CC1120_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
741 { .addr = CC1120_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
742 { .addr = CC1120_RNDGEN, .name = "RNDGEN" },
743 { .addr = CC1120_MAGN2, .name = "MAGN2" },
744 { .addr = CC1120_MAGN1, .name = "MAGN1" },
745 { .addr = CC1120_MAGN0, .name = "MAGN0" },
746 { .addr = CC1120_ANG1, .name = "ANG1" },
747 { .addr = CC1120_ANG0, .name = "ANG0" },
748 { .addr = CC1120_CHFILT_I2, .name = "CHFILT_I2" },
749 { .addr = CC1120_CHFILT_I1, .name = "CHFILT_I1" },
750 { .addr = CC1120_CHFILT_I0, .name = "CHFILT_I0" },
751 { .addr = CC1120_CHFILT_Q2, .name = "CHFILT_Q2" },
752 { .addr = CC1120_CHFILT_Q1, .name = "CHFILT_Q1" },
753 { .addr = CC1120_CHFILT_Q0, .name = "CHFILT_Q0" },
754 { .addr = CC1120_GPIO_STATUS, .name = "GPIO_STATUS" },
755 { .addr = CC1120_FSCAL_CTRL, .name = "FSCAL_CTRL" },
756 { .addr = CC1120_PHASE_ADJUST, .name = "PHASE_ADJUST" },
757 { .addr = CC1120_PARTNUMBER, .name = "PARTNUMBER" },
758 { .addr = CC1120_PARTVERSION, .name = "PARTVERSION" },
759 { .addr = CC1120_SERIAL_STATUS, .name = "SERIAL_STATUS" },
760 { .addr = CC1120_RX_STATUS, .name = "RX_STATUS" },
761 { .addr = CC1120_TX_STATUS, .name = "TX_STATUS" },
762 { .addr = CC1120_MARC_STATUS1, .name = "MARC_STATUS1" },
763 { .addr = CC1120_MARC_STATUS0, .name = "MARC_STATUS0" },
764 { .addr = CC1120_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
765 { .addr = CC1120_FSRF_TEST, .name = "FSRF_TEST" },
766 { .addr = CC1120_PRE_TEST, .name = "PRE_TEST" },
767 { .addr = CC1120_PRE_OVR, .name = "PRE_OVR" },
768 { .addr = CC1120_ADC_TEST, .name = "ADC_TEST" },
769 { .addr = CC1120_DVC_TEST, .name = "DVC_TEST" },
770 { .addr = CC1120_ATEST, .name = "ATEST" },
771 { .addr = CC1120_ATEST_LVDS, .name = "ATEST_LVDS" },
772 { .addr = CC1120_ATEST_MODE, .name = "ATEST_MODE" },
773 { .addr = CC1120_XOSC_TEST1, .name = "XOSC_TEST1" },
774 { .addr = CC1120_XOSC_TEST0, .name = "XOSC_TEST0" },
775 { .addr = CC1120_RXFIRST, .name = "RXFIRST" },
776 { .addr = CC1120_TXFIRST, .name = "TXFIRST" },
777 { .addr = CC1120_RXLAST, .name = "RXLAST" },
778 { .addr = CC1120_TXLAST, .name = "TXLAST" },
779 { .addr = CC1120_NUM_TXBYTES, .name = "NUM_TXBYTES" },
780 { .addr = CC1120_NUM_RXBYTES, .name = "NUM_RXBYTES" },
781 { .addr = CC1120_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
782 { .addr = CC1120_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
785 #define AO_NUM_CC1120_REG (sizeof ao_cc1120_reg / sizeof ao_cc1120_reg[0])
787 static void ao_radio_show(void) {
788 uint8_t status = ao_radio_status();
792 status = ao_radio_status();
793 printf ("Status: %02x\n", status);
794 printf ("CHIP_RDY: %d\n", (status >> CC1120_STATUS_CHIP_RDY) & 1);
795 printf ("STATE: %s\n", cc1120_state_name[(status >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK]);
796 printf ("MARC: %02x\n", ao_radio_marc_status());
798 for (i = 0; i < AO_NUM_CC1120_REG; i++)
799 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name);
803 static void ao_radio_beep(void) {
804 ao_radio_rdf(RDF_PACKET_LEN);
807 static void ao_radio_packet(void) {
808 static uint8_t packet[] = {
810 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
811 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
812 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
813 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
819 ao_radio_send(packet, sizeof (packet));
825 ao_radio_recv(0, 34);
830 static const struct ao_cmds ao_radio_cmds[] = {
831 { ao_radio_test, "C <1 start, 0 stop, none both>\0Radio carrier test" },
833 { ao_radio_show, "R\0Show CC1120 status" },
834 { ao_radio_beep, "b\0Emit an RDF beacon" },
835 { ao_radio_packet, "p\0Send a test packet" },
836 { ao_radio_test_recv, "q\0Recv a test packet" },
846 ao_radio_configured = 0;
847 ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN));
849 AO_CC1120_SPI_CS_PORT.bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN));
850 for (i = 0; i < 10000; i++) {
851 if ((SPI_2_GPIO.idr & (1 << SPI_2_MISO)) == 0)
854 AO_CC1120_SPI_CS_PORT.bsrr = (1 << AO_CC1120_SPI_CS_PIN);
856 ao_panic(AO_PANIC_SELF_TEST);
858 /* Enable the EXTI interrupt for the appropriate pin */
859 ao_enable_port(AO_CC1120_INT_PORT);
860 ao_exti_setup(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_EXTI_MODE_FALLING, ao_radio_tx_isr);
862 ao_cmd_register(&ao_radio_cmds[0]);