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