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
32 const uint32_t ao_radio_cal = 0x6ca333;
36 #define ao_radio_select() ao_spi_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS,AO_SPI_SPEED_1MHz)
37 #define ao_radio_deselect() ao_spi_put_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS)
38 #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1120_SPI_BUS)
39 #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1120_SPI_BUS)
40 #define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1120_SPI_BUS)
41 #define ao_radio_duplex(o,i,l) ao_spi_duplex((o), (i), (l), AO_CC1120_SPI_BUS)
44 ao_radio_reg_read(uint16_t addr)
50 printf("\t\tao_radio_reg_read (%04x): ", addr); flush();
52 if (CC1120_IS_EXTENDED(addr)) {
53 data[0] = ((1 << CC1120_READ) |
59 data[0] = ((1 << CC1120_READ) |
65 ao_radio_spi_send(data, d);
66 ao_radio_spi_recv(data, 1);
69 printf (" %02x\n", data[0]);
75 ao_radio_reg_write(uint16_t addr, uint8_t value)
81 printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value);
83 if (CC1120_IS_EXTENDED(addr)) {
84 data[0] = ((0 << CC1120_READ) |
90 data[0] = ((0 << CC1120_READ) |
97 ao_radio_spi_send(data, d+1);
102 ao_radio_burst_read_start (uint16_t addr)
107 if (CC1120_IS_EXTENDED(addr)) {
108 data[0] = ((1 << CC1120_READ) |
109 (1 << CC1120_BURST) |
114 data[0] = ((1 << CC1120_READ) |
115 (1 << CC1120_BURST) |
120 ao_radio_spi_send(data, d);
124 ao_radio_burst_read_stop (void)
131 ao_radio_strobe(uint8_t addr)
136 printf("\t\tao_radio_strobe (%02x): ", addr); flush();
139 ao_radio_duplex(&addr, &in, 1);
142 printf("%02x\n", in); flush();
148 ao_radio_fifo_read(uint8_t *data, uint8_t len)
150 uint8_t addr = ((1 << CC1120_READ) |
151 (1 << CC1120_BURST) |
156 ao_radio_duplex(&addr, &status, 1);
157 ao_radio_spi_recv(data, len);
163 ao_radio_fifo_write(uint8_t *data, uint8_t len)
165 uint8_t addr = ((0 << CC1120_READ) |
166 (1 << CC1120_BURST) |
171 ao_radio_duplex(&addr, &status, 1);
172 ao_radio_spi_send(data, len);
178 ao_radio_fifo_write_fixed(uint8_t data, uint8_t len)
180 uint8_t addr = ((0 << CC1120_READ) |
181 (1 << CC1120_BURST) |
186 ao_radio_duplex(&addr, &status, 1);
187 ao_radio_spi_send_fixed(data, len);
193 ao_radio_tx_fifo_space(void)
195 return CC1120_FIFO_SIZE - ao_radio_reg_read(CC1120_NUM_TXBYTES);
199 ao_radio_status(void)
201 return ao_radio_strobe (CC1120_SNOP);
205 ao_radio_recv_abort(void)
208 ao_wakeup(&ao_radio_wake);
211 #define ao_radio_rdf_value 0x55
214 ao_radio_marc_status(void)
216 return ao_radio_reg_read(CC1120_MARC_STATUS1);
220 ao_radio_tx_isr(void)
222 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
224 ao_wakeup(&ao_radio_wake);
228 ao_radio_start_tx(void)
230 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_tx_isr);
231 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
232 ao_radio_strobe(CC1120_STX);
239 uint8_t state = ao_radio_strobe(CC1120_SIDLE);
240 if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_IDLE)
246 * Packet deviation is 20.5kHz
248 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
250 * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz
253 #define PACKET_DEV_E 5
254 #define PACKET_DEV_M 80
257 * For our packet data, set the symbol rate to 38360 Baud
259 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
260 * Rdata = -------------------------------------- * fosc
264 * DATARATE_M = 239914
267 #define PACKET_DRATE_E 9
268 #define PACKET_DRATE_M 239914
270 static const uint16_t packet_setup[] = {
271 CC1120_DEVIATION_M, PACKET_DEV_M,
272 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
273 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
274 (PACKET_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
275 CC1120_DRATE2, ((PACKET_DRATE_E << CC1120_DRATE2_DATARATE_E) |
276 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
277 CC1120_DRATE1, ((PACKET_DRATE_M >> 8) & 0xff),
278 CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff),
279 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
280 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
281 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
282 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
283 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
284 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
285 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
286 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
287 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
288 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
289 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
292 static const uint16_t packet_tx_setup[] = {
293 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
294 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
295 CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG,
298 static const uint16_t packet_rx_setup[] = {
299 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
300 (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT)),
301 CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT,
305 * RDF deviation is 5kHz
307 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
309 * 32e6Hz / (2 ** 24) * (256 + 71) * (2 ** 3) = 4989
314 #define RDF_PACKET_LEN 50
317 * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
319 * (2**20 - DATARATE_M) * 2 ** DATARATE_E
320 * Rdata = -------------------------------------- * fosc
323 * DATARATE_M = 511705
326 * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
328 #define RDF_DRATE_E 5
329 #define RDF_DRATE_M 25166
330 #define RDF_PACKET_LEN 50
332 static const uint16_t rdf_setup[] = {
333 CC1120_DEVIATION_M, RDF_DEV_M,
334 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
335 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
336 (RDF_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
337 CC1120_DRATE2, ((RDF_DRATE_E << CC1120_DRATE2_DATARATE_E) |
338 (((RDF_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
339 CC1120_DRATE1, ((RDF_DRATE_M >> 8) & 0xff),
340 CC1120_DRATE0, ((RDF_DRATE_M >> 0) & 0xff),
341 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
342 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
343 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
344 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
345 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
346 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
347 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
348 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
349 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
350 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
351 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
354 static uint8_t ao_radio_mode;
356 #define AO_RADIO_MODE_BITS_PACKET 1
357 #define AO_RADIO_MODE_BITS_PACKET_TX 2
358 #define AO_RADIO_MODE_BITS_TX_BUF 4
359 #define AO_RADIO_MODE_BITS_TX_FINISH 8
360 #define AO_RADIO_MODE_BITS_PACKET_RX 16
361 #define AO_RADIO_MODE_BITS_RDF 32
363 #define AO_RADIO_MODE_NONE 0
364 #define AO_RADIO_MODE_PACKET_TX_BUF (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_BUF)
365 #define AO_RADIO_MODE_PACKET_TX_FINISH (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_FINISH)
366 #define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_RX)
367 #define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_TX_FINISH)
370 ao_radio_set_mode(uint8_t new_mode)
375 if (new_mode == ao_radio_mode)
378 changes = new_mode & (~ao_radio_mode);
379 if (changes & AO_RADIO_MODE_BITS_PACKET)
380 for (i = 0; i < sizeof (packet_setup) / sizeof (packet_setup[0]); i += 2)
381 ao_radio_reg_write(packet_setup[i], packet_setup[i+1]);
383 if (changes & AO_RADIO_MODE_BITS_PACKET_TX)
384 for (i = 0; i < sizeof (packet_tx_setup) / sizeof (packet_tx_setup[0]); i += 2)
385 ao_radio_reg_write(packet_tx_setup[i], packet_tx_setup[i+1]);
387 if (changes & AO_RADIO_MODE_BITS_TX_BUF)
388 ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_TXFIFO_THR);
390 if (changes & AO_RADIO_MODE_BITS_TX_FINISH)
391 ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG);
393 if (changes & AO_RADIO_MODE_BITS_PACKET_RX)
394 for (i = 0; i < sizeof (packet_rx_setup) / sizeof (packet_rx_setup[0]); i += 2)
395 ao_radio_reg_write(packet_rx_setup[i], packet_rx_setup[i+1]);
397 if (changes & AO_RADIO_MODE_BITS_RDF)
398 for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2)
399 ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]);
400 ao_radio_mode = new_mode;
403 static const uint16_t radio_setup[] = {
404 #include "ao_cc1120_CC1120.h"
407 static uint8_t ao_radio_configured = 0;
414 ao_radio_strobe(CC1120_SRES);
416 for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2)
417 ao_radio_reg_write(radio_setup[i], radio_setup[i+1]);
423 ao_radio_configured = 1;
427 ao_radio_get(uint8_t len)
429 static uint32_t last_radio_setting;
430 static uint8_t last_len;
432 ao_mutex_get(&ao_radio_mutex);
433 if (!ao_radio_configured)
435 if (ao_config.radio_setting != last_radio_setting) {
436 ao_radio_reg_write(CC1120_FREQ2, ao_config.radio_setting >> 16);
437 ao_radio_reg_write(CC1120_FREQ1, ao_config.radio_setting >> 8);
438 ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting);
439 last_radio_setting = ao_config.radio_setting;
441 if (len != last_len) {
442 ao_radio_reg_write(CC1120_PKT_LEN, len);
447 #define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
450 ao_radio_rdf(uint8_t len)
457 ao_radio_set_mode(AO_RADIO_MODE_RDF);
460 ao_radio_fifo_write_fixed(ao_radio_rdf_value, len);
465 while (!ao_radio_wake && !ao_radio_abort)
466 ao_sleep(&ao_radio_wake);
474 ao_radio_rdf_abort(void)
477 ao_wakeup(&ao_radio_wake);
486 if (ao_cmd_lex_c != '\n') {
488 mode = (uint8_t) ao_cmd_lex_u32;
491 if ((mode & 2) && !radio_on) {
493 ao_monitor_disable();
496 ao_packet_slave_stop();
499 ao_radio_strobe(CC1120_STX);
502 for (t = 0; t < 10; t++) {
503 printf ("status: %02x\n", ao_radio_status());
504 ao_delay(AO_MS_TO_TICKS(100));
511 printf ("Hit a character to stop..."); flush();
515 if ((mode & 1) && radio_on) {
526 ao_radio_send(const void *d, uint8_t size)
529 static uint8_t encode[256];
536 encode_len = ao_fec_encode(d, size, encode);
538 ao_radio_get(encode_len);
541 fifo_space = CC1120_FIFO_SIZE;
543 this_len = encode_len;
545 if (this_len > fifo_space) {
546 this_len = fifo_space;
547 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_BUF);
549 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_FINISH);
552 ao_radio_fifo_write(e, this_len);
554 encode_len -= this_len;
560 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
566 while (!ao_radio_wake)
567 ao_sleep(&ao_radio_wake);
571 fifo_space = ao_radio_tx_fifo_space();
572 } while (!fifo_space);
577 #define AO_RADIO_MAX_RECV 90
579 static uint8_t rx_data[(AO_RADIO_MAX_RECV + 4) * 2 * 8];
580 static uint16_t rx_data_count;
581 static uint16_t rx_data_consumed;
582 static uint16_t rx_data_cur;
583 static uint8_t rx_ignore;
584 static uint8_t rx_waiting;
587 static uint32_t rx_start_tick, rx_packet_tick, rx_done_tick, rx_last_done_tick;
589 uint32_t ao_rx_start_tick, ao_rx_packet_tick, ao_rx_done_tick, ao_rx_last_done_tick;
591 #include <ao_profile.h>
595 ao_radio_rx_isr(void)
601 if (rx_ignore == 0) {
602 if (rx_data_cur >= rx_data_count)
603 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
605 rx_data[rx_data_cur++] = d;
606 if (rx_waiting && rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) {
609 rx_packet_tick = ao_profile_tick();
610 if (rx_data_cur < rx_data_count)
614 ao_wakeup(&ao_radio_wake);
622 ao_radio_rx_wait(void)
626 while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&
628 ao_sleep(&ao_radio_wake);
634 rx_data_consumed += AO_FEC_DECODE_BLOCK;
636 return rx_data_cur - rx_data_consumed;
638 return AO_FEC_DECODE_BLOCK;
642 ao_radio_recv(__xdata void *d, uint8_t size)
648 static int been_here = 0;
650 size -= 2; /* status bytes */
651 if (size > AO_RADIO_MAX_RECV) {
652 ao_delay(AO_SEC_TO_TICKS(1));
656 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 /* Store the received RSSI value; the crc-OK byte is already done */
701 ((uint8_t *) d)[size] = (uint8_t) rssi;
703 ao_radio_in_recv = 0;
709 rx_last_done_tick = rx_done_tick;
710 rx_done_tick = ao_profile_tick();
712 ao_rx_start_tick = rx_start_tick;
713 ao_rx_packet_tick = rx_packet_tick;
714 ao_rx_done_tick = rx_done_tick;
715 ao_rx_last_done_tick = rx_last_done_tick;
723 static char *cc1120_state_name[] = {
724 [CC1120_STATUS_STATE_IDLE] = "IDLE",
725 [CC1120_STATUS_STATE_RX] = "RX",
726 [CC1120_STATUS_STATE_TX] = "TX",
727 [CC1120_STATUS_STATE_FSTXON] = "FSTXON",
728 [CC1120_STATUS_STATE_CALIBRATE] = "CALIBRATE",
729 [CC1120_STATUS_STATE_SETTLING] = "SETTLING",
730 [CC1120_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
731 [CC1120_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
734 struct ao_cc1120_reg {
739 const static struct ao_cc1120_reg ao_cc1120_reg[] = {
740 { .addr = CC1120_IOCFG3, .name = "IOCFG3" },
741 { .addr = CC1120_IOCFG2, .name = "IOCFG2" },
742 { .addr = CC1120_IOCFG1, .name = "IOCFG1" },
743 { .addr = CC1120_IOCFG0, .name = "IOCFG0" },
744 { .addr = CC1120_SYNC3, .name = "SYNC3" },
745 { .addr = CC1120_SYNC2, .name = "SYNC2" },
746 { .addr = CC1120_SYNC1, .name = "SYNC1" },
747 { .addr = CC1120_SYNC0, .name = "SYNC0" },
748 { .addr = CC1120_SYNC_CFG1, .name = "SYNC_CFG1" },
749 { .addr = CC1120_SYNC_CFG0, .name = "SYNC_CFG0" },
750 { .addr = CC1120_DEVIATION_M, .name = "DEVIATION_M" },
751 { .addr = CC1120_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
752 { .addr = CC1120_DCFILT_CFG, .name = "DCFILT_CFG" },
753 { .addr = CC1120_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
754 { .addr = CC1120_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
755 { .addr = CC1120_FREQ_IF_CFG, .name = "FREQ_IF_CFG" },
756 { .addr = CC1120_IQIC, .name = "IQIC" },
757 { .addr = CC1120_CHAN_BW, .name = "CHAN_BW" },
758 { .addr = CC1120_MDMCFG1, .name = "MDMCFG1" },
759 { .addr = CC1120_MDMCFG0, .name = "MDMCFG0" },
760 { .addr = CC1120_DRATE2, .name = "DRATE2" },
761 { .addr = CC1120_DRATE1, .name = "DRATE1" },
762 { .addr = CC1120_DRATE0, .name = "DRATE0" },
763 { .addr = CC1120_AGC_REF, .name = "AGC_REF" },
764 { .addr = CC1120_AGC_CS_THR, .name = "AGC_CS_THR" },
765 { .addr = CC1120_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
766 { .addr = CC1120_AGC_CFG3, .name = "AGC_CFG3" },
767 { .addr = CC1120_AGC_CFG2, .name = "AGC_CFG2" },
768 { .addr = CC1120_AGC_CFG1, .name = "AGC_CFG1" },
769 { .addr = CC1120_AGC_CFG0, .name = "AGC_CFG0" },
770 { .addr = CC1120_FIFO_CFG, .name = "FIFO_CFG" },
771 { .addr = CC1120_DEV_ADDR, .name = "DEV_ADDR" },
772 { .addr = CC1120_SETTLING_CFG, .name = "SETTLING_CFG" },
773 { .addr = CC1120_FS_CFG, .name = "FS_CFG" },
774 { .addr = CC1120_WOR_CFG1, .name = "WOR_CFG1" },
775 { .addr = CC1120_WOR_CFG0, .name = "WOR_CFG0" },
776 { .addr = CC1120_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
777 { .addr = CC1120_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
778 { .addr = CC1120_PKT_CFG2, .name = "PKT_CFG2" },
779 { .addr = CC1120_PKT_CFG1, .name = "PKT_CFG1" },
780 { .addr = CC1120_PKT_CFG0, .name = "PKT_CFG0" },
781 { .addr = CC1120_RFEND_CFG1, .name = "RFEND_CFG1" },
782 { .addr = CC1120_RFEND_CFG0, .name = "RFEND_CFG0" },
783 { .addr = CC1120_PA_CFG2, .name = "PA_CFG2" },
784 { .addr = CC1120_PA_CFG1, .name = "PA_CFG1" },
785 { .addr = CC1120_PA_CFG0, .name = "PA_CFG0" },
786 { .addr = CC1120_PKT_LEN, .name = "PKT_LEN" },
787 { .addr = CC1120_IF_MIX_CFG, .name = "IF_MIX_CFG" },
788 { .addr = CC1120_FREQOFF_CFG, .name = "FREQOFF_CFG" },
789 { .addr = CC1120_TOC_CFG, .name = "TOC_CFG" },
790 { .addr = CC1120_MARC_SPARE, .name = "MARC_SPARE" },
791 { .addr = CC1120_ECG_CFG, .name = "ECG_CFG" },
792 { .addr = CC1120_SOFT_TX_DATA_CFG, .name = "SOFT_TX_DATA_CFG" },
793 { .addr = CC1120_EXT_CTRL, .name = "EXT_CTRL" },
794 { .addr = CC1120_RCCAL_FINE, .name = "RCCAL_FINE" },
795 { .addr = CC1120_RCCAL_COARSE, .name = "RCCAL_COARSE" },
796 { .addr = CC1120_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
797 { .addr = CC1120_FREQOFF1, .name = "FREQOFF1" },
798 { .addr = CC1120_FREQOFF0, .name = "FREQOFF0" },
799 { .addr = CC1120_FREQ2, .name = "FREQ2" },
800 { .addr = CC1120_FREQ1, .name = "FREQ1" },
801 { .addr = CC1120_FREQ0, .name = "FREQ0" },
802 { .addr = CC1120_IF_ADC2, .name = "IF_ADC2" },
803 { .addr = CC1120_IF_ADC1, .name = "IF_ADC1" },
804 { .addr = CC1120_IF_ADC0, .name = "IF_ADC0" },
805 { .addr = CC1120_FS_DIG1, .name = "FS_DIG1" },
806 { .addr = CC1120_FS_DIG0, .name = "FS_DIG0" },
807 { .addr = CC1120_FS_CAL3, .name = "FS_CAL3" },
808 { .addr = CC1120_FS_CAL2, .name = "FS_CAL2" },
809 { .addr = CC1120_FS_CAL1, .name = "FS_CAL1" },
810 { .addr = CC1120_FS_CAL0, .name = "FS_CAL0" },
811 { .addr = CC1120_FS_CHP, .name = "FS_CHP" },
812 { .addr = CC1120_FS_DIVTWO, .name = "FS_DIVTWO" },
813 { .addr = CC1120_FS_DSM1, .name = "FS_DSM1" },
814 { .addr = CC1120_FS_DSM0, .name = "FS_DSM0" },
815 { .addr = CC1120_FS_DVC1, .name = "FS_DVC1" },
816 { .addr = CC1120_FS_DVC0, .name = "FS_DVC0" },
817 { .addr = CC1120_FS_LBI, .name = "FS_LBI" },
818 { .addr = CC1120_FS_PFD, .name = "FS_PFD" },
819 { .addr = CC1120_FS_PRE, .name = "FS_PRE" },
820 { .addr = CC1120_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
821 { .addr = CC1120_FS_SPARE, .name = "FS_SPARE" },
822 { .addr = CC1120_FS_VCO4, .name = "FS_VCO4" },
823 { .addr = CC1120_FS_VCO3, .name = "FS_VCO3" },
824 { .addr = CC1120_FS_VCO2, .name = "FS_VCO2" },
825 { .addr = CC1120_FS_VCO1, .name = "FS_VCO1" },
826 { .addr = CC1120_FS_VCO0, .name = "FS_VCO0" },
827 { .addr = CC1120_GBIAS6, .name = "GBIAS6" },
828 { .addr = CC1120_GBIAS5, .name = "GBIAS5" },
829 { .addr = CC1120_GBIAS4, .name = "GBIAS4" },
830 { .addr = CC1120_GBIAS3, .name = "GBIAS3" },
831 { .addr = CC1120_GBIAS2, .name = "GBIAS2" },
832 { .addr = CC1120_GBIAS1, .name = "GBIAS1" },
833 { .addr = CC1120_GBIAS0, .name = "GBIAS0" },
834 { .addr = CC1120_IFAMP, .name = "IFAMP" },
835 { .addr = CC1120_LNA, .name = "LNA" },
836 { .addr = CC1120_RXMIX, .name = "RXMIX" },
837 { .addr = CC1120_XOSC5, .name = "XOSC5" },
838 { .addr = CC1120_XOSC4, .name = "XOSC4" },
839 { .addr = CC1120_XOSC3, .name = "XOSC3" },
840 { .addr = CC1120_XOSC2, .name = "XOSC2" },
841 { .addr = CC1120_XOSC1, .name = "XOSC1" },
842 { .addr = CC1120_XOSC0, .name = "XOSC0" },
843 { .addr = CC1120_ANALOG_SPARE, .name = "ANALOG_SPARE" },
844 { .addr = CC1120_PA_CFG3, .name = "PA_CFG3" },
845 { .addr = CC1120_WOR_TIME1, .name = "WOR_TIME1" },
846 { .addr = CC1120_WOR_TIME0, .name = "WOR_TIME0" },
847 { .addr = CC1120_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
848 { .addr = CC1120_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
849 { .addr = CC1120_BIST, .name = "BIST" },
850 { .addr = CC1120_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
851 { .addr = CC1120_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
852 { .addr = CC1120_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
853 { .addr = CC1120_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
854 { .addr = CC1120_IQIE_I1, .name = "IQIE_I1" },
855 { .addr = CC1120_IQIE_I0, .name = "IQIE_I0" },
856 { .addr = CC1120_IQIE_Q1, .name = "IQIE_Q1" },
857 { .addr = CC1120_IQIE_Q0, .name = "IQIE_Q0" },
858 { .addr = CC1120_RSSI1, .name = "RSSI1" },
859 { .addr = CC1120_RSSI0, .name = "RSSI0" },
860 { .addr = CC1120_MARCSTATE, .name = "MARCSTATE" },
861 { .addr = CC1120_LQI_VAL, .name = "LQI_VAL" },
862 { .addr = CC1120_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
863 { .addr = CC1120_DEM_STATUS, .name = "DEM_STATUS" },
864 { .addr = CC1120_FREQOFF_EST1, .name = "FREQOFF_EST1" },
865 { .addr = CC1120_FREQOFF_EST0, .name = "FREQOFF_EST0" },
866 { .addr = CC1120_AGC_GAIN3, .name = "AGC_GAIN3" },
867 { .addr = CC1120_AGC_GAIN2, .name = "AGC_GAIN2" },
868 { .addr = CC1120_AGC_GAIN1, .name = "AGC_GAIN1" },
869 { .addr = CC1120_AGC_GAIN0, .name = "AGC_GAIN0" },
870 { .addr = CC1120_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
871 { .addr = CC1120_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
872 { .addr = CC1120_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
873 { .addr = CC1120_RNDGEN, .name = "RNDGEN" },
874 { .addr = CC1120_MAGN2, .name = "MAGN2" },
875 { .addr = CC1120_MAGN1, .name = "MAGN1" },
876 { .addr = CC1120_MAGN0, .name = "MAGN0" },
877 { .addr = CC1120_ANG1, .name = "ANG1" },
878 { .addr = CC1120_ANG0, .name = "ANG0" },
879 { .addr = CC1120_CHFILT_I2, .name = "CHFILT_I2" },
880 { .addr = CC1120_CHFILT_I1, .name = "CHFILT_I1" },
881 { .addr = CC1120_CHFILT_I0, .name = "CHFILT_I0" },
882 { .addr = CC1120_CHFILT_Q2, .name = "CHFILT_Q2" },
883 { .addr = CC1120_CHFILT_Q1, .name = "CHFILT_Q1" },
884 { .addr = CC1120_CHFILT_Q0, .name = "CHFILT_Q0" },
885 { .addr = CC1120_GPIO_STATUS, .name = "GPIO_STATUS" },
886 { .addr = CC1120_FSCAL_CTRL, .name = "FSCAL_CTRL" },
887 { .addr = CC1120_PHASE_ADJUST, .name = "PHASE_ADJUST" },
888 { .addr = CC1120_PARTNUMBER, .name = "PARTNUMBER" },
889 { .addr = CC1120_PARTVERSION, .name = "PARTVERSION" },
890 { .addr = CC1120_SERIAL_STATUS, .name = "SERIAL_STATUS" },
891 { .addr = CC1120_RX_STATUS, .name = "RX_STATUS" },
892 { .addr = CC1120_TX_STATUS, .name = "TX_STATUS" },
893 { .addr = CC1120_MARC_STATUS1, .name = "MARC_STATUS1" },
894 { .addr = CC1120_MARC_STATUS0, .name = "MARC_STATUS0" },
895 { .addr = CC1120_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
896 { .addr = CC1120_FSRF_TEST, .name = "FSRF_TEST" },
897 { .addr = CC1120_PRE_TEST, .name = "PRE_TEST" },
898 { .addr = CC1120_PRE_OVR, .name = "PRE_OVR" },
899 { .addr = CC1120_ADC_TEST, .name = "ADC_TEST" },
900 { .addr = CC1120_DVC_TEST, .name = "DVC_TEST" },
901 { .addr = CC1120_ATEST, .name = "ATEST" },
902 { .addr = CC1120_ATEST_LVDS, .name = "ATEST_LVDS" },
903 { .addr = CC1120_ATEST_MODE, .name = "ATEST_MODE" },
904 { .addr = CC1120_XOSC_TEST1, .name = "XOSC_TEST1" },
905 { .addr = CC1120_XOSC_TEST0, .name = "XOSC_TEST0" },
906 { .addr = CC1120_RXFIRST, .name = "RXFIRST" },
907 { .addr = CC1120_TXFIRST, .name = "TXFIRST" },
908 { .addr = CC1120_RXLAST, .name = "RXLAST" },
909 { .addr = CC1120_TXLAST, .name = "TXLAST" },
910 { .addr = CC1120_NUM_TXBYTES, .name = "NUM_TXBYTES" },
911 { .addr = CC1120_NUM_RXBYTES, .name = "NUM_RXBYTES" },
912 { .addr = CC1120_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
913 { .addr = CC1120_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
916 #define AO_NUM_CC1120_REG (sizeof ao_cc1120_reg / sizeof ao_cc1120_reg[0])
918 static void ao_radio_show(void) {
919 uint8_t status = ao_radio_status();
923 status = ao_radio_status();
924 printf ("Status: %02x\n", status);
925 printf ("CHIP_RDY: %d\n", (status >> CC1120_STATUS_CHIP_RDY) & 1);
926 printf ("STATE: %s\n", cc1120_state_name[(status >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK]);
927 printf ("MARC: %02x\n", ao_radio_marc_status());
929 for (i = 0; i < AO_NUM_CC1120_REG; i++)
930 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name);
934 static void ao_radio_beep(void) {
935 ao_radio_rdf(RDF_PACKET_LEN);
938 static void ao_radio_packet(void) {
939 static const uint8_t packet[] = {
941 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
942 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
943 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
944 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
950 ao_radio_send(packet, sizeof (packet));
959 if (ao_radio_recv(bytes, 34)) {
960 if (bytes[33] & 0x80)
964 printf (" RSSI %d", (int16_t) ((int8_t) bytes[32] >> 1) - 74);
965 for (b = 0; b < 32; b++)
966 printf (" %02x", bytes[b]);
973 static const struct ao_cmds ao_radio_cmds[] = {
974 { ao_radio_test, "C <1 start, 0 stop, none both>\0Radio carrier test" },
976 { ao_radio_show, "R\0Show CC1120 status" },
977 { ao_radio_beep, "b\0Emit an RDF beacon" },
978 { ao_radio_packet, "p\0Send a test packet" },
979 { ao_radio_test_recv, "q\0Recv a test packet" },
989 ao_radio_configured = 0;
990 ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN));
992 AO_CC1120_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN));
993 for (i = 0; i < 10000; i++) {
994 if ((SPI_2_GPIO->idr & (1 << SPI_2_MISO)) == 0)
997 AO_CC1120_SPI_CS_PORT->bsrr = (1 << AO_CC1120_SPI_CS_PIN);
999 ao_panic(AO_PANIC_SELF_TEST);
1001 /* Enable the EXTI interrupt for the appropriate pin */
1002 ao_enable_port(AO_CC1120_INT_PORT);
1003 ao_exti_setup(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1004 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
1007 ao_cmd_register(&ao_radio_cmds[0]);