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_consumed;
404 static uint16_t rx_data_cur;
405 static uint8_t rx_ignore;
408 ao_radio_rx_isr(void)
410 if (rx_ignore == 0) {
411 rx_data[rx_data_cur++] = stm_spi2.dr;
412 if (rx_data_cur >= rx_data_count)
413 ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
414 if (rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) {
415 ao_wakeup(&ao_radio_wake);
425 ao_radio_rx_wait(void)
428 while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&
430 ao_sleep(&ao_radio_wake);
434 return AO_FEC_DECODE_BLOCK;
438 ao_radio_recv(__xdata void *d, uint8_t size)
444 size -= 2; /* status bytes */
445 len = size + 2; /* CRC bytes */
446 len += 1 + ~(len & 1); /* 1 or two pad bytes */
447 len *= 2; /* 1/2 rate convolution */
448 rx_data_count = len * 8; /* bytes to bits */
450 rx_data_consumed = 0;
453 printf ("len %d rx_data_count %d\n", len, rx_data_count);
455 /* configure interrupt pin */
460 ao_radio_reg_write(CC1120_PKT_CFG2,
461 (CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
462 (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT));
464 ao_radio_reg_write(CC1120_EXT_CTRL, 0);
466 ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT);
473 ao_exti_set_callback(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
474 ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
476 ao_radio_strobe(CC1120_SRX);
478 ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
480 ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait);
482 ao_radio_burst_read_stop();
484 /* Convert from 'real' rssi to cc1111-style values */
486 rssi = (((int8_t) ao_radio_reg_read(CC1120_RSSI1)) + 74) * 2;
488 ao_radio_strobe(CC1120_SIDLE);
492 /* Construct final packet */
494 ao_fec_decode(rx_data, rx_data_cur, d, size + 2, 0);
496 if (ao_fec_check_crc(d, size))
497 ((uint8_t *) d)[size + 1] = 0x80;
499 ((uint8_t *) d)[size + 1] = 0x00;
501 ((uint8_t *) d)[size] = (uint8_t) rssi;
507 * Packet deviation is 20.5kHz
509 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
511 * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz
514 #define PACKET_DEV_E 5
515 #define PACKET_DEV_M 80
518 * For our packet data, set the symbol rate to 38360 Baud
520 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
521 * Rdata = -------------------------------------- * fosc
525 * DATARATE_M = 239914
528 #define PACKET_DRATE_E 9
529 #define PACKET_DRATE_M 239914
531 static const uint16_t packet_setup[] = {
532 CC1120_DEVIATION_M, PACKET_DEV_M,
533 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
534 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
535 (PACKET_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
536 CC1120_DRATE2, ((PACKET_DRATE_E << CC1120_DRATE2_DATARATE_E) |
537 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
538 CC1120_DRATE1, ((PACKET_DRATE_M >> 8) & 0xff),
539 CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff),
540 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
541 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
542 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
543 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
544 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
545 (1 << CC1120_PKT_CFG1_APPEND_STATUS)),
546 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
547 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
548 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
549 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
550 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
554 ao_radio_set_packet(void)
558 for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2)
559 ao_radio_reg_write(packet_setup[i], packet_setup[i+1]);
566 uint8_t state = ao_radio_strobe(CC1120_SIDLE);
567 if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_IDLE)
570 ao_radio_strobe(CC1120_SFTX);
571 ao_radio_strobe(CC1120_SFRX);
574 static const uint16_t radio_setup[] = {
575 #include "ao_cc1120_CC1120.h"
578 static uint8_t ao_radio_configured = 0;
586 ao_radio_strobe(CC1120_SRES);
588 for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2)
589 ao_radio_reg_write(radio_setup[i], radio_setup[i+1]);
591 ao_radio_set_packet();
595 ao_radio_configured = 1;
599 ao_radio_get(uint8_t len)
601 ao_mutex_get(&ao_radio_mutex);
602 if (!ao_radio_configured)
604 ao_radio_reg_write(CC1120_FREQ2, ao_config.radio_setting >> 16);
605 ao_radio_reg_write(CC1120_FREQ1, ao_config.radio_setting >> 8);
606 ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting);
607 ao_radio_reg_write(CC1120_PKT_LEN, len);
611 static char *cc1120_state_name[] = {
612 [CC1120_STATUS_STATE_IDLE] = "IDLE",
613 [CC1120_STATUS_STATE_RX] = "RX",
614 [CC1120_STATUS_STATE_TX] = "TX",
615 [CC1120_STATUS_STATE_FSTXON] = "FSTXON",
616 [CC1120_STATUS_STATE_CALIBRATE] = "CALIBRATE",
617 [CC1120_STATUS_STATE_SETTLING] = "SETTLING",
618 [CC1120_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
619 [CC1120_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
622 struct ao_cc1120_reg {
627 const static struct ao_cc1120_reg ao_cc1120_reg[] = {
628 { .addr = CC1120_IOCFG3, .name = "IOCFG3" },
629 { .addr = CC1120_IOCFG2, .name = "IOCFG2" },
630 { .addr = CC1120_IOCFG1, .name = "IOCFG1" },
631 { .addr = CC1120_IOCFG0, .name = "IOCFG0" },
632 { .addr = CC1120_SYNC3, .name = "SYNC3" },
633 { .addr = CC1120_SYNC2, .name = "SYNC2" },
634 { .addr = CC1120_SYNC1, .name = "SYNC1" },
635 { .addr = CC1120_SYNC0, .name = "SYNC0" },
636 { .addr = CC1120_SYNC_CFG1, .name = "SYNC_CFG1" },
637 { .addr = CC1120_SYNC_CFG0, .name = "SYNC_CFG0" },
638 { .addr = CC1120_DEVIATION_M, .name = "DEVIATION_M" },
639 { .addr = CC1120_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
640 { .addr = CC1120_DCFILT_CFG, .name = "DCFILT_CFG" },
641 { .addr = CC1120_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
642 { .addr = CC1120_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
643 { .addr = CC1120_FREQ_IF_CFG, .name = "FREQ_IF_CFG" },
644 { .addr = CC1120_IQIC, .name = "IQIC" },
645 { .addr = CC1120_CHAN_BW, .name = "CHAN_BW" },
646 { .addr = CC1120_MDMCFG1, .name = "MDMCFG1" },
647 { .addr = CC1120_MDMCFG0, .name = "MDMCFG0" },
648 { .addr = CC1120_DRATE2, .name = "DRATE2" },
649 { .addr = CC1120_DRATE1, .name = "DRATE1" },
650 { .addr = CC1120_DRATE0, .name = "DRATE0" },
651 { .addr = CC1120_AGC_REF, .name = "AGC_REF" },
652 { .addr = CC1120_AGC_CS_THR, .name = "AGC_CS_THR" },
653 { .addr = CC1120_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
654 { .addr = CC1120_AGC_CFG3, .name = "AGC_CFG3" },
655 { .addr = CC1120_AGC_CFG2, .name = "AGC_CFG2" },
656 { .addr = CC1120_AGC_CFG1, .name = "AGC_CFG1" },
657 { .addr = CC1120_AGC_CFG0, .name = "AGC_CFG0" },
658 { .addr = CC1120_FIFO_CFG, .name = "FIFO_CFG" },
659 { .addr = CC1120_DEV_ADDR, .name = "DEV_ADDR" },
660 { .addr = CC1120_SETTLING_CFG, .name = "SETTLING_CFG" },
661 { .addr = CC1120_FS_CFG, .name = "FS_CFG" },
662 { .addr = CC1120_WOR_CFG1, .name = "WOR_CFG1" },
663 { .addr = CC1120_WOR_CFG0, .name = "WOR_CFG0" },
664 { .addr = CC1120_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
665 { .addr = CC1120_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
666 { .addr = CC1120_PKT_CFG2, .name = "PKT_CFG2" },
667 { .addr = CC1120_PKT_CFG1, .name = "PKT_CFG1" },
668 { .addr = CC1120_PKT_CFG0, .name = "PKT_CFG0" },
669 { .addr = CC1120_RFEND_CFG1, .name = "RFEND_CFG1" },
670 { .addr = CC1120_RFEND_CFG0, .name = "RFEND_CFG0" },
671 { .addr = CC1120_PA_CFG2, .name = "PA_CFG2" },
672 { .addr = CC1120_PA_CFG1, .name = "PA_CFG1" },
673 { .addr = CC1120_PA_CFG0, .name = "PA_CFG0" },
674 { .addr = CC1120_PKT_LEN, .name = "PKT_LEN" },
675 { .addr = CC1120_IF_MIX_CFG, .name = "IF_MIX_CFG" },
676 { .addr = CC1120_FREQOFF_CFG, .name = "FREQOFF_CFG" },
677 { .addr = CC1120_TOC_CFG, .name = "TOC_CFG" },
678 { .addr = CC1120_MARC_SPARE, .name = "MARC_SPARE" },
679 { .addr = CC1120_ECG_CFG, .name = "ECG_CFG" },
680 { .addr = CC1120_SOFT_TX_DATA_CFG, .name = "SOFT_TX_DATA_CFG" },
681 { .addr = CC1120_EXT_CTRL, .name = "EXT_CTRL" },
682 { .addr = CC1120_RCCAL_FINE, .name = "RCCAL_FINE" },
683 { .addr = CC1120_RCCAL_COARSE, .name = "RCCAL_COARSE" },
684 { .addr = CC1120_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
685 { .addr = CC1120_FREQOFF1, .name = "FREQOFF1" },
686 { .addr = CC1120_FREQOFF0, .name = "FREQOFF0" },
687 { .addr = CC1120_FREQ2, .name = "FREQ2" },
688 { .addr = CC1120_FREQ1, .name = "FREQ1" },
689 { .addr = CC1120_FREQ0, .name = "FREQ0" },
690 { .addr = CC1120_IF_ADC2, .name = "IF_ADC2" },
691 { .addr = CC1120_IF_ADC1, .name = "IF_ADC1" },
692 { .addr = CC1120_IF_ADC0, .name = "IF_ADC0" },
693 { .addr = CC1120_FS_DIG1, .name = "FS_DIG1" },
694 { .addr = CC1120_FS_DIG0, .name = "FS_DIG0" },
695 { .addr = CC1120_FS_CAL3, .name = "FS_CAL3" },
696 { .addr = CC1120_FS_CAL2, .name = "FS_CAL2" },
697 { .addr = CC1120_FS_CAL1, .name = "FS_CAL1" },
698 { .addr = CC1120_FS_CAL0, .name = "FS_CAL0" },
699 { .addr = CC1120_FS_CHP, .name = "FS_CHP" },
700 { .addr = CC1120_FS_DIVTWO, .name = "FS_DIVTWO" },
701 { .addr = CC1120_FS_DSM1, .name = "FS_DSM1" },
702 { .addr = CC1120_FS_DSM0, .name = "FS_DSM0" },
703 { .addr = CC1120_FS_DVC1, .name = "FS_DVC1" },
704 { .addr = CC1120_FS_DVC0, .name = "FS_DVC0" },
705 { .addr = CC1120_FS_LBI, .name = "FS_LBI" },
706 { .addr = CC1120_FS_PFD, .name = "FS_PFD" },
707 { .addr = CC1120_FS_PRE, .name = "FS_PRE" },
708 { .addr = CC1120_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
709 { .addr = CC1120_FS_SPARE, .name = "FS_SPARE" },
710 { .addr = CC1120_FS_VCO4, .name = "FS_VCO4" },
711 { .addr = CC1120_FS_VCO3, .name = "FS_VCO3" },
712 { .addr = CC1120_FS_VCO2, .name = "FS_VCO2" },
713 { .addr = CC1120_FS_VCO1, .name = "FS_VCO1" },
714 { .addr = CC1120_FS_VCO0, .name = "FS_VCO0" },
715 { .addr = CC1120_GBIAS6, .name = "GBIAS6" },
716 { .addr = CC1120_GBIAS5, .name = "GBIAS5" },
717 { .addr = CC1120_GBIAS4, .name = "GBIAS4" },
718 { .addr = CC1120_GBIAS3, .name = "GBIAS3" },
719 { .addr = CC1120_GBIAS2, .name = "GBIAS2" },
720 { .addr = CC1120_GBIAS1, .name = "GBIAS1" },
721 { .addr = CC1120_GBIAS0, .name = "GBIAS0" },
722 { .addr = CC1120_IFAMP, .name = "IFAMP" },
723 { .addr = CC1120_LNA, .name = "LNA" },
724 { .addr = CC1120_RXMIX, .name = "RXMIX" },
725 { .addr = CC1120_XOSC5, .name = "XOSC5" },
726 { .addr = CC1120_XOSC4, .name = "XOSC4" },
727 { .addr = CC1120_XOSC3, .name = "XOSC3" },
728 { .addr = CC1120_XOSC2, .name = "XOSC2" },
729 { .addr = CC1120_XOSC1, .name = "XOSC1" },
730 { .addr = CC1120_XOSC0, .name = "XOSC0" },
731 { .addr = CC1120_ANALOG_SPARE, .name = "ANALOG_SPARE" },
732 { .addr = CC1120_PA_CFG3, .name = "PA_CFG3" },
733 { .addr = CC1120_WOR_TIME1, .name = "WOR_TIME1" },
734 { .addr = CC1120_WOR_TIME0, .name = "WOR_TIME0" },
735 { .addr = CC1120_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
736 { .addr = CC1120_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
737 { .addr = CC1120_BIST, .name = "BIST" },
738 { .addr = CC1120_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
739 { .addr = CC1120_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
740 { .addr = CC1120_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
741 { .addr = CC1120_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
742 { .addr = CC1120_IQIE_I1, .name = "IQIE_I1" },
743 { .addr = CC1120_IQIE_I0, .name = "IQIE_I0" },
744 { .addr = CC1120_IQIE_Q1, .name = "IQIE_Q1" },
745 { .addr = CC1120_IQIE_Q0, .name = "IQIE_Q0" },
746 { .addr = CC1120_RSSI1, .name = "RSSI1" },
747 { .addr = CC1120_RSSI0, .name = "RSSI0" },
748 { .addr = CC1120_MARCSTATE, .name = "MARCSTATE" },
749 { .addr = CC1120_LQI_VAL, .name = "LQI_VAL" },
750 { .addr = CC1120_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
751 { .addr = CC1120_DEM_STATUS, .name = "DEM_STATUS" },
752 { .addr = CC1120_FREQOFF_EST1, .name = "FREQOFF_EST1" },
753 { .addr = CC1120_FREQOFF_EST0, .name = "FREQOFF_EST0" },
754 { .addr = CC1120_AGC_GAIN3, .name = "AGC_GAIN3" },
755 { .addr = CC1120_AGC_GAIN2, .name = "AGC_GAIN2" },
756 { .addr = CC1120_AGC_GAIN1, .name = "AGC_GAIN1" },
757 { .addr = CC1120_AGC_GAIN0, .name = "AGC_GAIN0" },
758 { .addr = CC1120_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
759 { .addr = CC1120_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
760 { .addr = CC1120_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
761 { .addr = CC1120_RNDGEN, .name = "RNDGEN" },
762 { .addr = CC1120_MAGN2, .name = "MAGN2" },
763 { .addr = CC1120_MAGN1, .name = "MAGN1" },
764 { .addr = CC1120_MAGN0, .name = "MAGN0" },
765 { .addr = CC1120_ANG1, .name = "ANG1" },
766 { .addr = CC1120_ANG0, .name = "ANG0" },
767 { .addr = CC1120_CHFILT_I2, .name = "CHFILT_I2" },
768 { .addr = CC1120_CHFILT_I1, .name = "CHFILT_I1" },
769 { .addr = CC1120_CHFILT_I0, .name = "CHFILT_I0" },
770 { .addr = CC1120_CHFILT_Q2, .name = "CHFILT_Q2" },
771 { .addr = CC1120_CHFILT_Q1, .name = "CHFILT_Q1" },
772 { .addr = CC1120_CHFILT_Q0, .name = "CHFILT_Q0" },
773 { .addr = CC1120_GPIO_STATUS, .name = "GPIO_STATUS" },
774 { .addr = CC1120_FSCAL_CTRL, .name = "FSCAL_CTRL" },
775 { .addr = CC1120_PHASE_ADJUST, .name = "PHASE_ADJUST" },
776 { .addr = CC1120_PARTNUMBER, .name = "PARTNUMBER" },
777 { .addr = CC1120_PARTVERSION, .name = "PARTVERSION" },
778 { .addr = CC1120_SERIAL_STATUS, .name = "SERIAL_STATUS" },
779 { .addr = CC1120_RX_STATUS, .name = "RX_STATUS" },
780 { .addr = CC1120_TX_STATUS, .name = "TX_STATUS" },
781 { .addr = CC1120_MARC_STATUS1, .name = "MARC_STATUS1" },
782 { .addr = CC1120_MARC_STATUS0, .name = "MARC_STATUS0" },
783 { .addr = CC1120_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
784 { .addr = CC1120_FSRF_TEST, .name = "FSRF_TEST" },
785 { .addr = CC1120_PRE_TEST, .name = "PRE_TEST" },
786 { .addr = CC1120_PRE_OVR, .name = "PRE_OVR" },
787 { .addr = CC1120_ADC_TEST, .name = "ADC_TEST" },
788 { .addr = CC1120_DVC_TEST, .name = "DVC_TEST" },
789 { .addr = CC1120_ATEST, .name = "ATEST" },
790 { .addr = CC1120_ATEST_LVDS, .name = "ATEST_LVDS" },
791 { .addr = CC1120_ATEST_MODE, .name = "ATEST_MODE" },
792 { .addr = CC1120_XOSC_TEST1, .name = "XOSC_TEST1" },
793 { .addr = CC1120_XOSC_TEST0, .name = "XOSC_TEST0" },
794 { .addr = CC1120_RXFIRST, .name = "RXFIRST" },
795 { .addr = CC1120_TXFIRST, .name = "TXFIRST" },
796 { .addr = CC1120_RXLAST, .name = "RXLAST" },
797 { .addr = CC1120_TXLAST, .name = "TXLAST" },
798 { .addr = CC1120_NUM_TXBYTES, .name = "NUM_TXBYTES" },
799 { .addr = CC1120_NUM_RXBYTES, .name = "NUM_RXBYTES" },
800 { .addr = CC1120_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
801 { .addr = CC1120_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
804 #define AO_NUM_CC1120_REG (sizeof ao_cc1120_reg / sizeof ao_cc1120_reg[0])
806 static void ao_radio_show(void) {
807 uint8_t status = ao_radio_status();
811 status = ao_radio_status();
812 printf ("Status: %02x\n", status);
813 printf ("CHIP_RDY: %d\n", (status >> CC1120_STATUS_CHIP_RDY) & 1);
814 printf ("STATE: %s\n", cc1120_state_name[(status >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK]);
815 printf ("MARC: %02x\n", ao_radio_marc_status());
817 for (i = 0; i < AO_NUM_CC1120_REG; i++)
818 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name);
822 static void ao_radio_beep(void) {
823 ao_radio_rdf(RDF_PACKET_LEN);
826 static void ao_radio_packet(void) {
827 static uint8_t packet[] = {
829 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
830 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
831 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
832 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
838 ao_radio_send(packet, sizeof (packet));
844 ao_radio_recv(0, 34);
849 static const struct ao_cmds ao_radio_cmds[] = {
850 { ao_radio_test, "C <1 start, 0 stop, none both>\0Radio carrier test" },
852 { ao_radio_show, "R\0Show CC1120 status" },
853 { ao_radio_beep, "b\0Emit an RDF beacon" },
854 { ao_radio_packet, "p\0Send a test packet" },
855 { ao_radio_test_recv, "q\0Recv a test packet" },
865 ao_radio_configured = 0;
866 ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN));
868 AO_CC1120_SPI_CS_PORT.bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN));
869 for (i = 0; i < 10000; i++) {
870 if ((SPI_2_GPIO.idr & (1 << SPI_2_MISO)) == 0)
873 AO_CC1120_SPI_CS_PORT.bsrr = (1 << AO_CC1120_SPI_CS_PIN);
875 ao_panic(AO_PANIC_SELF_TEST);
877 /* Enable the EXTI interrupt for the appropriate pin */
878 ao_enable_port(AO_CC1120_INT_PORT);
879 ao_exti_setup(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_EXTI_MODE_FALLING, ao_radio_tx_isr);
881 ao_cmd_register(&ao_radio_cmds[0]);