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 #define AO_RADIO_MAX_RECV sizeof(struct ao_packet)
25 #define AO_RADIO_MAX_SEND sizeof(struct ao_packet)
27 uint8_t ao_radio_wake;
28 uint8_t ao_radio_mutex;
29 uint8_t ao_radio_abort;
30 uint8_t ao_radio_in_recv;
32 #define CC1120_DEBUG AO_FEC_DEBUG
33 #define CC1120_TRACE 0
35 extern const uint32_t ao_radio_cal;
39 #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)
40 #define ao_radio_deselect() ao_spi_put_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS)
41 #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1120_SPI_BUS)
42 #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1120_SPI_BUS)
43 #define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1120_SPI_BUS)
44 #define ao_radio_duplex(o,i,l) ao_spi_duplex((o), (i), (l), AO_CC1120_SPI_BUS)
47 ao_radio_reg_read(uint16_t addr)
53 printf("\t\tao_radio_reg_read (%04x): ", addr); flush();
55 if (CC1120_IS_EXTENDED(addr)) {
56 data[0] = ((1 << CC1120_READ) |
62 data[0] = ((1 << CC1120_READ) |
68 ao_radio_spi_send(data, d);
69 ao_radio_spi_recv(data, 1);
72 printf (" %02x\n", data[0]);
78 ao_radio_reg_write(uint16_t addr, uint8_t value)
84 printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value);
86 if (CC1120_IS_EXTENDED(addr)) {
87 data[0] = ((0 << CC1120_READ) |
93 data[0] = ((0 << CC1120_READ) |
100 ao_radio_spi_send(data, d+1);
105 ao_radio_burst_read_start (uint16_t addr)
110 if (CC1120_IS_EXTENDED(addr)) {
111 data[0] = ((1 << CC1120_READ) |
112 (1 << CC1120_BURST) |
117 data[0] = ((1 << CC1120_READ) |
118 (1 << CC1120_BURST) |
123 ao_radio_spi_send(data, d);
127 ao_radio_burst_read_stop (void)
134 ao_radio_strobe(uint8_t addr)
139 printf("\t\tao_radio_strobe (%02x): ", addr); flush();
142 ao_radio_duplex(&addr, &in, 1);
145 printf("%02x\n", in); flush();
151 ao_radio_fifo_read(uint8_t *data, uint8_t len)
153 uint8_t addr = ((1 << CC1120_READ) |
154 (1 << CC1120_BURST) |
159 ao_radio_duplex(&addr, &status, 1);
160 ao_radio_spi_recv(data, len);
166 ao_radio_fifo_write_start(void)
168 uint8_t addr = ((0 << CC1120_READ) |
169 (1 << CC1120_BURST) |
174 ao_radio_duplex(&addr, &status, 1);
178 static inline uint8_t ao_radio_fifo_write_stop(uint8_t status) {
184 ao_radio_fifo_write(uint8_t *data, uint8_t len)
186 uint8_t status = ao_radio_fifo_write_start();
187 ao_radio_spi_send(data, len);
188 return ao_radio_fifo_write_stop(status);
192 ao_radio_fifo_write_fixed(uint8_t data, uint8_t len)
194 uint8_t status = ao_radio_fifo_write_start();
195 ao_radio_spi_send_fixed(data, len);
196 return ao_radio_fifo_write_stop(status);
200 ao_radio_tx_fifo_space(void)
202 return CC1120_FIFO_SIZE - ao_radio_reg_read(CC1120_NUM_TXBYTES);
206 ao_radio_status(void)
208 return ao_radio_strobe (CC1120_SNOP);
212 ao_radio_recv_abort(void)
215 ao_wakeup(&ao_radio_wake);
218 #define ao_radio_rdf_value 0x55
221 ao_radio_marc_status(void)
223 return ao_radio_reg_read(CC1120_MARC_STATUS1);
227 ao_radio_tx_isr(void)
229 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
231 ao_wakeup(&ao_radio_wake);
235 ao_radio_start_tx(void)
237 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_tx_isr);
238 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
239 ao_radio_strobe(CC1120_STX);
246 uint8_t state = ao_radio_strobe(CC1120_SIDLE);
247 if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_IDLE)
253 * Packet deviation is 20.5kHz
255 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
257 * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz
260 #define PACKET_DEV_E 5
261 #define PACKET_DEV_M 80
264 * For our packet data, set the symbol rate to 38360 Baud
266 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
267 * Rdata = -------------------------------------- * fosc
271 * DATARATE_M = 239914
274 #define PACKET_DRATE_E 9
275 #define PACKET_DRATE_M 239914
277 static const uint16_t packet_setup[] = {
278 CC1120_DEVIATION_M, PACKET_DEV_M,
279 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
280 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
281 (PACKET_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
282 CC1120_DRATE2, ((PACKET_DRATE_E << CC1120_DRATE2_DATARATE_E) |
283 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
284 CC1120_DRATE1, ((PACKET_DRATE_M >> 8) & 0xff),
285 CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff),
286 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
287 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
288 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
289 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
290 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
291 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
292 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
293 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
294 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
295 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
296 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
299 static const uint16_t packet_tx_setup[] = {
300 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
301 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
302 CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG,
305 static const uint16_t packet_rx_setup[] = {
306 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
307 (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT)),
308 CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT,
312 * RDF deviation is 5kHz
314 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
316 * 32e6Hz / (2 ** 24) * (256 + 71) * (2 ** 3) = 4989
321 #define RDF_PACKET_LEN 50
324 * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
326 * (2**20 - DATARATE_M) * 2 ** DATARATE_E
327 * Rdata = -------------------------------------- * fosc
330 * DATARATE_M = 511705
333 * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
335 #define RDF_DRATE_E 5
336 #define RDF_DRATE_M 25166
337 #define RDF_PACKET_LEN 50
339 static const uint16_t rdf_setup[] = {
340 CC1120_DEVIATION_M, RDF_DEV_M,
341 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
342 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
343 (RDF_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
344 CC1120_DRATE2, ((RDF_DRATE_E << CC1120_DRATE2_DATARATE_E) |
345 (((RDF_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
346 CC1120_DRATE1, ((RDF_DRATE_M >> 8) & 0xff),
347 CC1120_DRATE0, ((RDF_DRATE_M >> 0) & 0xff),
348 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
349 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
350 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
351 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
352 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
353 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
354 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
355 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
356 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
357 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
358 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
361 static uint8_t ao_radio_mode;
363 #define AO_RADIO_MODE_BITS_PACKET 1
364 #define AO_RADIO_MODE_BITS_PACKET_TX 2
365 #define AO_RADIO_MODE_BITS_TX_BUF 4
366 #define AO_RADIO_MODE_BITS_TX_FINISH 8
367 #define AO_RADIO_MODE_BITS_PACKET_RX 16
368 #define AO_RADIO_MODE_BITS_RDF 32
370 #define AO_RADIO_MODE_NONE 0
371 #define AO_RADIO_MODE_PACKET_TX_BUF (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_BUF)
372 #define AO_RADIO_MODE_PACKET_TX_FINISH (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_FINISH)
373 #define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_RX)
374 #define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_TX_FINISH)
377 ao_radio_set_mode(uint8_t new_mode)
382 if (new_mode == ao_radio_mode)
385 changes = new_mode & (~ao_radio_mode);
386 if (changes & AO_RADIO_MODE_BITS_PACKET)
387 for (i = 0; i < sizeof (packet_setup) / sizeof (packet_setup[0]); i += 2)
388 ao_radio_reg_write(packet_setup[i], packet_setup[i+1]);
390 if (changes & AO_RADIO_MODE_BITS_PACKET_TX)
391 for (i = 0; i < sizeof (packet_tx_setup) / sizeof (packet_tx_setup[0]); i += 2)
392 ao_radio_reg_write(packet_tx_setup[i], packet_tx_setup[i+1]);
394 if (changes & AO_RADIO_MODE_BITS_TX_BUF)
395 ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_TXFIFO_THR);
397 if (changes & AO_RADIO_MODE_BITS_TX_FINISH)
398 ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG);
400 if (changes & AO_RADIO_MODE_BITS_PACKET_RX)
401 for (i = 0; i < sizeof (packet_rx_setup) / sizeof (packet_rx_setup[0]); i += 2)
402 ao_radio_reg_write(packet_rx_setup[i], packet_rx_setup[i+1]);
404 if (changes & AO_RADIO_MODE_BITS_RDF)
405 for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2)
406 ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]);
407 ao_radio_mode = new_mode;
410 static const uint16_t radio_setup[] = {
411 #include "ao_cc1120_CC1120.h"
414 static uint8_t ao_radio_configured = 0;
421 ao_radio_strobe(CC1120_SRES);
423 for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2)
424 ao_radio_reg_write(radio_setup[i], radio_setup[i+1]);
430 ao_radio_configured = 1;
434 ao_radio_get(uint8_t len)
436 static uint32_t last_radio_setting;
437 static uint8_t last_len;
439 ao_mutex_get(&ao_radio_mutex);
440 if (!ao_radio_configured)
442 if (ao_config.radio_setting != last_radio_setting) {
443 ao_radio_reg_write(CC1120_FREQ2, ao_config.radio_setting >> 16);
444 ao_radio_reg_write(CC1120_FREQ1, ao_config.radio_setting >> 8);
445 ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting);
446 last_radio_setting = ao_config.radio_setting;
448 if (len != last_len) {
449 ao_radio_reg_write(CC1120_PKT_LEN, len);
454 #define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
457 ao_rdf_start(uint8_t len)
462 ao_radio_set_mode(AO_RADIO_MODE_RDF);
472 ao_arch_block_interrupts();
473 while (!ao_radio_wake && !ao_radio_abort)
474 ao_sleep(&ao_radio_wake);
475 ao_arch_release_interrupts();
484 ao_rdf_start(AO_RADIO_RDF_LEN);
486 ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN);
492 ao_radio_continuity(uint8_t c)
497 ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN);
499 status = ao_radio_fifo_write_start();
500 for (i = 0; i < 3; i++) {
501 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
503 ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN);
505 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN);
507 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
508 status = ao_radio_fifo_write_stop(status);
514 ao_radio_rdf_abort(void)
517 ao_wakeup(&ao_radio_wake);
521 ao_radio_test_cmd(void)
526 if (ao_cmd_lex_c != '\n') {
528 mode = (uint8_t) ao_cmd_lex_u32;
531 if ((mode & 2) && !radio_on) {
533 ao_monitor_disable();
536 ao_packet_slave_stop();
539 ao_radio_strobe(CC1120_STX);
542 for (t = 0; t < 10; t++) {
543 printf ("status: %02x\n", ao_radio_status());
544 ao_delay(AO_MS_TO_TICKS(100));
551 printf ("Hit a character to stop..."); flush();
555 if ((mode & 1) && radio_on) {
565 static uint8_t tx_data[(AO_RADIO_MAX_SEND + 4) * 2];
568 ao_radio_send(const void *d, uint8_t size)
571 uint8_t *e = tx_data;
577 encode_len = ao_fec_encode(d, size, tx_data);
579 ao_radio_get(encode_len);
582 fifo_space = CC1120_FIFO_SIZE;
584 this_len = encode_len;
586 if (this_len > fifo_space) {
587 this_len = fifo_space;
588 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_BUF);
590 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_FINISH);
593 ao_radio_fifo_write(e, this_len);
595 encode_len -= this_len;
601 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
606 ao_arch_block_interrupts();
607 while (!ao_radio_wake)
608 ao_sleep(&ao_radio_wake);
609 ao_arch_release_interrupts();
612 fifo_space = ao_radio_tx_fifo_space();
613 } while (!fifo_space);
618 static uint8_t rx_data[(AO_RADIO_MAX_RECV + 4) * 2 * 8];
619 static uint16_t rx_data_count;
620 static uint16_t rx_data_consumed;
621 static uint16_t rx_data_cur;
622 static uint8_t rx_ignore;
623 static uint8_t rx_waiting;
626 static uint32_t rx_start_tick, rx_packet_tick, rx_done_tick, rx_last_done_tick;
628 uint32_t ao_rx_start_tick, ao_rx_packet_tick, ao_rx_done_tick, ao_rx_last_done_tick;
630 #include <ao_profile.h>
634 ao_radio_rx_isr(void)
640 if (rx_ignore == 0) {
641 if (rx_data_cur >= rx_data_count)
642 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
644 rx_data[rx_data_cur++] = d;
645 if (rx_waiting && rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) {
648 rx_packet_tick = ao_profile_tick();
649 if (rx_data_cur < rx_data_count)
653 ao_wakeup(&ao_radio_wake);
661 ao_radio_rx_wait(void)
663 ao_arch_block_interrupts();
665 while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&
667 ao_sleep(&ao_radio_wake);
670 ao_arch_release_interrupts();
673 rx_data_consumed += AO_FEC_DECODE_BLOCK;
675 return rx_data_cur - rx_data_consumed;
677 return AO_FEC_DECODE_BLOCK;
681 ao_radio_recv(__xdata void *d, uint8_t size)
687 static int been_here = 0;
689 size -= 2; /* status bytes */
690 if (size > AO_RADIO_MAX_RECV) {
691 ao_delay(AO_SEC_TO_TICKS(1));
695 rx_start_tick = ao_profile_tick();
698 len = size + 2; /* CRC bytes */
699 len += 1 + ~(len & 1); /* 1 or two pad bytes */
700 len *= 2; /* 1/2 rate convolution */
701 rx_data_count = len * 8; /* bytes to bits */
703 rx_data_consumed = 0;
707 ao_radio_in_recv = 1;
708 /* configure interrupt pin */
710 ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
719 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
720 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
722 ao_radio_strobe(CC1120_SRX);
724 ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
726 ret = ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait);
728 ao_radio_burst_read_stop();
730 ao_radio_strobe(CC1120_SIDLE);
732 /* Convert from 'real' rssi to cc1111-style values */
734 rssi = AO_RADIO_FROM_RSSI(ao_radio_reg_read(CC1120_RSSI1));
738 /* Store the received RSSI value; the crc-OK byte is already done */
740 ((uint8_t *) d)[size] = (uint8_t) rssi;
742 ao_radio_in_recv = 0;
748 rx_last_done_tick = rx_done_tick;
749 rx_done_tick = ao_profile_tick();
751 ao_rx_start_tick = rx_start_tick;
752 ao_rx_packet_tick = rx_packet_tick;
753 ao_rx_done_tick = rx_done_tick;
754 ao_rx_last_done_tick = rx_last_done_tick;
762 static char *cc1120_state_name[] = {
763 [CC1120_STATUS_STATE_IDLE] = "IDLE",
764 [CC1120_STATUS_STATE_RX] = "RX",
765 [CC1120_STATUS_STATE_TX] = "TX",
766 [CC1120_STATUS_STATE_FSTXON] = "FSTXON",
767 [CC1120_STATUS_STATE_CALIBRATE] = "CALIBRATE",
768 [CC1120_STATUS_STATE_SETTLING] = "SETTLING",
769 [CC1120_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
770 [CC1120_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
773 struct ao_cc1120_reg {
778 const static struct ao_cc1120_reg ao_cc1120_reg[] = {
779 { .addr = CC1120_IOCFG3, .name = "IOCFG3" },
780 { .addr = CC1120_IOCFG2, .name = "IOCFG2" },
781 { .addr = CC1120_IOCFG1, .name = "IOCFG1" },
782 { .addr = CC1120_IOCFG0, .name = "IOCFG0" },
783 { .addr = CC1120_SYNC3, .name = "SYNC3" },
784 { .addr = CC1120_SYNC2, .name = "SYNC2" },
785 { .addr = CC1120_SYNC1, .name = "SYNC1" },
786 { .addr = CC1120_SYNC0, .name = "SYNC0" },
787 { .addr = CC1120_SYNC_CFG1, .name = "SYNC_CFG1" },
788 { .addr = CC1120_SYNC_CFG0, .name = "SYNC_CFG0" },
789 { .addr = CC1120_DEVIATION_M, .name = "DEVIATION_M" },
790 { .addr = CC1120_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
791 { .addr = CC1120_DCFILT_CFG, .name = "DCFILT_CFG" },
792 { .addr = CC1120_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
793 { .addr = CC1120_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
794 { .addr = CC1120_FREQ_IF_CFG, .name = "FREQ_IF_CFG" },
795 { .addr = CC1120_IQIC, .name = "IQIC" },
796 { .addr = CC1120_CHAN_BW, .name = "CHAN_BW" },
797 { .addr = CC1120_MDMCFG1, .name = "MDMCFG1" },
798 { .addr = CC1120_MDMCFG0, .name = "MDMCFG0" },
799 { .addr = CC1120_DRATE2, .name = "DRATE2" },
800 { .addr = CC1120_DRATE1, .name = "DRATE1" },
801 { .addr = CC1120_DRATE0, .name = "DRATE0" },
802 { .addr = CC1120_AGC_REF, .name = "AGC_REF" },
803 { .addr = CC1120_AGC_CS_THR, .name = "AGC_CS_THR" },
804 { .addr = CC1120_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
805 { .addr = CC1120_AGC_CFG3, .name = "AGC_CFG3" },
806 { .addr = CC1120_AGC_CFG2, .name = "AGC_CFG2" },
807 { .addr = CC1120_AGC_CFG1, .name = "AGC_CFG1" },
808 { .addr = CC1120_AGC_CFG0, .name = "AGC_CFG0" },
809 { .addr = CC1120_FIFO_CFG, .name = "FIFO_CFG" },
810 { .addr = CC1120_DEV_ADDR, .name = "DEV_ADDR" },
811 { .addr = CC1120_SETTLING_CFG, .name = "SETTLING_CFG" },
812 { .addr = CC1120_FS_CFG, .name = "FS_CFG" },
813 { .addr = CC1120_WOR_CFG1, .name = "WOR_CFG1" },
814 { .addr = CC1120_WOR_CFG0, .name = "WOR_CFG0" },
815 { .addr = CC1120_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
816 { .addr = CC1120_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
817 { .addr = CC1120_PKT_CFG2, .name = "PKT_CFG2" },
818 { .addr = CC1120_PKT_CFG1, .name = "PKT_CFG1" },
819 { .addr = CC1120_PKT_CFG0, .name = "PKT_CFG0" },
820 { .addr = CC1120_RFEND_CFG1, .name = "RFEND_CFG1" },
821 { .addr = CC1120_RFEND_CFG0, .name = "RFEND_CFG0" },
822 { .addr = CC1120_PA_CFG2, .name = "PA_CFG2" },
823 { .addr = CC1120_PA_CFG1, .name = "PA_CFG1" },
824 { .addr = CC1120_PA_CFG0, .name = "PA_CFG0" },
825 { .addr = CC1120_PKT_LEN, .name = "PKT_LEN" },
826 { .addr = CC1120_IF_MIX_CFG, .name = "IF_MIX_CFG" },
827 { .addr = CC1120_FREQOFF_CFG, .name = "FREQOFF_CFG" },
828 { .addr = CC1120_TOC_CFG, .name = "TOC_CFG" },
829 { .addr = CC1120_MARC_SPARE, .name = "MARC_SPARE" },
830 { .addr = CC1120_ECG_CFG, .name = "ECG_CFG" },
831 { .addr = CC1120_SOFT_TX_DATA_CFG, .name = "SOFT_TX_DATA_CFG" },
832 { .addr = CC1120_EXT_CTRL, .name = "EXT_CTRL" },
833 { .addr = CC1120_RCCAL_FINE, .name = "RCCAL_FINE" },
834 { .addr = CC1120_RCCAL_COARSE, .name = "RCCAL_COARSE" },
835 { .addr = CC1120_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
836 { .addr = CC1120_FREQOFF1, .name = "FREQOFF1" },
837 { .addr = CC1120_FREQOFF0, .name = "FREQOFF0" },
838 { .addr = CC1120_FREQ2, .name = "FREQ2" },
839 { .addr = CC1120_FREQ1, .name = "FREQ1" },
840 { .addr = CC1120_FREQ0, .name = "FREQ0" },
841 { .addr = CC1120_IF_ADC2, .name = "IF_ADC2" },
842 { .addr = CC1120_IF_ADC1, .name = "IF_ADC1" },
843 { .addr = CC1120_IF_ADC0, .name = "IF_ADC0" },
844 { .addr = CC1120_FS_DIG1, .name = "FS_DIG1" },
845 { .addr = CC1120_FS_DIG0, .name = "FS_DIG0" },
846 { .addr = CC1120_FS_CAL3, .name = "FS_CAL3" },
847 { .addr = CC1120_FS_CAL2, .name = "FS_CAL2" },
848 { .addr = CC1120_FS_CAL1, .name = "FS_CAL1" },
849 { .addr = CC1120_FS_CAL0, .name = "FS_CAL0" },
850 { .addr = CC1120_FS_CHP, .name = "FS_CHP" },
851 { .addr = CC1120_FS_DIVTWO, .name = "FS_DIVTWO" },
852 { .addr = CC1120_FS_DSM1, .name = "FS_DSM1" },
853 { .addr = CC1120_FS_DSM0, .name = "FS_DSM0" },
854 { .addr = CC1120_FS_DVC1, .name = "FS_DVC1" },
855 { .addr = CC1120_FS_DVC0, .name = "FS_DVC0" },
856 { .addr = CC1120_FS_LBI, .name = "FS_LBI" },
857 { .addr = CC1120_FS_PFD, .name = "FS_PFD" },
858 { .addr = CC1120_FS_PRE, .name = "FS_PRE" },
859 { .addr = CC1120_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
860 { .addr = CC1120_FS_SPARE, .name = "FS_SPARE" },
861 { .addr = CC1120_FS_VCO4, .name = "FS_VCO4" },
862 { .addr = CC1120_FS_VCO3, .name = "FS_VCO3" },
863 { .addr = CC1120_FS_VCO2, .name = "FS_VCO2" },
864 { .addr = CC1120_FS_VCO1, .name = "FS_VCO1" },
865 { .addr = CC1120_FS_VCO0, .name = "FS_VCO0" },
866 { .addr = CC1120_GBIAS6, .name = "GBIAS6" },
867 { .addr = CC1120_GBIAS5, .name = "GBIAS5" },
868 { .addr = CC1120_GBIAS4, .name = "GBIAS4" },
869 { .addr = CC1120_GBIAS3, .name = "GBIAS3" },
870 { .addr = CC1120_GBIAS2, .name = "GBIAS2" },
871 { .addr = CC1120_GBIAS1, .name = "GBIAS1" },
872 { .addr = CC1120_GBIAS0, .name = "GBIAS0" },
873 { .addr = CC1120_IFAMP, .name = "IFAMP" },
874 { .addr = CC1120_LNA, .name = "LNA" },
875 { .addr = CC1120_RXMIX, .name = "RXMIX" },
876 { .addr = CC1120_XOSC5, .name = "XOSC5" },
877 { .addr = CC1120_XOSC4, .name = "XOSC4" },
878 { .addr = CC1120_XOSC3, .name = "XOSC3" },
879 { .addr = CC1120_XOSC2, .name = "XOSC2" },
880 { .addr = CC1120_XOSC1, .name = "XOSC1" },
881 { .addr = CC1120_XOSC0, .name = "XOSC0" },
882 { .addr = CC1120_ANALOG_SPARE, .name = "ANALOG_SPARE" },
883 { .addr = CC1120_PA_CFG3, .name = "PA_CFG3" },
884 { .addr = CC1120_WOR_TIME1, .name = "WOR_TIME1" },
885 { .addr = CC1120_WOR_TIME0, .name = "WOR_TIME0" },
886 { .addr = CC1120_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
887 { .addr = CC1120_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
888 { .addr = CC1120_BIST, .name = "BIST" },
889 { .addr = CC1120_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
890 { .addr = CC1120_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
891 { .addr = CC1120_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
892 { .addr = CC1120_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
893 { .addr = CC1120_IQIE_I1, .name = "IQIE_I1" },
894 { .addr = CC1120_IQIE_I0, .name = "IQIE_I0" },
895 { .addr = CC1120_IQIE_Q1, .name = "IQIE_Q1" },
896 { .addr = CC1120_IQIE_Q0, .name = "IQIE_Q0" },
897 { .addr = CC1120_RSSI1, .name = "RSSI1" },
898 { .addr = CC1120_RSSI0, .name = "RSSI0" },
899 { .addr = CC1120_MARCSTATE, .name = "MARCSTATE" },
900 { .addr = CC1120_LQI_VAL, .name = "LQI_VAL" },
901 { .addr = CC1120_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
902 { .addr = CC1120_DEM_STATUS, .name = "DEM_STATUS" },
903 { .addr = CC1120_FREQOFF_EST1, .name = "FREQOFF_EST1" },
904 { .addr = CC1120_FREQOFF_EST0, .name = "FREQOFF_EST0" },
905 { .addr = CC1120_AGC_GAIN3, .name = "AGC_GAIN3" },
906 { .addr = CC1120_AGC_GAIN2, .name = "AGC_GAIN2" },
907 { .addr = CC1120_AGC_GAIN1, .name = "AGC_GAIN1" },
908 { .addr = CC1120_AGC_GAIN0, .name = "AGC_GAIN0" },
909 { .addr = CC1120_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
910 { .addr = CC1120_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
911 { .addr = CC1120_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
912 { .addr = CC1120_RNDGEN, .name = "RNDGEN" },
913 { .addr = CC1120_MAGN2, .name = "MAGN2" },
914 { .addr = CC1120_MAGN1, .name = "MAGN1" },
915 { .addr = CC1120_MAGN0, .name = "MAGN0" },
916 { .addr = CC1120_ANG1, .name = "ANG1" },
917 { .addr = CC1120_ANG0, .name = "ANG0" },
918 { .addr = CC1120_CHFILT_I2, .name = "CHFILT_I2" },
919 { .addr = CC1120_CHFILT_I1, .name = "CHFILT_I1" },
920 { .addr = CC1120_CHFILT_I0, .name = "CHFILT_I0" },
921 { .addr = CC1120_CHFILT_Q2, .name = "CHFILT_Q2" },
922 { .addr = CC1120_CHFILT_Q1, .name = "CHFILT_Q1" },
923 { .addr = CC1120_CHFILT_Q0, .name = "CHFILT_Q0" },
924 { .addr = CC1120_GPIO_STATUS, .name = "GPIO_STATUS" },
925 { .addr = CC1120_FSCAL_CTRL, .name = "FSCAL_CTRL" },
926 { .addr = CC1120_PHASE_ADJUST, .name = "PHASE_ADJUST" },
927 { .addr = CC1120_PARTNUMBER, .name = "PARTNUMBER" },
928 { .addr = CC1120_PARTVERSION, .name = "PARTVERSION" },
929 { .addr = CC1120_SERIAL_STATUS, .name = "SERIAL_STATUS" },
930 { .addr = CC1120_RX_STATUS, .name = "RX_STATUS" },
931 { .addr = CC1120_TX_STATUS, .name = "TX_STATUS" },
932 { .addr = CC1120_MARC_STATUS1, .name = "MARC_STATUS1" },
933 { .addr = CC1120_MARC_STATUS0, .name = "MARC_STATUS0" },
934 { .addr = CC1120_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
935 { .addr = CC1120_FSRF_TEST, .name = "FSRF_TEST" },
936 { .addr = CC1120_PRE_TEST, .name = "PRE_TEST" },
937 { .addr = CC1120_PRE_OVR, .name = "PRE_OVR" },
938 { .addr = CC1120_ADC_TEST, .name = "ADC_TEST" },
939 { .addr = CC1120_DVC_TEST, .name = "DVC_TEST" },
940 { .addr = CC1120_ATEST, .name = "ATEST" },
941 { .addr = CC1120_ATEST_LVDS, .name = "ATEST_LVDS" },
942 { .addr = CC1120_ATEST_MODE, .name = "ATEST_MODE" },
943 { .addr = CC1120_XOSC_TEST1, .name = "XOSC_TEST1" },
944 { .addr = CC1120_XOSC_TEST0, .name = "XOSC_TEST0" },
945 { .addr = CC1120_RXFIRST, .name = "RXFIRST" },
946 { .addr = CC1120_TXFIRST, .name = "TXFIRST" },
947 { .addr = CC1120_RXLAST, .name = "RXLAST" },
948 { .addr = CC1120_TXLAST, .name = "TXLAST" },
949 { .addr = CC1120_NUM_TXBYTES, .name = "NUM_TXBYTES" },
950 { .addr = CC1120_NUM_RXBYTES, .name = "NUM_RXBYTES" },
951 { .addr = CC1120_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
952 { .addr = CC1120_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
955 #define AO_NUM_CC1120_REG (sizeof ao_cc1120_reg / sizeof ao_cc1120_reg[0])
957 static void ao_radio_show(void) {
958 uint8_t status = ao_radio_status();
962 status = ao_radio_status();
963 printf ("Status: %02x\n", status);
964 printf ("CHIP_RDY: %d\n", (status >> CC1120_STATUS_CHIP_RDY) & 1);
965 printf ("STATE: %s\n", cc1120_state_name[(status >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK]);
966 printf ("MARC: %02x\n", ao_radio_marc_status());
968 for (i = 0; i < AO_NUM_CC1120_REG; i++)
969 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name);
973 static void ao_radio_beep(void) {
974 ao_radio_rdf(RDF_PACKET_LEN);
977 static void ao_radio_packet(void) {
978 static const uint8_t packet[] = {
980 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
981 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
982 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
983 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
989 ao_radio_send(packet, sizeof (packet));
998 if (ao_radio_recv(bytes, 34)) {
999 if (bytes[33] & 0x80)
1003 printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32]));
1004 for (b = 0; b < 32; b++)
1005 printf (" %02x", bytes[b]);
1012 static const struct ao_cmds ao_radio_cmds[] = {
1013 { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
1015 { ao_radio_show, "R\0Show CC1120 status" },
1016 { ao_radio_beep, "b\0Emit an RDF beacon" },
1017 { ao_radio_packet, "p\0Send a test packet" },
1018 { ao_radio_test_recv, "q\0Recv a test packet" },
1028 ao_radio_configured = 0;
1029 ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN));
1032 AO_CC1120_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN));
1033 for (i = 0; i < 10000; i++) {
1034 if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0)
1037 AO_CC1120_SPI_CS_PORT->bsrr = (1 << AO_CC1120_SPI_CS_PIN);
1039 ao_panic(AO_PANIC_SELF_TEST_CC1120);
1042 /* Enable the EXTI interrupt for the appropriate pin */
1043 ao_enable_port(AO_CC1120_INT_PORT);
1044 ao_exti_setup(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1045 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
1048 ao_cmd_register(&ao_radio_cmds[0]);