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;
27 uint8_t ao_radio_in_recv;
29 #define CC1120_DEBUG AO_FEC_DEBUG
30 #define CC1120_TRACE 0
33 #define fec_dump_bytes(b,l,n) ao_fec_dump_bytes(b,l,n)
35 #define fec_dump_bytes(b,l,n)
38 const uint32_t ao_radio_cal = 0x6ca333;
42 #define ao_radio_select() ao_spi_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS)
43 #define ao_radio_deselect() ao_spi_put_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS)
44 #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1120_SPI_BUS)
45 #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1120_SPI_BUS)
46 #define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1120_SPI_BUS)
47 #define ao_radio_duplex(o,i,l) ao_spi_duplex((o), (i), (l), AO_CC1120_SPI_BUS)
50 ao_radio_reg_read(uint16_t addr)
56 printf("\t\tao_radio_reg_read (%04x): ", addr); flush();
58 if (CC1120_IS_EXTENDED(addr)) {
59 data[0] = ((1 << CC1120_READ) |
65 data[0] = ((1 << CC1120_READ) |
71 ao_radio_spi_send(data, d);
72 ao_radio_spi_recv(data, 1);
75 printf (" %02x\n", data[0]);
81 ao_radio_reg_write(uint16_t addr, uint8_t value)
87 printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value);
89 if (CC1120_IS_EXTENDED(addr)) {
90 data[0] = ((0 << CC1120_READ) |
96 data[0] = ((0 << CC1120_READ) |
103 ao_radio_spi_send(data, d+1);
108 ao_radio_burst_read_start (uint16_t addr)
113 if (CC1120_IS_EXTENDED(addr)) {
114 data[0] = ((1 << CC1120_READ) |
115 (1 << CC1120_BURST) |
120 data[0] = ((1 << CC1120_READ) |
121 (1 << CC1120_BURST) |
126 ao_radio_spi_send(data, d);
130 ao_radio_burst_read_stop (void)
137 ao_radio_strobe(uint8_t addr)
142 printf("\t\tao_radio_strobe (%02x): ", addr); flush();
145 ao_radio_duplex(&addr, &in, 1);
148 printf("%02x\n", in); flush();
154 ao_radio_fifo_read(uint8_t *data, uint8_t len)
156 uint8_t addr = ((1 << CC1120_READ) |
157 (1 << CC1120_BURST) |
162 ao_radio_duplex(&addr, &status, 1);
163 ao_radio_spi_recv(data, len);
169 ao_radio_fifo_write(uint8_t *data, uint8_t len)
171 uint8_t addr = ((0 << CC1120_READ) |
172 (1 << CC1120_BURST) |
177 ao_radio_duplex(&addr, &status, 1);
178 ao_radio_spi_send(data, len);
184 ao_radio_fifo_write_fixed(uint8_t data, uint8_t len)
186 uint8_t addr = ((0 << CC1120_READ) |
187 (1 << CC1120_BURST) |
192 ao_radio_duplex(&addr, &status, 1);
193 ao_radio_spi_send_fixed(data, len);
199 ao_radio_tx_fifo_space(void)
201 return CC1120_FIFO_SIZE - ao_radio_reg_read(CC1120_NUM_TXBYTES);
205 ao_radio_status(void)
207 return ao_radio_strobe (CC1120_SNOP);
211 ao_radio_recv_abort(void)
214 ao_wakeup(&ao_radio_wake);
217 #define ao_radio_rdf_value 0x55
220 ao_radio_marc_status(void)
222 return ao_radio_reg_read(CC1120_MARC_STATUS1);
226 ao_radio_tx_isr(void)
228 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
230 ao_wakeup(&ao_radio_wake);
234 ao_radio_start_tx(void)
236 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_tx_isr);
237 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
238 ao_radio_strobe(CC1120_STX);
245 uint8_t state = ao_radio_strobe(CC1120_SIDLE);
246 if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_IDLE)
252 * Packet deviation is 20.5kHz
254 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
256 * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz
259 #define PACKET_DEV_E 5
260 #define PACKET_DEV_M 80
263 * For our packet data, set the symbol rate to 38360 Baud
265 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
266 * Rdata = -------------------------------------- * fosc
270 * DATARATE_M = 239914
273 #define PACKET_DRATE_E 9
274 #define PACKET_DRATE_M 239914
276 static const uint16_t packet_setup[] = {
277 CC1120_DEVIATION_M, PACKET_DEV_M,
278 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
279 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
280 (PACKET_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
281 CC1120_DRATE2, ((PACKET_DRATE_E << CC1120_DRATE2_DATARATE_E) |
282 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
283 CC1120_DRATE1, ((PACKET_DRATE_M >> 8) & 0xff),
284 CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff),
285 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
286 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
287 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
288 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
289 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
290 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
291 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
292 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
293 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
294 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
295 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
298 static const uint16_t packet_tx_setup[] = {
299 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
300 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
301 CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG,
304 static const uint16_t packet_rx_setup[] = {
305 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
306 (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT)),
307 CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT,
311 * RDF deviation is 5kHz
313 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
315 * 32e6Hz / (2 ** 24) * (256 + 71) * (2 ** 3) = 4989
320 #define RDF_PACKET_LEN 50
323 * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
325 * (2**20 - DATARATE_M) * 2 ** DATARATE_E
326 * Rdata = -------------------------------------- * fosc
329 * DATARATE_M = 511705
332 * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
334 #define RDF_DRATE_E 5
335 #define RDF_DRATE_M 25166
336 #define RDF_PACKET_LEN 50
338 static const uint16_t rdf_setup[] = {
339 CC1120_DEVIATION_M, RDF_DEV_M,
340 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
341 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
342 (RDF_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
343 CC1120_DRATE2, ((RDF_DRATE_E << CC1120_DRATE2_DATARATE_E) |
344 (((RDF_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
345 CC1120_DRATE1, ((RDF_DRATE_M >> 8) & 0xff),
346 CC1120_DRATE0, ((RDF_DRATE_M >> 0) & 0xff),
347 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
348 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
349 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
350 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
351 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
352 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
353 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
354 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
355 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
356 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
357 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
360 static uint8_t ao_radio_mode;
362 #define AO_RADIO_MODE_BITS_PACKET 1
363 #define AO_RADIO_MODE_BITS_PACKET_TX 2
364 #define AO_RADIO_MODE_BITS_TX_BUF 4
365 #define AO_RADIO_MODE_BITS_TX_FINISH 8
366 #define AO_RADIO_MODE_BITS_PACKET_RX 16
367 #define AO_RADIO_MODE_BITS_RDF 32
369 #define AO_RADIO_MODE_NONE 0
370 #define AO_RADIO_MODE_PACKET_TX_BUF (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_BUF)
371 #define AO_RADIO_MODE_PACKET_TX_FINISH (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_FINISH)
372 #define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_RX)
373 #define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_TX_FINISH)
376 ao_radio_set_mode(uint8_t new_mode)
381 if (new_mode == ao_radio_mode)
384 changes = new_mode & (~ao_radio_mode);
385 if (changes & AO_RADIO_MODE_BITS_PACKET)
386 for (i = 0; i < sizeof (packet_setup) / sizeof (packet_setup[0]); i += 2)
387 ao_radio_reg_write(packet_setup[i], packet_setup[i+1]);
389 if (changes & AO_RADIO_MODE_BITS_PACKET_TX)
390 for (i = 0; i < sizeof (packet_tx_setup) / sizeof (packet_tx_setup[0]); i += 2)
391 ao_radio_reg_write(packet_tx_setup[i], packet_tx_setup[i+1]);
393 if (changes & AO_RADIO_MODE_BITS_TX_BUF)
394 ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_TXFIFO_THR);
396 if (changes & AO_RADIO_MODE_BITS_TX_FINISH)
397 ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG);
399 if (changes & AO_RADIO_MODE_BITS_PACKET_RX)
400 for (i = 0; i < sizeof (packet_rx_setup) / sizeof (packet_rx_setup[0]); i += 2)
401 ao_radio_reg_write(packet_rx_setup[i], packet_rx_setup[i+1]);
403 if (changes & AO_RADIO_MODE_BITS_RDF)
404 for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2)
405 ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]);
406 ao_radio_mode = new_mode;
409 static const uint16_t radio_setup[] = {
410 #include "ao_cc1120_CC1120.h"
413 static uint8_t ao_radio_configured = 0;
420 ao_radio_strobe(CC1120_SRES);
422 for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2)
423 ao_radio_reg_write(radio_setup[i], radio_setup[i+1]);
429 ao_radio_configured = 1;
433 ao_radio_get(uint8_t len)
435 static uint32_t last_radio_setting;
436 static uint8_t last_len;
438 ao_mutex_get(&ao_radio_mutex);
439 if (!ao_radio_configured)
441 if (ao_config.radio_setting != last_radio_setting) {
442 ao_radio_reg_write(CC1120_FREQ2, ao_config.radio_setting >> 16);
443 ao_radio_reg_write(CC1120_FREQ1, ao_config.radio_setting >> 8);
444 ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting);
445 last_radio_setting = ao_config.radio_setting;
447 if (len != last_len) {
448 ao_radio_reg_write(CC1120_PKT_LEN, len);
453 #define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
456 ao_radio_rdf(uint8_t len)
463 ao_radio_set_mode(AO_RADIO_MODE_RDF);
466 ao_radio_fifo_write_fixed(ao_radio_rdf_value, len);
471 while (!ao_radio_wake && !ao_radio_abort)
472 ao_sleep(&ao_radio_wake);
480 ao_radio_rdf_abort(void)
483 ao_wakeup(&ao_radio_wake);
492 if (ao_cmd_lex_c != '\n') {
494 mode = (uint8_t) ao_cmd_lex_u32;
497 if ((mode & 2) && !radio_on) {
499 ao_monitor_disable();
502 ao_packet_slave_stop();
505 ao_radio_strobe(CC1120_STX);
508 for (t = 0; t < 10; t++) {
509 printf ("status: %02x\n", ao_radio_status());
510 ao_delay(AO_MS_TO_TICKS(100));
517 printf ("Hit a character to stop..."); flush();
521 if ((mode & 1) && radio_on) {
532 ao_radio_send(const void *d, uint8_t size)
535 static uint8_t encode[256];
542 encode_len = ao_fec_encode(d, size, encode);
544 ao_radio_get(encode_len);
547 fifo_space = CC1120_FIFO_SIZE;
549 this_len = encode_len;
551 if (this_len > fifo_space) {
552 this_len = fifo_space;
553 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_BUF);
555 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_FINISH);
558 ao_radio_fifo_write(e, this_len);
560 encode_len -= this_len;
566 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
572 while (!ao_radio_wake)
573 ao_sleep(&ao_radio_wake);
577 fifo_space = ao_radio_tx_fifo_space();
578 } while (!fifo_space);
583 #define AO_RADIO_MAX_RECV 90
585 uint8_t rx_data[(AO_RADIO_MAX_RECV + 4) * 2 * 8];
586 uint16_t rx_data_count;
587 uint16_t rx_data_consumed;
588 uint16_t rx_data_cur;
593 static uint32_t rx_start_tick, rx_packet_tick, rx_done_tick, rx_last_done_tick;
595 uint32_t ao_rx_start_tick, ao_rx_packet_tick, ao_rx_done_tick, ao_rx_last_done_tick;
597 #include <ao_profile.h>
601 ao_radio_rx_isr(void)
607 if (rx_ignore == 0) {
608 if (rx_data_cur >= rx_data_count)
609 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
611 rx_data[rx_data_cur++] = d;
612 if (rx_waiting && rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) {
614 if (rx_data_consumed == 0)
615 rx_packet_tick = ao_profile_tick();
618 ao_wakeup(&ao_radio_wake);
626 ao_radio_rx_wait(void)
630 while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&
632 ao_sleep(&ao_radio_wake);
638 rx_data_consumed += AO_FEC_DECODE_BLOCK;
639 return AO_FEC_DECODE_BLOCK;
643 ao_radio_recv(__xdata void *d, uint8_t size)
649 static int been_here = 0;
651 size -= 2; /* status bytes */
652 if (size > AO_RADIO_MAX_RECV) {
653 ao_delay(AO_SEC_TO_TICKS(1));
657 rx_start_tick = ao_profile_tick();
659 len = size + 2; /* CRC bytes */
660 len += 1 + ~(len & 1); /* 1 or two pad bytes */
661 len *= 2; /* 1/2 rate convolution */
662 rx_data_count = len * 8; /* bytes to bits */
664 rx_data_consumed = 0;
668 ao_radio_in_recv = 1;
669 /* configure interrupt pin */
671 ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
680 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
681 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
683 ao_radio_strobe(CC1120_SRX);
685 ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
687 ret = ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait);
689 ao_radio_burst_read_stop();
691 ao_radio_strobe(CC1120_SIDLE);
693 /* Convert from 'real' rssi to cc1111-style values */
695 rssi = (((int8_t) ao_radio_reg_read(CC1120_RSSI1)) + 74) * 2;
699 /* Construct final packet */
701 if (ret && ((uint8_t *) d)[size] == 0 && ((uint8_t *)d)[size+1] == 0)
702 ((uint8_t *) d)[size + 1] = 0x80;
704 ((uint8_t *) d)[size + 1] = 0x00;
706 ((uint8_t *) d)[size] = (uint8_t) rssi;
708 ao_radio_in_recv = 0;
714 rx_last_done_tick = rx_done_tick;
715 rx_done_tick = ao_profile_tick();
717 ao_rx_start_tick = rx_start_tick;
718 ao_rx_packet_tick = rx_packet_tick;
719 ao_rx_done_tick = rx_done_tick;
720 ao_rx_last_done_tick = rx_last_done_tick;
728 static char *cc1120_state_name[] = {
729 [CC1120_STATUS_STATE_IDLE] = "IDLE",
730 [CC1120_STATUS_STATE_RX] = "RX",
731 [CC1120_STATUS_STATE_TX] = "TX",
732 [CC1120_STATUS_STATE_FSTXON] = "FSTXON",
733 [CC1120_STATUS_STATE_CALIBRATE] = "CALIBRATE",
734 [CC1120_STATUS_STATE_SETTLING] = "SETTLING",
735 [CC1120_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
736 [CC1120_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
739 struct ao_cc1120_reg {
744 const static struct ao_cc1120_reg ao_cc1120_reg[] = {
745 { .addr = CC1120_IOCFG3, .name = "IOCFG3" },
746 { .addr = CC1120_IOCFG2, .name = "IOCFG2" },
747 { .addr = CC1120_IOCFG1, .name = "IOCFG1" },
748 { .addr = CC1120_IOCFG0, .name = "IOCFG0" },
749 { .addr = CC1120_SYNC3, .name = "SYNC3" },
750 { .addr = CC1120_SYNC2, .name = "SYNC2" },
751 { .addr = CC1120_SYNC1, .name = "SYNC1" },
752 { .addr = CC1120_SYNC0, .name = "SYNC0" },
753 { .addr = CC1120_SYNC_CFG1, .name = "SYNC_CFG1" },
754 { .addr = CC1120_SYNC_CFG0, .name = "SYNC_CFG0" },
755 { .addr = CC1120_DEVIATION_M, .name = "DEVIATION_M" },
756 { .addr = CC1120_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
757 { .addr = CC1120_DCFILT_CFG, .name = "DCFILT_CFG" },
758 { .addr = CC1120_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
759 { .addr = CC1120_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
760 { .addr = CC1120_FREQ_IF_CFG, .name = "FREQ_IF_CFG" },
761 { .addr = CC1120_IQIC, .name = "IQIC" },
762 { .addr = CC1120_CHAN_BW, .name = "CHAN_BW" },
763 { .addr = CC1120_MDMCFG1, .name = "MDMCFG1" },
764 { .addr = CC1120_MDMCFG0, .name = "MDMCFG0" },
765 { .addr = CC1120_DRATE2, .name = "DRATE2" },
766 { .addr = CC1120_DRATE1, .name = "DRATE1" },
767 { .addr = CC1120_DRATE0, .name = "DRATE0" },
768 { .addr = CC1120_AGC_REF, .name = "AGC_REF" },
769 { .addr = CC1120_AGC_CS_THR, .name = "AGC_CS_THR" },
770 { .addr = CC1120_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
771 { .addr = CC1120_AGC_CFG3, .name = "AGC_CFG3" },
772 { .addr = CC1120_AGC_CFG2, .name = "AGC_CFG2" },
773 { .addr = CC1120_AGC_CFG1, .name = "AGC_CFG1" },
774 { .addr = CC1120_AGC_CFG0, .name = "AGC_CFG0" },
775 { .addr = CC1120_FIFO_CFG, .name = "FIFO_CFG" },
776 { .addr = CC1120_DEV_ADDR, .name = "DEV_ADDR" },
777 { .addr = CC1120_SETTLING_CFG, .name = "SETTLING_CFG" },
778 { .addr = CC1120_FS_CFG, .name = "FS_CFG" },
779 { .addr = CC1120_WOR_CFG1, .name = "WOR_CFG1" },
780 { .addr = CC1120_WOR_CFG0, .name = "WOR_CFG0" },
781 { .addr = CC1120_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
782 { .addr = CC1120_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
783 { .addr = CC1120_PKT_CFG2, .name = "PKT_CFG2" },
784 { .addr = CC1120_PKT_CFG1, .name = "PKT_CFG1" },
785 { .addr = CC1120_PKT_CFG0, .name = "PKT_CFG0" },
786 { .addr = CC1120_RFEND_CFG1, .name = "RFEND_CFG1" },
787 { .addr = CC1120_RFEND_CFG0, .name = "RFEND_CFG0" },
788 { .addr = CC1120_PA_CFG2, .name = "PA_CFG2" },
789 { .addr = CC1120_PA_CFG1, .name = "PA_CFG1" },
790 { .addr = CC1120_PA_CFG0, .name = "PA_CFG0" },
791 { .addr = CC1120_PKT_LEN, .name = "PKT_LEN" },
792 { .addr = CC1120_IF_MIX_CFG, .name = "IF_MIX_CFG" },
793 { .addr = CC1120_FREQOFF_CFG, .name = "FREQOFF_CFG" },
794 { .addr = CC1120_TOC_CFG, .name = "TOC_CFG" },
795 { .addr = CC1120_MARC_SPARE, .name = "MARC_SPARE" },
796 { .addr = CC1120_ECG_CFG, .name = "ECG_CFG" },
797 { .addr = CC1120_SOFT_TX_DATA_CFG, .name = "SOFT_TX_DATA_CFG" },
798 { .addr = CC1120_EXT_CTRL, .name = "EXT_CTRL" },
799 { .addr = CC1120_RCCAL_FINE, .name = "RCCAL_FINE" },
800 { .addr = CC1120_RCCAL_COARSE, .name = "RCCAL_COARSE" },
801 { .addr = CC1120_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
802 { .addr = CC1120_FREQOFF1, .name = "FREQOFF1" },
803 { .addr = CC1120_FREQOFF0, .name = "FREQOFF0" },
804 { .addr = CC1120_FREQ2, .name = "FREQ2" },
805 { .addr = CC1120_FREQ1, .name = "FREQ1" },
806 { .addr = CC1120_FREQ0, .name = "FREQ0" },
807 { .addr = CC1120_IF_ADC2, .name = "IF_ADC2" },
808 { .addr = CC1120_IF_ADC1, .name = "IF_ADC1" },
809 { .addr = CC1120_IF_ADC0, .name = "IF_ADC0" },
810 { .addr = CC1120_FS_DIG1, .name = "FS_DIG1" },
811 { .addr = CC1120_FS_DIG0, .name = "FS_DIG0" },
812 { .addr = CC1120_FS_CAL3, .name = "FS_CAL3" },
813 { .addr = CC1120_FS_CAL2, .name = "FS_CAL2" },
814 { .addr = CC1120_FS_CAL1, .name = "FS_CAL1" },
815 { .addr = CC1120_FS_CAL0, .name = "FS_CAL0" },
816 { .addr = CC1120_FS_CHP, .name = "FS_CHP" },
817 { .addr = CC1120_FS_DIVTWO, .name = "FS_DIVTWO" },
818 { .addr = CC1120_FS_DSM1, .name = "FS_DSM1" },
819 { .addr = CC1120_FS_DSM0, .name = "FS_DSM0" },
820 { .addr = CC1120_FS_DVC1, .name = "FS_DVC1" },
821 { .addr = CC1120_FS_DVC0, .name = "FS_DVC0" },
822 { .addr = CC1120_FS_LBI, .name = "FS_LBI" },
823 { .addr = CC1120_FS_PFD, .name = "FS_PFD" },
824 { .addr = CC1120_FS_PRE, .name = "FS_PRE" },
825 { .addr = CC1120_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
826 { .addr = CC1120_FS_SPARE, .name = "FS_SPARE" },
827 { .addr = CC1120_FS_VCO4, .name = "FS_VCO4" },
828 { .addr = CC1120_FS_VCO3, .name = "FS_VCO3" },
829 { .addr = CC1120_FS_VCO2, .name = "FS_VCO2" },
830 { .addr = CC1120_FS_VCO1, .name = "FS_VCO1" },
831 { .addr = CC1120_FS_VCO0, .name = "FS_VCO0" },
832 { .addr = CC1120_GBIAS6, .name = "GBIAS6" },
833 { .addr = CC1120_GBIAS5, .name = "GBIAS5" },
834 { .addr = CC1120_GBIAS4, .name = "GBIAS4" },
835 { .addr = CC1120_GBIAS3, .name = "GBIAS3" },
836 { .addr = CC1120_GBIAS2, .name = "GBIAS2" },
837 { .addr = CC1120_GBIAS1, .name = "GBIAS1" },
838 { .addr = CC1120_GBIAS0, .name = "GBIAS0" },
839 { .addr = CC1120_IFAMP, .name = "IFAMP" },
840 { .addr = CC1120_LNA, .name = "LNA" },
841 { .addr = CC1120_RXMIX, .name = "RXMIX" },
842 { .addr = CC1120_XOSC5, .name = "XOSC5" },
843 { .addr = CC1120_XOSC4, .name = "XOSC4" },
844 { .addr = CC1120_XOSC3, .name = "XOSC3" },
845 { .addr = CC1120_XOSC2, .name = "XOSC2" },
846 { .addr = CC1120_XOSC1, .name = "XOSC1" },
847 { .addr = CC1120_XOSC0, .name = "XOSC0" },
848 { .addr = CC1120_ANALOG_SPARE, .name = "ANALOG_SPARE" },
849 { .addr = CC1120_PA_CFG3, .name = "PA_CFG3" },
850 { .addr = CC1120_WOR_TIME1, .name = "WOR_TIME1" },
851 { .addr = CC1120_WOR_TIME0, .name = "WOR_TIME0" },
852 { .addr = CC1120_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
853 { .addr = CC1120_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
854 { .addr = CC1120_BIST, .name = "BIST" },
855 { .addr = CC1120_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
856 { .addr = CC1120_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
857 { .addr = CC1120_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
858 { .addr = CC1120_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
859 { .addr = CC1120_IQIE_I1, .name = "IQIE_I1" },
860 { .addr = CC1120_IQIE_I0, .name = "IQIE_I0" },
861 { .addr = CC1120_IQIE_Q1, .name = "IQIE_Q1" },
862 { .addr = CC1120_IQIE_Q0, .name = "IQIE_Q0" },
863 { .addr = CC1120_RSSI1, .name = "RSSI1" },
864 { .addr = CC1120_RSSI0, .name = "RSSI0" },
865 { .addr = CC1120_MARCSTATE, .name = "MARCSTATE" },
866 { .addr = CC1120_LQI_VAL, .name = "LQI_VAL" },
867 { .addr = CC1120_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
868 { .addr = CC1120_DEM_STATUS, .name = "DEM_STATUS" },
869 { .addr = CC1120_FREQOFF_EST1, .name = "FREQOFF_EST1" },
870 { .addr = CC1120_FREQOFF_EST0, .name = "FREQOFF_EST0" },
871 { .addr = CC1120_AGC_GAIN3, .name = "AGC_GAIN3" },
872 { .addr = CC1120_AGC_GAIN2, .name = "AGC_GAIN2" },
873 { .addr = CC1120_AGC_GAIN1, .name = "AGC_GAIN1" },
874 { .addr = CC1120_AGC_GAIN0, .name = "AGC_GAIN0" },
875 { .addr = CC1120_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
876 { .addr = CC1120_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
877 { .addr = CC1120_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
878 { .addr = CC1120_RNDGEN, .name = "RNDGEN" },
879 { .addr = CC1120_MAGN2, .name = "MAGN2" },
880 { .addr = CC1120_MAGN1, .name = "MAGN1" },
881 { .addr = CC1120_MAGN0, .name = "MAGN0" },
882 { .addr = CC1120_ANG1, .name = "ANG1" },
883 { .addr = CC1120_ANG0, .name = "ANG0" },
884 { .addr = CC1120_CHFILT_I2, .name = "CHFILT_I2" },
885 { .addr = CC1120_CHFILT_I1, .name = "CHFILT_I1" },
886 { .addr = CC1120_CHFILT_I0, .name = "CHFILT_I0" },
887 { .addr = CC1120_CHFILT_Q2, .name = "CHFILT_Q2" },
888 { .addr = CC1120_CHFILT_Q1, .name = "CHFILT_Q1" },
889 { .addr = CC1120_CHFILT_Q0, .name = "CHFILT_Q0" },
890 { .addr = CC1120_GPIO_STATUS, .name = "GPIO_STATUS" },
891 { .addr = CC1120_FSCAL_CTRL, .name = "FSCAL_CTRL" },
892 { .addr = CC1120_PHASE_ADJUST, .name = "PHASE_ADJUST" },
893 { .addr = CC1120_PARTNUMBER, .name = "PARTNUMBER" },
894 { .addr = CC1120_PARTVERSION, .name = "PARTVERSION" },
895 { .addr = CC1120_SERIAL_STATUS, .name = "SERIAL_STATUS" },
896 { .addr = CC1120_RX_STATUS, .name = "RX_STATUS" },
897 { .addr = CC1120_TX_STATUS, .name = "TX_STATUS" },
898 { .addr = CC1120_MARC_STATUS1, .name = "MARC_STATUS1" },
899 { .addr = CC1120_MARC_STATUS0, .name = "MARC_STATUS0" },
900 { .addr = CC1120_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
901 { .addr = CC1120_FSRF_TEST, .name = "FSRF_TEST" },
902 { .addr = CC1120_PRE_TEST, .name = "PRE_TEST" },
903 { .addr = CC1120_PRE_OVR, .name = "PRE_OVR" },
904 { .addr = CC1120_ADC_TEST, .name = "ADC_TEST" },
905 { .addr = CC1120_DVC_TEST, .name = "DVC_TEST" },
906 { .addr = CC1120_ATEST, .name = "ATEST" },
907 { .addr = CC1120_ATEST_LVDS, .name = "ATEST_LVDS" },
908 { .addr = CC1120_ATEST_MODE, .name = "ATEST_MODE" },
909 { .addr = CC1120_XOSC_TEST1, .name = "XOSC_TEST1" },
910 { .addr = CC1120_XOSC_TEST0, .name = "XOSC_TEST0" },
911 { .addr = CC1120_RXFIRST, .name = "RXFIRST" },
912 { .addr = CC1120_TXFIRST, .name = "TXFIRST" },
913 { .addr = CC1120_RXLAST, .name = "RXLAST" },
914 { .addr = CC1120_TXLAST, .name = "TXLAST" },
915 { .addr = CC1120_NUM_TXBYTES, .name = "NUM_TXBYTES" },
916 { .addr = CC1120_NUM_RXBYTES, .name = "NUM_RXBYTES" },
917 { .addr = CC1120_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
918 { .addr = CC1120_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
921 #define AO_NUM_CC1120_REG (sizeof ao_cc1120_reg / sizeof ao_cc1120_reg[0])
923 static void ao_radio_show(void) {
924 uint8_t status = ao_radio_status();
928 status = ao_radio_status();
929 printf ("Status: %02x\n", status);
930 printf ("CHIP_RDY: %d\n", (status >> CC1120_STATUS_CHIP_RDY) & 1);
931 printf ("STATE: %s\n", cc1120_state_name[(status >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK]);
932 printf ("MARC: %02x\n", ao_radio_marc_status());
934 for (i = 0; i < AO_NUM_CC1120_REG; i++)
935 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name);
939 static void ao_radio_beep(void) {
940 ao_radio_rdf(RDF_PACKET_LEN);
943 static void ao_radio_packet(void) {
944 static const uint8_t packet[] = {
946 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
947 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
948 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
949 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
955 ao_radio_send(packet, sizeof (packet));
964 if (ao_radio_recv(bytes, 34)) {
965 if (bytes[33] & 0x80)
969 printf (" RSSI %d", (int16_t) ((int8_t) bytes[32] >> 1) - 74);
970 for (b = 0; b < 32; b++)
971 printf (" %02x", bytes[b]);
978 static const struct ao_cmds ao_radio_cmds[] = {
979 { ao_radio_test, "C <1 start, 0 stop, none both>\0Radio carrier test" },
981 { ao_radio_show, "R\0Show CC1120 status" },
982 { ao_radio_beep, "b\0Emit an RDF beacon" },
983 { ao_radio_packet, "p\0Send a test packet" },
984 { ao_radio_test_recv, "q\0Recv a test packet" },
994 ao_radio_configured = 0;
995 ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN));
997 AO_CC1120_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN));
998 for (i = 0; i < 10000; i++) {
999 if ((SPI_2_GPIO->idr & (1 << SPI_2_MISO)) == 0)
1002 AO_CC1120_SPI_CS_PORT->bsrr = (1 << AO_CC1120_SPI_CS_PIN);
1004 ao_panic(AO_PANIC_SELF_TEST);
1006 /* Enable the EXTI interrupt for the appropriate pin */
1007 ao_enable_port(AO_CC1120_INT_PORT);
1008 ao_exti_setup(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1009 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
1012 ao_cmd_register(&ao_radio_cmds[0]);