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 extern const uint32_t ao_radio_cal;
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_start(void)
165 uint8_t addr = ((0 << CC1120_READ) |
166 (1 << CC1120_BURST) |
171 ao_radio_duplex(&addr, &status, 1);
175 static inline uint8_t ao_radio_fifo_write_stop(uint8_t status) {
181 ao_radio_fifo_write(uint8_t *data, uint8_t len)
183 uint8_t status = ao_radio_fifo_write_start();
184 ao_radio_spi_send(data, len);
185 return ao_radio_fifo_write_stop(status);
189 ao_radio_fifo_write_fixed(uint8_t data, uint8_t len)
191 uint8_t status = ao_radio_fifo_write_start();
192 ao_radio_spi_send_fixed(data, len);
193 return ao_radio_fifo_write_stop(status);
197 ao_radio_tx_fifo_space(void)
199 return CC1120_FIFO_SIZE - ao_radio_reg_read(CC1120_NUM_TXBYTES);
203 ao_radio_status(void)
205 return ao_radio_strobe (CC1120_SNOP);
209 ao_radio_recv_abort(void)
212 ao_wakeup(&ao_radio_wake);
215 #define ao_radio_rdf_value 0x55
218 ao_radio_marc_status(void)
220 return ao_radio_reg_read(CC1120_MARC_STATUS1);
224 ao_radio_tx_isr(void)
226 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
228 ao_wakeup(&ao_radio_wake);
232 ao_radio_start_tx(void)
234 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_tx_isr);
235 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
236 ao_radio_strobe(CC1120_STX);
243 uint8_t state = ao_radio_strobe(CC1120_SIDLE);
244 if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_IDLE)
250 * Packet deviation is 20.5kHz
252 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
254 * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz
257 #define PACKET_DEV_E 5
258 #define PACKET_DEV_M 80
261 * For our packet data, set the symbol rate to 38360 Baud
263 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
264 * Rdata = -------------------------------------- * fosc
268 * DATARATE_M = 239914
271 #define PACKET_DRATE_E 9
272 #define PACKET_DRATE_M 239914
274 static const uint16_t packet_setup[] = {
275 CC1120_DEVIATION_M, PACKET_DEV_M,
276 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
277 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
278 (PACKET_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
279 CC1120_DRATE2, ((PACKET_DRATE_E << CC1120_DRATE2_DATARATE_E) |
280 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
281 CC1120_DRATE1, ((PACKET_DRATE_M >> 8) & 0xff),
282 CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff),
283 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
284 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
285 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
286 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
287 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
288 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
289 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
290 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
291 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
292 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
293 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
296 static const uint16_t packet_tx_setup[] = {
297 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
298 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
299 CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG,
302 static const uint16_t packet_rx_setup[] = {
303 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
304 (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT)),
305 CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT,
309 * RDF deviation is 5kHz
311 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
313 * 32e6Hz / (2 ** 24) * (256 + 71) * (2 ** 3) = 4989
318 #define RDF_PACKET_LEN 50
321 * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
323 * (2**20 - DATARATE_M) * 2 ** DATARATE_E
324 * Rdata = -------------------------------------- * fosc
327 * DATARATE_M = 511705
330 * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
332 #define RDF_DRATE_E 5
333 #define RDF_DRATE_M 25166
334 #define RDF_PACKET_LEN 50
336 static const uint16_t rdf_setup[] = {
337 CC1120_DEVIATION_M, RDF_DEV_M,
338 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
339 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
340 (RDF_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
341 CC1120_DRATE2, ((RDF_DRATE_E << CC1120_DRATE2_DATARATE_E) |
342 (((RDF_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
343 CC1120_DRATE1, ((RDF_DRATE_M >> 8) & 0xff),
344 CC1120_DRATE0, ((RDF_DRATE_M >> 0) & 0xff),
345 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
346 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
347 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
348 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
349 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
350 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
351 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
352 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
353 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
354 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
355 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
358 static uint8_t ao_radio_mode;
360 #define AO_RADIO_MODE_BITS_PACKET 1
361 #define AO_RADIO_MODE_BITS_PACKET_TX 2
362 #define AO_RADIO_MODE_BITS_TX_BUF 4
363 #define AO_RADIO_MODE_BITS_TX_FINISH 8
364 #define AO_RADIO_MODE_BITS_PACKET_RX 16
365 #define AO_RADIO_MODE_BITS_RDF 32
367 #define AO_RADIO_MODE_NONE 0
368 #define AO_RADIO_MODE_PACKET_TX_BUF (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_BUF)
369 #define AO_RADIO_MODE_PACKET_TX_FINISH (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_FINISH)
370 #define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_RX)
371 #define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_TX_FINISH)
374 ao_radio_set_mode(uint8_t new_mode)
379 if (new_mode == ao_radio_mode)
382 changes = new_mode & (~ao_radio_mode);
383 if (changes & AO_RADIO_MODE_BITS_PACKET)
384 for (i = 0; i < sizeof (packet_setup) / sizeof (packet_setup[0]); i += 2)
385 ao_radio_reg_write(packet_setup[i], packet_setup[i+1]);
387 if (changes & AO_RADIO_MODE_BITS_PACKET_TX)
388 for (i = 0; i < sizeof (packet_tx_setup) / sizeof (packet_tx_setup[0]); i += 2)
389 ao_radio_reg_write(packet_tx_setup[i], packet_tx_setup[i+1]);
391 if (changes & AO_RADIO_MODE_BITS_TX_BUF)
392 ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_TXFIFO_THR);
394 if (changes & AO_RADIO_MODE_BITS_TX_FINISH)
395 ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG);
397 if (changes & AO_RADIO_MODE_BITS_PACKET_RX)
398 for (i = 0; i < sizeof (packet_rx_setup) / sizeof (packet_rx_setup[0]); i += 2)
399 ao_radio_reg_write(packet_rx_setup[i], packet_rx_setup[i+1]);
401 if (changes & AO_RADIO_MODE_BITS_RDF)
402 for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2)
403 ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]);
404 ao_radio_mode = new_mode;
407 static const uint16_t radio_setup[] = {
408 #include "ao_cc1120_CC1120.h"
411 static uint8_t ao_radio_configured = 0;
418 ao_radio_strobe(CC1120_SRES);
420 for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2)
421 ao_radio_reg_write(radio_setup[i], radio_setup[i+1]);
427 ao_radio_configured = 1;
431 ao_radio_get(uint8_t len)
433 static uint32_t last_radio_setting;
434 static uint8_t last_len;
436 ao_mutex_get(&ao_radio_mutex);
437 if (!ao_radio_configured)
439 if (ao_config.radio_setting != last_radio_setting) {
440 ao_radio_reg_write(CC1120_FREQ2, ao_config.radio_setting >> 16);
441 ao_radio_reg_write(CC1120_FREQ1, ao_config.radio_setting >> 8);
442 ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting);
443 last_radio_setting = ao_config.radio_setting;
445 if (len != last_len) {
446 ao_radio_reg_write(CC1120_PKT_LEN, len);
451 #define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
454 ao_rdf_start(uint8_t len)
459 ao_radio_set_mode(AO_RADIO_MODE_RDF);
470 while (!ao_radio_wake && !ao_radio_abort)
471 ao_sleep(&ao_radio_wake);
481 ao_rdf_start(AO_RADIO_RDF_LEN);
483 ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN);
489 ao_radio_continuity(uint8_t c)
494 ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN);
496 status = ao_radio_fifo_write_start();
497 for (i = 0; i < 3; i++) {
498 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
500 ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN);
502 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN);
504 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
505 status = ao_radio_fifo_write_stop(status);
511 ao_radio_rdf_abort(void)
514 ao_wakeup(&ao_radio_wake);
518 ao_radio_test_cmd(void)
523 if (ao_cmd_lex_c != '\n') {
525 mode = (uint8_t) ao_cmd_lex_u32;
528 if ((mode & 2) && !radio_on) {
530 ao_monitor_disable();
533 ao_packet_slave_stop();
536 ao_radio_strobe(CC1120_STX);
539 for (t = 0; t < 10; t++) {
540 printf ("status: %02x\n", ao_radio_status());
541 ao_delay(AO_MS_TO_TICKS(100));
548 printf ("Hit a character to stop..."); flush();
552 if ((mode & 1) && radio_on) {
563 ao_radio_send(const void *d, uint8_t size)
566 static uint8_t encode[256];
573 encode_len = ao_fec_encode(d, size, encode);
575 ao_radio_get(encode_len);
578 fifo_space = CC1120_FIFO_SIZE;
580 this_len = encode_len;
582 if (this_len > fifo_space) {
583 this_len = fifo_space;
584 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_BUF);
586 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_FINISH);
589 ao_radio_fifo_write(e, this_len);
591 encode_len -= this_len;
597 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
603 while (!ao_radio_wake)
604 ao_sleep(&ao_radio_wake);
608 fifo_space = ao_radio_tx_fifo_space();
609 } while (!fifo_space);
614 #define AO_RADIO_MAX_RECV 90
616 static uint8_t rx_data[(AO_RADIO_MAX_RECV + 4) * 2 * 8];
617 static uint16_t rx_data_count;
618 static uint16_t rx_data_consumed;
619 static uint16_t rx_data_cur;
620 static uint8_t rx_ignore;
621 static uint8_t rx_waiting;
624 static uint32_t rx_start_tick, rx_packet_tick, rx_done_tick, rx_last_done_tick;
626 uint32_t ao_rx_start_tick, ao_rx_packet_tick, ao_rx_done_tick, ao_rx_last_done_tick;
628 #include <ao_profile.h>
632 ao_radio_rx_isr(void)
638 if (rx_ignore == 0) {
639 if (rx_data_cur >= rx_data_count)
640 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
642 rx_data[rx_data_cur++] = d;
643 if (rx_waiting && rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) {
646 rx_packet_tick = ao_profile_tick();
647 if (rx_data_cur < rx_data_count)
651 ao_wakeup(&ao_radio_wake);
659 ao_radio_rx_wait(void)
663 while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&
665 ao_sleep(&ao_radio_wake);
671 rx_data_consumed += AO_FEC_DECODE_BLOCK;
673 return rx_data_cur - rx_data_consumed;
675 return AO_FEC_DECODE_BLOCK;
679 ao_radio_recv(__xdata void *d, uint8_t size)
685 static int been_here = 0;
687 size -= 2; /* status bytes */
688 if (size > AO_RADIO_MAX_RECV) {
689 ao_delay(AO_SEC_TO_TICKS(1));
693 rx_start_tick = ao_profile_tick();
696 len = size + 2; /* CRC bytes */
697 len += 1 + ~(len & 1); /* 1 or two pad bytes */
698 len *= 2; /* 1/2 rate convolution */
699 rx_data_count = len * 8; /* bytes to bits */
701 rx_data_consumed = 0;
705 ao_radio_in_recv = 1;
706 /* configure interrupt pin */
708 ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
717 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
718 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
720 ao_radio_strobe(CC1120_SRX);
722 ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
724 ret = ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait);
726 ao_radio_burst_read_stop();
728 ao_radio_strobe(CC1120_SIDLE);
730 /* Convert from 'real' rssi to cc1111-style values */
732 rssi = AO_RADIO_FROM_RSSI(ao_radio_reg_read(CC1120_RSSI1));
736 /* Store the received RSSI value; the crc-OK byte is already done */
738 ((uint8_t *) d)[size] = (uint8_t) rssi;
740 ao_radio_in_recv = 0;
746 rx_last_done_tick = rx_done_tick;
747 rx_done_tick = ao_profile_tick();
749 ao_rx_start_tick = rx_start_tick;
750 ao_rx_packet_tick = rx_packet_tick;
751 ao_rx_done_tick = rx_done_tick;
752 ao_rx_last_done_tick = rx_last_done_tick;
760 static char *cc1120_state_name[] = {
761 [CC1120_STATUS_STATE_IDLE] = "IDLE",
762 [CC1120_STATUS_STATE_RX] = "RX",
763 [CC1120_STATUS_STATE_TX] = "TX",
764 [CC1120_STATUS_STATE_FSTXON] = "FSTXON",
765 [CC1120_STATUS_STATE_CALIBRATE] = "CALIBRATE",
766 [CC1120_STATUS_STATE_SETTLING] = "SETTLING",
767 [CC1120_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
768 [CC1120_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
771 struct ao_cc1120_reg {
776 const static struct ao_cc1120_reg ao_cc1120_reg[] = {
777 { .addr = CC1120_IOCFG3, .name = "IOCFG3" },
778 { .addr = CC1120_IOCFG2, .name = "IOCFG2" },
779 { .addr = CC1120_IOCFG1, .name = "IOCFG1" },
780 { .addr = CC1120_IOCFG0, .name = "IOCFG0" },
781 { .addr = CC1120_SYNC3, .name = "SYNC3" },
782 { .addr = CC1120_SYNC2, .name = "SYNC2" },
783 { .addr = CC1120_SYNC1, .name = "SYNC1" },
784 { .addr = CC1120_SYNC0, .name = "SYNC0" },
785 { .addr = CC1120_SYNC_CFG1, .name = "SYNC_CFG1" },
786 { .addr = CC1120_SYNC_CFG0, .name = "SYNC_CFG0" },
787 { .addr = CC1120_DEVIATION_M, .name = "DEVIATION_M" },
788 { .addr = CC1120_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
789 { .addr = CC1120_DCFILT_CFG, .name = "DCFILT_CFG" },
790 { .addr = CC1120_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
791 { .addr = CC1120_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
792 { .addr = CC1120_FREQ_IF_CFG, .name = "FREQ_IF_CFG" },
793 { .addr = CC1120_IQIC, .name = "IQIC" },
794 { .addr = CC1120_CHAN_BW, .name = "CHAN_BW" },
795 { .addr = CC1120_MDMCFG1, .name = "MDMCFG1" },
796 { .addr = CC1120_MDMCFG0, .name = "MDMCFG0" },
797 { .addr = CC1120_DRATE2, .name = "DRATE2" },
798 { .addr = CC1120_DRATE1, .name = "DRATE1" },
799 { .addr = CC1120_DRATE0, .name = "DRATE0" },
800 { .addr = CC1120_AGC_REF, .name = "AGC_REF" },
801 { .addr = CC1120_AGC_CS_THR, .name = "AGC_CS_THR" },
802 { .addr = CC1120_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
803 { .addr = CC1120_AGC_CFG3, .name = "AGC_CFG3" },
804 { .addr = CC1120_AGC_CFG2, .name = "AGC_CFG2" },
805 { .addr = CC1120_AGC_CFG1, .name = "AGC_CFG1" },
806 { .addr = CC1120_AGC_CFG0, .name = "AGC_CFG0" },
807 { .addr = CC1120_FIFO_CFG, .name = "FIFO_CFG" },
808 { .addr = CC1120_DEV_ADDR, .name = "DEV_ADDR" },
809 { .addr = CC1120_SETTLING_CFG, .name = "SETTLING_CFG" },
810 { .addr = CC1120_FS_CFG, .name = "FS_CFG" },
811 { .addr = CC1120_WOR_CFG1, .name = "WOR_CFG1" },
812 { .addr = CC1120_WOR_CFG0, .name = "WOR_CFG0" },
813 { .addr = CC1120_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
814 { .addr = CC1120_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
815 { .addr = CC1120_PKT_CFG2, .name = "PKT_CFG2" },
816 { .addr = CC1120_PKT_CFG1, .name = "PKT_CFG1" },
817 { .addr = CC1120_PKT_CFG0, .name = "PKT_CFG0" },
818 { .addr = CC1120_RFEND_CFG1, .name = "RFEND_CFG1" },
819 { .addr = CC1120_RFEND_CFG0, .name = "RFEND_CFG0" },
820 { .addr = CC1120_PA_CFG2, .name = "PA_CFG2" },
821 { .addr = CC1120_PA_CFG1, .name = "PA_CFG1" },
822 { .addr = CC1120_PA_CFG0, .name = "PA_CFG0" },
823 { .addr = CC1120_PKT_LEN, .name = "PKT_LEN" },
824 { .addr = CC1120_IF_MIX_CFG, .name = "IF_MIX_CFG" },
825 { .addr = CC1120_FREQOFF_CFG, .name = "FREQOFF_CFG" },
826 { .addr = CC1120_TOC_CFG, .name = "TOC_CFG" },
827 { .addr = CC1120_MARC_SPARE, .name = "MARC_SPARE" },
828 { .addr = CC1120_ECG_CFG, .name = "ECG_CFG" },
829 { .addr = CC1120_SOFT_TX_DATA_CFG, .name = "SOFT_TX_DATA_CFG" },
830 { .addr = CC1120_EXT_CTRL, .name = "EXT_CTRL" },
831 { .addr = CC1120_RCCAL_FINE, .name = "RCCAL_FINE" },
832 { .addr = CC1120_RCCAL_COARSE, .name = "RCCAL_COARSE" },
833 { .addr = CC1120_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
834 { .addr = CC1120_FREQOFF1, .name = "FREQOFF1" },
835 { .addr = CC1120_FREQOFF0, .name = "FREQOFF0" },
836 { .addr = CC1120_FREQ2, .name = "FREQ2" },
837 { .addr = CC1120_FREQ1, .name = "FREQ1" },
838 { .addr = CC1120_FREQ0, .name = "FREQ0" },
839 { .addr = CC1120_IF_ADC2, .name = "IF_ADC2" },
840 { .addr = CC1120_IF_ADC1, .name = "IF_ADC1" },
841 { .addr = CC1120_IF_ADC0, .name = "IF_ADC0" },
842 { .addr = CC1120_FS_DIG1, .name = "FS_DIG1" },
843 { .addr = CC1120_FS_DIG0, .name = "FS_DIG0" },
844 { .addr = CC1120_FS_CAL3, .name = "FS_CAL3" },
845 { .addr = CC1120_FS_CAL2, .name = "FS_CAL2" },
846 { .addr = CC1120_FS_CAL1, .name = "FS_CAL1" },
847 { .addr = CC1120_FS_CAL0, .name = "FS_CAL0" },
848 { .addr = CC1120_FS_CHP, .name = "FS_CHP" },
849 { .addr = CC1120_FS_DIVTWO, .name = "FS_DIVTWO" },
850 { .addr = CC1120_FS_DSM1, .name = "FS_DSM1" },
851 { .addr = CC1120_FS_DSM0, .name = "FS_DSM0" },
852 { .addr = CC1120_FS_DVC1, .name = "FS_DVC1" },
853 { .addr = CC1120_FS_DVC0, .name = "FS_DVC0" },
854 { .addr = CC1120_FS_LBI, .name = "FS_LBI" },
855 { .addr = CC1120_FS_PFD, .name = "FS_PFD" },
856 { .addr = CC1120_FS_PRE, .name = "FS_PRE" },
857 { .addr = CC1120_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
858 { .addr = CC1120_FS_SPARE, .name = "FS_SPARE" },
859 { .addr = CC1120_FS_VCO4, .name = "FS_VCO4" },
860 { .addr = CC1120_FS_VCO3, .name = "FS_VCO3" },
861 { .addr = CC1120_FS_VCO2, .name = "FS_VCO2" },
862 { .addr = CC1120_FS_VCO1, .name = "FS_VCO1" },
863 { .addr = CC1120_FS_VCO0, .name = "FS_VCO0" },
864 { .addr = CC1120_GBIAS6, .name = "GBIAS6" },
865 { .addr = CC1120_GBIAS5, .name = "GBIAS5" },
866 { .addr = CC1120_GBIAS4, .name = "GBIAS4" },
867 { .addr = CC1120_GBIAS3, .name = "GBIAS3" },
868 { .addr = CC1120_GBIAS2, .name = "GBIAS2" },
869 { .addr = CC1120_GBIAS1, .name = "GBIAS1" },
870 { .addr = CC1120_GBIAS0, .name = "GBIAS0" },
871 { .addr = CC1120_IFAMP, .name = "IFAMP" },
872 { .addr = CC1120_LNA, .name = "LNA" },
873 { .addr = CC1120_RXMIX, .name = "RXMIX" },
874 { .addr = CC1120_XOSC5, .name = "XOSC5" },
875 { .addr = CC1120_XOSC4, .name = "XOSC4" },
876 { .addr = CC1120_XOSC3, .name = "XOSC3" },
877 { .addr = CC1120_XOSC2, .name = "XOSC2" },
878 { .addr = CC1120_XOSC1, .name = "XOSC1" },
879 { .addr = CC1120_XOSC0, .name = "XOSC0" },
880 { .addr = CC1120_ANALOG_SPARE, .name = "ANALOG_SPARE" },
881 { .addr = CC1120_PA_CFG3, .name = "PA_CFG3" },
882 { .addr = CC1120_WOR_TIME1, .name = "WOR_TIME1" },
883 { .addr = CC1120_WOR_TIME0, .name = "WOR_TIME0" },
884 { .addr = CC1120_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
885 { .addr = CC1120_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
886 { .addr = CC1120_BIST, .name = "BIST" },
887 { .addr = CC1120_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
888 { .addr = CC1120_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
889 { .addr = CC1120_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
890 { .addr = CC1120_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
891 { .addr = CC1120_IQIE_I1, .name = "IQIE_I1" },
892 { .addr = CC1120_IQIE_I0, .name = "IQIE_I0" },
893 { .addr = CC1120_IQIE_Q1, .name = "IQIE_Q1" },
894 { .addr = CC1120_IQIE_Q0, .name = "IQIE_Q0" },
895 { .addr = CC1120_RSSI1, .name = "RSSI1" },
896 { .addr = CC1120_RSSI0, .name = "RSSI0" },
897 { .addr = CC1120_MARCSTATE, .name = "MARCSTATE" },
898 { .addr = CC1120_LQI_VAL, .name = "LQI_VAL" },
899 { .addr = CC1120_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
900 { .addr = CC1120_DEM_STATUS, .name = "DEM_STATUS" },
901 { .addr = CC1120_FREQOFF_EST1, .name = "FREQOFF_EST1" },
902 { .addr = CC1120_FREQOFF_EST0, .name = "FREQOFF_EST0" },
903 { .addr = CC1120_AGC_GAIN3, .name = "AGC_GAIN3" },
904 { .addr = CC1120_AGC_GAIN2, .name = "AGC_GAIN2" },
905 { .addr = CC1120_AGC_GAIN1, .name = "AGC_GAIN1" },
906 { .addr = CC1120_AGC_GAIN0, .name = "AGC_GAIN0" },
907 { .addr = CC1120_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
908 { .addr = CC1120_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
909 { .addr = CC1120_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
910 { .addr = CC1120_RNDGEN, .name = "RNDGEN" },
911 { .addr = CC1120_MAGN2, .name = "MAGN2" },
912 { .addr = CC1120_MAGN1, .name = "MAGN1" },
913 { .addr = CC1120_MAGN0, .name = "MAGN0" },
914 { .addr = CC1120_ANG1, .name = "ANG1" },
915 { .addr = CC1120_ANG0, .name = "ANG0" },
916 { .addr = CC1120_CHFILT_I2, .name = "CHFILT_I2" },
917 { .addr = CC1120_CHFILT_I1, .name = "CHFILT_I1" },
918 { .addr = CC1120_CHFILT_I0, .name = "CHFILT_I0" },
919 { .addr = CC1120_CHFILT_Q2, .name = "CHFILT_Q2" },
920 { .addr = CC1120_CHFILT_Q1, .name = "CHFILT_Q1" },
921 { .addr = CC1120_CHFILT_Q0, .name = "CHFILT_Q0" },
922 { .addr = CC1120_GPIO_STATUS, .name = "GPIO_STATUS" },
923 { .addr = CC1120_FSCAL_CTRL, .name = "FSCAL_CTRL" },
924 { .addr = CC1120_PHASE_ADJUST, .name = "PHASE_ADJUST" },
925 { .addr = CC1120_PARTNUMBER, .name = "PARTNUMBER" },
926 { .addr = CC1120_PARTVERSION, .name = "PARTVERSION" },
927 { .addr = CC1120_SERIAL_STATUS, .name = "SERIAL_STATUS" },
928 { .addr = CC1120_RX_STATUS, .name = "RX_STATUS" },
929 { .addr = CC1120_TX_STATUS, .name = "TX_STATUS" },
930 { .addr = CC1120_MARC_STATUS1, .name = "MARC_STATUS1" },
931 { .addr = CC1120_MARC_STATUS0, .name = "MARC_STATUS0" },
932 { .addr = CC1120_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
933 { .addr = CC1120_FSRF_TEST, .name = "FSRF_TEST" },
934 { .addr = CC1120_PRE_TEST, .name = "PRE_TEST" },
935 { .addr = CC1120_PRE_OVR, .name = "PRE_OVR" },
936 { .addr = CC1120_ADC_TEST, .name = "ADC_TEST" },
937 { .addr = CC1120_DVC_TEST, .name = "DVC_TEST" },
938 { .addr = CC1120_ATEST, .name = "ATEST" },
939 { .addr = CC1120_ATEST_LVDS, .name = "ATEST_LVDS" },
940 { .addr = CC1120_ATEST_MODE, .name = "ATEST_MODE" },
941 { .addr = CC1120_XOSC_TEST1, .name = "XOSC_TEST1" },
942 { .addr = CC1120_XOSC_TEST0, .name = "XOSC_TEST0" },
943 { .addr = CC1120_RXFIRST, .name = "RXFIRST" },
944 { .addr = CC1120_TXFIRST, .name = "TXFIRST" },
945 { .addr = CC1120_RXLAST, .name = "RXLAST" },
946 { .addr = CC1120_TXLAST, .name = "TXLAST" },
947 { .addr = CC1120_NUM_TXBYTES, .name = "NUM_TXBYTES" },
948 { .addr = CC1120_NUM_RXBYTES, .name = "NUM_RXBYTES" },
949 { .addr = CC1120_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
950 { .addr = CC1120_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
953 #define AO_NUM_CC1120_REG (sizeof ao_cc1120_reg / sizeof ao_cc1120_reg[0])
955 static void ao_radio_show(void) {
956 uint8_t status = ao_radio_status();
960 status = ao_radio_status();
961 printf ("Status: %02x\n", status);
962 printf ("CHIP_RDY: %d\n", (status >> CC1120_STATUS_CHIP_RDY) & 1);
963 printf ("STATE: %s\n", cc1120_state_name[(status >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK]);
964 printf ("MARC: %02x\n", ao_radio_marc_status());
966 for (i = 0; i < AO_NUM_CC1120_REG; i++)
967 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name);
971 static void ao_radio_beep(void) {
972 ao_radio_rdf(RDF_PACKET_LEN);
975 static void ao_radio_packet(void) {
976 static const uint8_t packet[] = {
978 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
979 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
980 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
981 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
987 ao_radio_send(packet, sizeof (packet));
996 if (ao_radio_recv(bytes, 34)) {
997 if (bytes[33] & 0x80)
1001 printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32]));
1002 for (b = 0; b < 32; b++)
1003 printf (" %02x", bytes[b]);
1010 static const struct ao_cmds ao_radio_cmds[] = {
1011 { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
1013 { ao_radio_show, "R\0Show CC1120 status" },
1014 { ao_radio_beep, "b\0Emit an RDF beacon" },
1015 { ao_radio_packet, "p\0Send a test packet" },
1016 { ao_radio_test_recv, "q\0Recv a test packet" },
1026 ao_radio_configured = 0;
1027 ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN));
1029 AO_CC1120_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN));
1030 for (i = 0; i < 10000; i++) {
1031 if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0)
1034 AO_CC1120_SPI_CS_PORT->bsrr = (1 << AO_CC1120_SPI_CS_PIN);
1036 ao_panic(AO_PANIC_SELF_TEST_CC1120);
1038 /* Enable the EXTI interrupt for the appropriate pin */
1039 ao_enable_port(AO_CC1120_INT_PORT);
1040 ao_exti_setup(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1041 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
1044 ao_cmd_register(&ao_radio_cmds[0]);