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)
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) {
608 if (rx_data_consumed == 0)
609 rx_packet_tick = ao_profile_tick();
612 ao_wakeup(&ao_radio_wake);
620 ao_radio_rx_wait(void)
624 while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&
626 ao_sleep(&ao_radio_wake);
632 rx_data_consumed += AO_FEC_DECODE_BLOCK;
633 return AO_FEC_DECODE_BLOCK;
637 ao_radio_recv(__xdata void *d, uint8_t size)
643 static int been_here = 0;
645 size -= 2; /* status bytes */
646 if (size > AO_RADIO_MAX_RECV) {
647 ao_delay(AO_SEC_TO_TICKS(1));
651 rx_start_tick = ao_profile_tick();
653 len = size + 2; /* CRC bytes */
654 len += 1 + ~(len & 1); /* 1 or two pad bytes */
655 len *= 2; /* 1/2 rate convolution */
656 rx_data_count = len * 8; /* bytes to bits */
658 rx_data_consumed = 0;
662 ao_radio_in_recv = 1;
663 /* configure interrupt pin */
665 ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
674 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
675 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
677 ao_radio_strobe(CC1120_SRX);
679 ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
681 ret = ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait);
683 ao_radio_burst_read_stop();
685 ao_radio_strobe(CC1120_SIDLE);
687 /* Convert from 'real' rssi to cc1111-style values */
689 rssi = (((int8_t) ao_radio_reg_read(CC1120_RSSI1)) + 74) * 2;
693 /* Construct final packet */
695 if (ret && ((uint8_t *) d)[size] == 0 && ((uint8_t *)d)[size+1] == 0)
696 ((uint8_t *) d)[size + 1] = 0x80;
698 ((uint8_t *) d)[size + 1] = 0x00;
700 ((uint8_t *) d)[size] = (uint8_t) rssi;
702 ao_radio_in_recv = 0;
708 rx_last_done_tick = rx_done_tick;
709 rx_done_tick = ao_profile_tick();
711 ao_rx_start_tick = rx_start_tick;
712 ao_rx_packet_tick = rx_packet_tick;
713 ao_rx_done_tick = rx_done_tick;
714 ao_rx_last_done_tick = rx_last_done_tick;
722 static char *cc1120_state_name[] = {
723 [CC1120_STATUS_STATE_IDLE] = "IDLE",
724 [CC1120_STATUS_STATE_RX] = "RX",
725 [CC1120_STATUS_STATE_TX] = "TX",
726 [CC1120_STATUS_STATE_FSTXON] = "FSTXON",
727 [CC1120_STATUS_STATE_CALIBRATE] = "CALIBRATE",
728 [CC1120_STATUS_STATE_SETTLING] = "SETTLING",
729 [CC1120_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
730 [CC1120_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
733 struct ao_cc1120_reg {
738 const static struct ao_cc1120_reg ao_cc1120_reg[] = {
739 { .addr = CC1120_IOCFG3, .name = "IOCFG3" },
740 { .addr = CC1120_IOCFG2, .name = "IOCFG2" },
741 { .addr = CC1120_IOCFG1, .name = "IOCFG1" },
742 { .addr = CC1120_IOCFG0, .name = "IOCFG0" },
743 { .addr = CC1120_SYNC3, .name = "SYNC3" },
744 { .addr = CC1120_SYNC2, .name = "SYNC2" },
745 { .addr = CC1120_SYNC1, .name = "SYNC1" },
746 { .addr = CC1120_SYNC0, .name = "SYNC0" },
747 { .addr = CC1120_SYNC_CFG1, .name = "SYNC_CFG1" },
748 { .addr = CC1120_SYNC_CFG0, .name = "SYNC_CFG0" },
749 { .addr = CC1120_DEVIATION_M, .name = "DEVIATION_M" },
750 { .addr = CC1120_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
751 { .addr = CC1120_DCFILT_CFG, .name = "DCFILT_CFG" },
752 { .addr = CC1120_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
753 { .addr = CC1120_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
754 { .addr = CC1120_FREQ_IF_CFG, .name = "FREQ_IF_CFG" },
755 { .addr = CC1120_IQIC, .name = "IQIC" },
756 { .addr = CC1120_CHAN_BW, .name = "CHAN_BW" },
757 { .addr = CC1120_MDMCFG1, .name = "MDMCFG1" },
758 { .addr = CC1120_MDMCFG0, .name = "MDMCFG0" },
759 { .addr = CC1120_DRATE2, .name = "DRATE2" },
760 { .addr = CC1120_DRATE1, .name = "DRATE1" },
761 { .addr = CC1120_DRATE0, .name = "DRATE0" },
762 { .addr = CC1120_AGC_REF, .name = "AGC_REF" },
763 { .addr = CC1120_AGC_CS_THR, .name = "AGC_CS_THR" },
764 { .addr = CC1120_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
765 { .addr = CC1120_AGC_CFG3, .name = "AGC_CFG3" },
766 { .addr = CC1120_AGC_CFG2, .name = "AGC_CFG2" },
767 { .addr = CC1120_AGC_CFG1, .name = "AGC_CFG1" },
768 { .addr = CC1120_AGC_CFG0, .name = "AGC_CFG0" },
769 { .addr = CC1120_FIFO_CFG, .name = "FIFO_CFG" },
770 { .addr = CC1120_DEV_ADDR, .name = "DEV_ADDR" },
771 { .addr = CC1120_SETTLING_CFG, .name = "SETTLING_CFG" },
772 { .addr = CC1120_FS_CFG, .name = "FS_CFG" },
773 { .addr = CC1120_WOR_CFG1, .name = "WOR_CFG1" },
774 { .addr = CC1120_WOR_CFG0, .name = "WOR_CFG0" },
775 { .addr = CC1120_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
776 { .addr = CC1120_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
777 { .addr = CC1120_PKT_CFG2, .name = "PKT_CFG2" },
778 { .addr = CC1120_PKT_CFG1, .name = "PKT_CFG1" },
779 { .addr = CC1120_PKT_CFG0, .name = "PKT_CFG0" },
780 { .addr = CC1120_RFEND_CFG1, .name = "RFEND_CFG1" },
781 { .addr = CC1120_RFEND_CFG0, .name = "RFEND_CFG0" },
782 { .addr = CC1120_PA_CFG2, .name = "PA_CFG2" },
783 { .addr = CC1120_PA_CFG1, .name = "PA_CFG1" },
784 { .addr = CC1120_PA_CFG0, .name = "PA_CFG0" },
785 { .addr = CC1120_PKT_LEN, .name = "PKT_LEN" },
786 { .addr = CC1120_IF_MIX_CFG, .name = "IF_MIX_CFG" },
787 { .addr = CC1120_FREQOFF_CFG, .name = "FREQOFF_CFG" },
788 { .addr = CC1120_TOC_CFG, .name = "TOC_CFG" },
789 { .addr = CC1120_MARC_SPARE, .name = "MARC_SPARE" },
790 { .addr = CC1120_ECG_CFG, .name = "ECG_CFG" },
791 { .addr = CC1120_SOFT_TX_DATA_CFG, .name = "SOFT_TX_DATA_CFG" },
792 { .addr = CC1120_EXT_CTRL, .name = "EXT_CTRL" },
793 { .addr = CC1120_RCCAL_FINE, .name = "RCCAL_FINE" },
794 { .addr = CC1120_RCCAL_COARSE, .name = "RCCAL_COARSE" },
795 { .addr = CC1120_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
796 { .addr = CC1120_FREQOFF1, .name = "FREQOFF1" },
797 { .addr = CC1120_FREQOFF0, .name = "FREQOFF0" },
798 { .addr = CC1120_FREQ2, .name = "FREQ2" },
799 { .addr = CC1120_FREQ1, .name = "FREQ1" },
800 { .addr = CC1120_FREQ0, .name = "FREQ0" },
801 { .addr = CC1120_IF_ADC2, .name = "IF_ADC2" },
802 { .addr = CC1120_IF_ADC1, .name = "IF_ADC1" },
803 { .addr = CC1120_IF_ADC0, .name = "IF_ADC0" },
804 { .addr = CC1120_FS_DIG1, .name = "FS_DIG1" },
805 { .addr = CC1120_FS_DIG0, .name = "FS_DIG0" },
806 { .addr = CC1120_FS_CAL3, .name = "FS_CAL3" },
807 { .addr = CC1120_FS_CAL2, .name = "FS_CAL2" },
808 { .addr = CC1120_FS_CAL1, .name = "FS_CAL1" },
809 { .addr = CC1120_FS_CAL0, .name = "FS_CAL0" },
810 { .addr = CC1120_FS_CHP, .name = "FS_CHP" },
811 { .addr = CC1120_FS_DIVTWO, .name = "FS_DIVTWO" },
812 { .addr = CC1120_FS_DSM1, .name = "FS_DSM1" },
813 { .addr = CC1120_FS_DSM0, .name = "FS_DSM0" },
814 { .addr = CC1120_FS_DVC1, .name = "FS_DVC1" },
815 { .addr = CC1120_FS_DVC0, .name = "FS_DVC0" },
816 { .addr = CC1120_FS_LBI, .name = "FS_LBI" },
817 { .addr = CC1120_FS_PFD, .name = "FS_PFD" },
818 { .addr = CC1120_FS_PRE, .name = "FS_PRE" },
819 { .addr = CC1120_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
820 { .addr = CC1120_FS_SPARE, .name = "FS_SPARE" },
821 { .addr = CC1120_FS_VCO4, .name = "FS_VCO4" },
822 { .addr = CC1120_FS_VCO3, .name = "FS_VCO3" },
823 { .addr = CC1120_FS_VCO2, .name = "FS_VCO2" },
824 { .addr = CC1120_FS_VCO1, .name = "FS_VCO1" },
825 { .addr = CC1120_FS_VCO0, .name = "FS_VCO0" },
826 { .addr = CC1120_GBIAS6, .name = "GBIAS6" },
827 { .addr = CC1120_GBIAS5, .name = "GBIAS5" },
828 { .addr = CC1120_GBIAS4, .name = "GBIAS4" },
829 { .addr = CC1120_GBIAS3, .name = "GBIAS3" },
830 { .addr = CC1120_GBIAS2, .name = "GBIAS2" },
831 { .addr = CC1120_GBIAS1, .name = "GBIAS1" },
832 { .addr = CC1120_GBIAS0, .name = "GBIAS0" },
833 { .addr = CC1120_IFAMP, .name = "IFAMP" },
834 { .addr = CC1120_LNA, .name = "LNA" },
835 { .addr = CC1120_RXMIX, .name = "RXMIX" },
836 { .addr = CC1120_XOSC5, .name = "XOSC5" },
837 { .addr = CC1120_XOSC4, .name = "XOSC4" },
838 { .addr = CC1120_XOSC3, .name = "XOSC3" },
839 { .addr = CC1120_XOSC2, .name = "XOSC2" },
840 { .addr = CC1120_XOSC1, .name = "XOSC1" },
841 { .addr = CC1120_XOSC0, .name = "XOSC0" },
842 { .addr = CC1120_ANALOG_SPARE, .name = "ANALOG_SPARE" },
843 { .addr = CC1120_PA_CFG3, .name = "PA_CFG3" },
844 { .addr = CC1120_WOR_TIME1, .name = "WOR_TIME1" },
845 { .addr = CC1120_WOR_TIME0, .name = "WOR_TIME0" },
846 { .addr = CC1120_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
847 { .addr = CC1120_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
848 { .addr = CC1120_BIST, .name = "BIST" },
849 { .addr = CC1120_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
850 { .addr = CC1120_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
851 { .addr = CC1120_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
852 { .addr = CC1120_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
853 { .addr = CC1120_IQIE_I1, .name = "IQIE_I1" },
854 { .addr = CC1120_IQIE_I0, .name = "IQIE_I0" },
855 { .addr = CC1120_IQIE_Q1, .name = "IQIE_Q1" },
856 { .addr = CC1120_IQIE_Q0, .name = "IQIE_Q0" },
857 { .addr = CC1120_RSSI1, .name = "RSSI1" },
858 { .addr = CC1120_RSSI0, .name = "RSSI0" },
859 { .addr = CC1120_MARCSTATE, .name = "MARCSTATE" },
860 { .addr = CC1120_LQI_VAL, .name = "LQI_VAL" },
861 { .addr = CC1120_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
862 { .addr = CC1120_DEM_STATUS, .name = "DEM_STATUS" },
863 { .addr = CC1120_FREQOFF_EST1, .name = "FREQOFF_EST1" },
864 { .addr = CC1120_FREQOFF_EST0, .name = "FREQOFF_EST0" },
865 { .addr = CC1120_AGC_GAIN3, .name = "AGC_GAIN3" },
866 { .addr = CC1120_AGC_GAIN2, .name = "AGC_GAIN2" },
867 { .addr = CC1120_AGC_GAIN1, .name = "AGC_GAIN1" },
868 { .addr = CC1120_AGC_GAIN0, .name = "AGC_GAIN0" },
869 { .addr = CC1120_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
870 { .addr = CC1120_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
871 { .addr = CC1120_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
872 { .addr = CC1120_RNDGEN, .name = "RNDGEN" },
873 { .addr = CC1120_MAGN2, .name = "MAGN2" },
874 { .addr = CC1120_MAGN1, .name = "MAGN1" },
875 { .addr = CC1120_MAGN0, .name = "MAGN0" },
876 { .addr = CC1120_ANG1, .name = "ANG1" },
877 { .addr = CC1120_ANG0, .name = "ANG0" },
878 { .addr = CC1120_CHFILT_I2, .name = "CHFILT_I2" },
879 { .addr = CC1120_CHFILT_I1, .name = "CHFILT_I1" },
880 { .addr = CC1120_CHFILT_I0, .name = "CHFILT_I0" },
881 { .addr = CC1120_CHFILT_Q2, .name = "CHFILT_Q2" },
882 { .addr = CC1120_CHFILT_Q1, .name = "CHFILT_Q1" },
883 { .addr = CC1120_CHFILT_Q0, .name = "CHFILT_Q0" },
884 { .addr = CC1120_GPIO_STATUS, .name = "GPIO_STATUS" },
885 { .addr = CC1120_FSCAL_CTRL, .name = "FSCAL_CTRL" },
886 { .addr = CC1120_PHASE_ADJUST, .name = "PHASE_ADJUST" },
887 { .addr = CC1120_PARTNUMBER, .name = "PARTNUMBER" },
888 { .addr = CC1120_PARTVERSION, .name = "PARTVERSION" },
889 { .addr = CC1120_SERIAL_STATUS, .name = "SERIAL_STATUS" },
890 { .addr = CC1120_RX_STATUS, .name = "RX_STATUS" },
891 { .addr = CC1120_TX_STATUS, .name = "TX_STATUS" },
892 { .addr = CC1120_MARC_STATUS1, .name = "MARC_STATUS1" },
893 { .addr = CC1120_MARC_STATUS0, .name = "MARC_STATUS0" },
894 { .addr = CC1120_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
895 { .addr = CC1120_FSRF_TEST, .name = "FSRF_TEST" },
896 { .addr = CC1120_PRE_TEST, .name = "PRE_TEST" },
897 { .addr = CC1120_PRE_OVR, .name = "PRE_OVR" },
898 { .addr = CC1120_ADC_TEST, .name = "ADC_TEST" },
899 { .addr = CC1120_DVC_TEST, .name = "DVC_TEST" },
900 { .addr = CC1120_ATEST, .name = "ATEST" },
901 { .addr = CC1120_ATEST_LVDS, .name = "ATEST_LVDS" },
902 { .addr = CC1120_ATEST_MODE, .name = "ATEST_MODE" },
903 { .addr = CC1120_XOSC_TEST1, .name = "XOSC_TEST1" },
904 { .addr = CC1120_XOSC_TEST0, .name = "XOSC_TEST0" },
905 { .addr = CC1120_RXFIRST, .name = "RXFIRST" },
906 { .addr = CC1120_TXFIRST, .name = "TXFIRST" },
907 { .addr = CC1120_RXLAST, .name = "RXLAST" },
908 { .addr = CC1120_TXLAST, .name = "TXLAST" },
909 { .addr = CC1120_NUM_TXBYTES, .name = "NUM_TXBYTES" },
910 { .addr = CC1120_NUM_RXBYTES, .name = "NUM_RXBYTES" },
911 { .addr = CC1120_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
912 { .addr = CC1120_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
915 #define AO_NUM_CC1120_REG (sizeof ao_cc1120_reg / sizeof ao_cc1120_reg[0])
917 static void ao_radio_show(void) {
918 uint8_t status = ao_radio_status();
922 status = ao_radio_status();
923 printf ("Status: %02x\n", status);
924 printf ("CHIP_RDY: %d\n", (status >> CC1120_STATUS_CHIP_RDY) & 1);
925 printf ("STATE: %s\n", cc1120_state_name[(status >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK]);
926 printf ("MARC: %02x\n", ao_radio_marc_status());
928 for (i = 0; i < AO_NUM_CC1120_REG; i++)
929 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name);
933 static void ao_radio_beep(void) {
934 ao_radio_rdf(RDF_PACKET_LEN);
937 static void ao_radio_packet(void) {
938 static const uint8_t packet[] = {
940 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
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,
949 ao_radio_send(packet, sizeof (packet));
958 if (ao_radio_recv(bytes, 34)) {
959 if (bytes[33] & 0x80)
963 printf (" RSSI %d", (int16_t) ((int8_t) bytes[32] >> 1) - 74);
964 for (b = 0; b < 32; b++)
965 printf (" %02x", bytes[b]);
972 static const struct ao_cmds ao_radio_cmds[] = {
973 { ao_radio_test, "C <1 start, 0 stop, none both>\0Radio carrier test" },
975 { ao_radio_show, "R\0Show CC1120 status" },
976 { ao_radio_beep, "b\0Emit an RDF beacon" },
977 { ao_radio_packet, "p\0Send a test packet" },
978 { ao_radio_test_recv, "q\0Recv a test packet" },
988 ao_radio_configured = 0;
989 ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN));
991 AO_CC1120_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN));
992 for (i = 0; i < 10000; i++) {
993 if ((SPI_2_GPIO->idr & (1 << SPI_2_MISO)) == 0)
996 AO_CC1120_SPI_CS_PORT->bsrr = (1 << AO_CC1120_SPI_CS_PIN);
998 ao_panic(AO_PANIC_SELF_TEST);
1000 /* Enable the EXTI interrupt for the appropriate pin */
1001 ao_enable_port(AO_CC1120_INT_PORT);
1002 ao_exti_setup(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1003 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
1006 ao_cmd_register(&ao_radio_cmds[0]);