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>
23 uint8_t ao_radio_wake;
24 uint8_t ao_radio_mutex;
25 uint8_t ao_radio_abort;
27 #define CC1120_DEBUG 1
28 #define CC1120_TRACE 0
31 #define fec_dump_bytes(b,l,n) ao_fec_dump_bytes(b,l,n)
33 #define fec_dump_bytes(b,l,n)
36 uint32_t ao_radio_cal = 0x6ca333;
40 #define ao_radio_select() ao_spi_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS)
41 #define ao_radio_deselect() ao_spi_put_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS)
42 #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1120_SPI_BUS)
43 #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1120_SPI_BUS)
44 #define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1120_SPI_BUS)
45 #define ao_radio_duplex(o,i,l) ao_spi_duplex((o), (i), (l), AO_CC1120_SPI_BUS)
48 ao_radio_reg_read(uint16_t addr)
54 printf("\t\tao_radio_reg_read (%04x): ", addr); flush();
56 if (CC1120_IS_EXTENDED(addr)) {
57 data[0] = ((1 << CC1120_READ) |
63 data[0] = ((1 << CC1120_READ) |
69 ao_radio_spi_send(data, d);
70 ao_radio_spi_recv(data, 1);
73 printf (" %02x\n", data[0]);
79 ao_radio_reg_write(uint16_t addr, uint8_t value)
85 printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value);
87 if (CC1120_IS_EXTENDED(addr)) {
88 data[0] = ((0 << CC1120_READ) |
94 data[0] = ((0 << CC1120_READ) |
101 ao_radio_spi_send(data, d+1);
106 ao_radio_strobe(uint8_t addr)
111 printf("\t\tao_radio_strobe (%02x): ", addr); flush();
114 ao_radio_duplex(&addr, &in, 1);
117 printf("%02x\n", in); flush();
123 ao_radio_fifo_read(uint8_t *data, uint8_t len)
125 uint8_t addr = ((1 << CC1120_READ) |
126 (1 << CC1120_BURST) |
131 ao_radio_duplex(&addr, &status, 1);
132 ao_radio_spi_recv(data, len);
138 ao_radio_fifo_write(uint8_t *data, uint8_t len)
140 uint8_t addr = ((0 << CC1120_READ) |
141 (1 << CC1120_BURST) |
146 ao_radio_duplex(&addr, &status, 1);
147 ao_radio_spi_send(data, len);
153 ao_radio_fifo_write_fixed(uint8_t data, uint8_t len)
155 uint8_t addr = ((0 << CC1120_READ) |
156 (1 << CC1120_BURST) |
161 ao_radio_duplex(&addr, &status, 1);
162 ao_radio_spi_send_fixed(data, len);
168 ao_radio_status(void)
170 return ao_radio_strobe (CC1120_SNOP);
174 ao_radio_recv_abort(void)
177 ao_wakeup(&ao_radio_wake);
180 #define ao_radio_rdf_value 0x55
183 * RDF deviation is 5kHz
185 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
187 * 32e6Hz / (2 ** 24) * (256 + 71) * (2 ** 3) = 4989
192 #define RDF_PACKET_LEN 50
195 * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
197 * (2**20 - DATARATE_M) * 2 ** DATARATE_E
198 * Rdata = -------------------------------------- * fosc
201 * DATARATE_M = 511705
204 * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
206 #define RDF_DRATE_E 5
207 #define RDF_DRATE_M 25166
208 #define RDF_PACKET_LEN 50
210 static const uint16_t rdf_setup[] = {
211 CC1120_DEVIATION_M, RDF_DEV_M,
212 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
213 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
214 (RDF_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
215 CC1120_DRATE2, ((RDF_DRATE_E << CC1120_DRATE2_DATARATE_E) |
216 (((RDF_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
217 CC1120_DRATE1, ((RDF_DRATE_M >> 8) & 0xff),
218 CC1120_DRATE0, ((RDF_DRATE_M >> 0) & 0xff),
219 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
220 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
221 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
222 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
223 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
224 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
225 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
226 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
227 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
228 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
229 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
233 ao_radio_marc_status(void)
235 return ao_radio_reg_read(CC1120_MARC_STATUS1);
239 ao_radio_tx_done(void)
241 return ao_radio_marc_status() == CC1120_MARC_STATUS1_TX_FINISHED;
245 ao_radio_rx_done(void)
247 return ao_radio_marc_status() == CC1120_MARC_STATUS1_RX_FINISHED;
251 ao_radio_start_tx(void)
253 ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG);
254 ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
255 ao_radio_strobe(CC1120_STX);
259 ao_radio_rdf(uint8_t len)
265 for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2)
266 ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]);
268 ao_radio_fifo_write_fixed(ao_radio_rdf_value, len);
273 while (!ao_radio_wake && !ao_radio_abort)
274 ao_sleep(&ao_radio_wake);
277 if (!ao_radio_tx_done())
279 ao_radio_set_packet();
284 ao_radio_rdf_abort(void)
287 ao_wakeup(&ao_radio_wake);
296 if (ao_cmd_lex_c != '\n') {
298 mode = (uint8_t) ao_cmd_lex_u32;
301 if ((mode & 2) && !radio_on) {
303 ao_monitor_disable();
306 ao_packet_slave_stop();
309 ao_radio_strobe(CC1120_STX);
312 for (t = 0; t < 10; t++) {
313 printf ("status: %02x\n", ao_radio_status());
314 ao_delay(AO_MS_TO_TICKS(100));
321 printf ("Hit a character to stop..."); flush();
325 if ((mode & 1) && radio_on) {
336 ao_radio_send(void *d, uint8_t size)
339 uint8_t prepare[size + AO_FEC_PREPARE_EXTRA];
341 uint8_t encode[sizeof(prepare) * 2];
343 uint8_t interleave[sizeof(encode)];
344 uint8_t interleave_len;
346 fec_dump_bytes(d, size, "Input");
348 prepare_len = ao_fec_prepare(d, size, prepare);
349 fec_dump_bytes(prepare, prepare_len, "Prepare");
351 ao_fec_whiten(prepare, prepare_len, prepare);
352 fec_dump_bytes(prepare, prepare_len, "Whiten");
354 encode_len = ao_fec_encode(prepare, prepare_len, encode);
355 fec_dump_bytes(encode, encode_len, "Encode");
357 interleave_len = ao_fec_interleave(encode, encode_len, interleave);
358 fec_dump_bytes(interleave, interleave_len, "Interleave");
360 ao_radio_get(interleave_len);
361 ao_radio_fifo_write(interleave, interleave_len);
368 while (!ao_radio_wake && !ao_radio_abort)
369 ao_sleep(&ao_radio_wake);
371 if (!ao_radio_tx_done())
377 ao_radio_recv(__xdata void *d, uint8_t size)
379 uint8_t marc_status = CC1120_MARC_STATUS1_NO_FAILURE;
381 /* configure interrupt pin */
384 ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
385 ao_radio_strobe(CC1120_SRX);
392 marc_status = ao_radio_marc_status();
393 if (marc_status != CC1120_MARC_STATUS1_NO_FAILURE)
397 ao_sleep(&ao_radio_wake);
400 if (marc_status != CC1120_MARC_STATUS1_RX_FINISHED)
401 ao_radio_fifo_read(d, size);
403 return marc_status == CC1120_MARC_STATUS1_RX_FINISHED;
407 * Packet deviation is 20.5kHz
409 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
411 * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz
414 #define PACKET_DEV_E 5
415 #define PACKET_DEV_M 80
418 * For our packet data, set the symbol rate to 38360 Baud
420 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
421 * Rdata = -------------------------------------- * fosc
425 * DATARATE_M = 239914
428 #define PACKET_DRATE_E 9
429 #define PACKET_DRATE_M 239914
431 static const uint16_t packet_setup[] = {
432 CC1120_DEVIATION_M, PACKET_DEV_M,
433 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
434 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
435 (PACKET_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
436 CC1120_DRATE2, ((PACKET_DRATE_E << CC1120_DRATE2_DATARATE_E) |
437 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
438 CC1120_DRATE1, ((PACKET_DRATE_M >> 8) & 0xff),
439 CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff),
440 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
441 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
442 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
443 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
444 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
445 (1 << CC1120_PKT_CFG1_APPEND_STATUS)),
446 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
447 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
448 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
449 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
450 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
454 ao_radio_set_packet(void)
458 for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2)
459 ao_radio_reg_write(packet_setup[i], packet_setup[i+1]);
466 uint8_t state = ao_radio_strobe(CC1120_SIDLE);
467 if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_IDLE)
470 ao_radio_strobe(CC1120_SFTX);
471 ao_radio_strobe(CC1120_SFRX);
474 static const uint16_t radio_setup[] = {
475 #include "ao_cc1120_CC1120.h"
478 static uint8_t ao_radio_configured = 0;
483 ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
485 ao_wakeup(&ao_radio_wake);
493 ao_radio_strobe(CC1120_SRES);
495 for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2)
496 ao_radio_reg_write(radio_setup[i], radio_setup[i+1]);
498 ao_radio_set_packet();
502 ao_radio_configured = 1;
506 ao_radio_get(uint8_t len)
508 ao_mutex_get(&ao_radio_mutex);
509 if (!ao_radio_configured)
511 ao_radio_reg_write(CC1120_FREQ2, ao_config.radio_setting >> 16);
512 ao_radio_reg_write(CC1120_FREQ1, ao_config.radio_setting >> 8);
513 ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting);
514 ao_radio_reg_write(CC1120_PKT_LEN, len);
518 static char *cc1120_state_name[] = {
519 [CC1120_STATUS_STATE_IDLE] = "IDLE",
520 [CC1120_STATUS_STATE_RX] = "RX",
521 [CC1120_STATUS_STATE_TX] = "TX",
522 [CC1120_STATUS_STATE_FSTXON] = "FSTXON",
523 [CC1120_STATUS_STATE_CALIBRATE] = "CALIBRATE",
524 [CC1120_STATUS_STATE_SETTLING] = "SETTLING",
525 [CC1120_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
526 [CC1120_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
529 struct ao_cc1120_reg {
534 const static struct ao_cc1120_reg ao_cc1120_reg[] = {
535 { .addr = CC1120_IOCFG3, .name = "IOCFG3" },
536 { .addr = CC1120_IOCFG2, .name = "IOCFG2" },
537 { .addr = CC1120_IOCFG1, .name = "IOCFG1" },
538 { .addr = CC1120_IOCFG0, .name = "IOCFG0" },
539 { .addr = CC1120_SYNC3, .name = "SYNC3" },
540 { .addr = CC1120_SYNC2, .name = "SYNC2" },
541 { .addr = CC1120_SYNC1, .name = "SYNC1" },
542 { .addr = CC1120_SYNC0, .name = "SYNC0" },
543 { .addr = CC1120_SYNC_CFG1, .name = "SYNC_CFG1" },
544 { .addr = CC1120_SYNC_CFG0, .name = "SYNC_CFG0" },
545 { .addr = CC1120_DEVIATION_M, .name = "DEVIATION_M" },
546 { .addr = CC1120_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
547 { .addr = CC1120_DCFILT_CFG, .name = "DCFILT_CFG" },
548 { .addr = CC1120_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
549 { .addr = CC1120_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
550 { .addr = CC1120_FREQ_IF_CFG, .name = "FREQ_IF_CFG" },
551 { .addr = CC1120_IQIC, .name = "IQIC" },
552 { .addr = CC1120_CHAN_BW, .name = "CHAN_BW" },
553 { .addr = CC1120_MDMCFG1, .name = "MDMCFG1" },
554 { .addr = CC1120_MDMCFG0, .name = "MDMCFG0" },
555 { .addr = CC1120_DRATE2, .name = "DRATE2" },
556 { .addr = CC1120_DRATE1, .name = "DRATE1" },
557 { .addr = CC1120_DRATE0, .name = "DRATE0" },
558 { .addr = CC1120_AGC_REF, .name = "AGC_REF" },
559 { .addr = CC1120_AGC_CS_THR, .name = "AGC_CS_THR" },
560 { .addr = CC1120_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
561 { .addr = CC1120_AGC_CFG3, .name = "AGC_CFG3" },
562 { .addr = CC1120_AGC_CFG2, .name = "AGC_CFG2" },
563 { .addr = CC1120_AGC_CFG1, .name = "AGC_CFG1" },
564 { .addr = CC1120_AGC_CFG0, .name = "AGC_CFG0" },
565 { .addr = CC1120_FIFO_CFG, .name = "FIFO_CFG" },
566 { .addr = CC1120_DEV_ADDR, .name = "DEV_ADDR" },
567 { .addr = CC1120_SETTLING_CFG, .name = "SETTLING_CFG" },
568 { .addr = CC1120_FS_CFG, .name = "FS_CFG" },
569 { .addr = CC1120_WOR_CFG1, .name = "WOR_CFG1" },
570 { .addr = CC1120_WOR_CFG0, .name = "WOR_CFG0" },
571 { .addr = CC1120_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
572 { .addr = CC1120_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
573 { .addr = CC1120_PKT_CFG2, .name = "PKT_CFG2" },
574 { .addr = CC1120_PKT_CFG1, .name = "PKT_CFG1" },
575 { .addr = CC1120_PKT_CFG0, .name = "PKT_CFG0" },
576 { .addr = CC1120_RFEND_CFG1, .name = "RFEND_CFG1" },
577 { .addr = CC1120_RFEND_CFG0, .name = "RFEND_CFG0" },
578 { .addr = CC1120_PA_CFG2, .name = "PA_CFG2" },
579 { .addr = CC1120_PA_CFG1, .name = "PA_CFG1" },
580 { .addr = CC1120_PA_CFG0, .name = "PA_CFG0" },
581 { .addr = CC1120_PKT_LEN, .name = "PKT_LEN" },
582 { .addr = CC1120_IF_MIX_CFG, .name = "IF_MIX_CFG" },
583 { .addr = CC1120_FREQOFF_CFG, .name = "FREQOFF_CFG" },
584 { .addr = CC1120_TOC_CFG, .name = "TOC_CFG" },
585 { .addr = CC1120_MARC_SPARE, .name = "MARC_SPARE" },
586 { .addr = CC1120_ECG_CFG, .name = "ECG_CFG" },
587 { .addr = CC1120_SOFT_TX_DATA_CFG, .name = "SOFT_TX_DATA_CFG" },
588 { .addr = CC1120_EXT_CTRL, .name = "EXT_CTRL" },
589 { .addr = CC1120_RCCAL_FINE, .name = "RCCAL_FINE" },
590 { .addr = CC1120_RCCAL_COARSE, .name = "RCCAL_COARSE" },
591 { .addr = CC1120_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
592 { .addr = CC1120_FREQOFF1, .name = "FREQOFF1" },
593 { .addr = CC1120_FREQOFF0, .name = "FREQOFF0" },
594 { .addr = CC1120_FREQ2, .name = "FREQ2" },
595 { .addr = CC1120_FREQ1, .name = "FREQ1" },
596 { .addr = CC1120_FREQ0, .name = "FREQ0" },
597 { .addr = CC1120_IF_ADC2, .name = "IF_ADC2" },
598 { .addr = CC1120_IF_ADC1, .name = "IF_ADC1" },
599 { .addr = CC1120_IF_ADC0, .name = "IF_ADC0" },
600 { .addr = CC1120_FS_DIG1, .name = "FS_DIG1" },
601 { .addr = CC1120_FS_DIG0, .name = "FS_DIG0" },
602 { .addr = CC1120_FS_CAL3, .name = "FS_CAL3" },
603 { .addr = CC1120_FS_CAL2, .name = "FS_CAL2" },
604 { .addr = CC1120_FS_CAL1, .name = "FS_CAL1" },
605 { .addr = CC1120_FS_CAL0, .name = "FS_CAL0" },
606 { .addr = CC1120_FS_CHP, .name = "FS_CHP" },
607 { .addr = CC1120_FS_DIVTWO, .name = "FS_DIVTWO" },
608 { .addr = CC1120_FS_DSM1, .name = "FS_DSM1" },
609 { .addr = CC1120_FS_DSM0, .name = "FS_DSM0" },
610 { .addr = CC1120_FS_DVC1, .name = "FS_DVC1" },
611 { .addr = CC1120_FS_DVC0, .name = "FS_DVC0" },
612 { .addr = CC1120_FS_LBI, .name = "FS_LBI" },
613 { .addr = CC1120_FS_PFD, .name = "FS_PFD" },
614 { .addr = CC1120_FS_PRE, .name = "FS_PRE" },
615 { .addr = CC1120_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
616 { .addr = CC1120_FS_SPARE, .name = "FS_SPARE" },
617 { .addr = CC1120_FS_VCO4, .name = "FS_VCO4" },
618 { .addr = CC1120_FS_VCO3, .name = "FS_VCO3" },
619 { .addr = CC1120_FS_VCO2, .name = "FS_VCO2" },
620 { .addr = CC1120_FS_VCO1, .name = "FS_VCO1" },
621 { .addr = CC1120_FS_VCO0, .name = "FS_VCO0" },
622 { .addr = CC1120_GBIAS6, .name = "GBIAS6" },
623 { .addr = CC1120_GBIAS5, .name = "GBIAS5" },
624 { .addr = CC1120_GBIAS4, .name = "GBIAS4" },
625 { .addr = CC1120_GBIAS3, .name = "GBIAS3" },
626 { .addr = CC1120_GBIAS2, .name = "GBIAS2" },
627 { .addr = CC1120_GBIAS1, .name = "GBIAS1" },
628 { .addr = CC1120_GBIAS0, .name = "GBIAS0" },
629 { .addr = CC1120_IFAMP, .name = "IFAMP" },
630 { .addr = CC1120_LNA, .name = "LNA" },
631 { .addr = CC1120_RXMIX, .name = "RXMIX" },
632 { .addr = CC1120_XOSC5, .name = "XOSC5" },
633 { .addr = CC1120_XOSC4, .name = "XOSC4" },
634 { .addr = CC1120_XOSC3, .name = "XOSC3" },
635 { .addr = CC1120_XOSC2, .name = "XOSC2" },
636 { .addr = CC1120_XOSC1, .name = "XOSC1" },
637 { .addr = CC1120_XOSC0, .name = "XOSC0" },
638 { .addr = CC1120_ANALOG_SPARE, .name = "ANALOG_SPARE" },
639 { .addr = CC1120_PA_CFG3, .name = "PA_CFG3" },
640 { .addr = CC1120_WOR_TIME1, .name = "WOR_TIME1" },
641 { .addr = CC1120_WOR_TIME0, .name = "WOR_TIME0" },
642 { .addr = CC1120_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
643 { .addr = CC1120_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
644 { .addr = CC1120_BIST, .name = "BIST" },
645 { .addr = CC1120_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
646 { .addr = CC1120_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
647 { .addr = CC1120_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
648 { .addr = CC1120_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
649 { .addr = CC1120_IQIE_I1, .name = "IQIE_I1" },
650 { .addr = CC1120_IQIE_I0, .name = "IQIE_I0" },
651 { .addr = CC1120_IQIE_Q1, .name = "IQIE_Q1" },
652 { .addr = CC1120_IQIE_Q0, .name = "IQIE_Q0" },
653 { .addr = CC1120_RSSI1, .name = "RSSI1" },
654 { .addr = CC1120_RSSI0, .name = "RSSI0" },
655 { .addr = CC1120_MARCSTATE, .name = "MARCSTATE" },
656 { .addr = CC1120_LQI_VAL, .name = "LQI_VAL" },
657 { .addr = CC1120_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
658 { .addr = CC1120_DEM_STATUS, .name = "DEM_STATUS" },
659 { .addr = CC1120_FREQOFF_EST1, .name = "FREQOFF_EST1" },
660 { .addr = CC1120_FREQOFF_EST0, .name = "FREQOFF_EST0" },
661 { .addr = CC1120_AGC_GAIN3, .name = "AGC_GAIN3" },
662 { .addr = CC1120_AGC_GAIN2, .name = "AGC_GAIN2" },
663 { .addr = CC1120_AGC_GAIN1, .name = "AGC_GAIN1" },
664 { .addr = CC1120_AGC_GAIN0, .name = "AGC_GAIN0" },
665 { .addr = CC1120_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
666 { .addr = CC1120_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
667 { .addr = CC1120_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
668 { .addr = CC1120_RNDGEN, .name = "RNDGEN" },
669 { .addr = CC1120_MAGN2, .name = "MAGN2" },
670 { .addr = CC1120_MAGN1, .name = "MAGN1" },
671 { .addr = CC1120_MAGN0, .name = "MAGN0" },
672 { .addr = CC1120_ANG1, .name = "ANG1" },
673 { .addr = CC1120_ANG0, .name = "ANG0" },
674 { .addr = CC1120_CHFILT_I2, .name = "CHFILT_I2" },
675 { .addr = CC1120_CHFILT_I1, .name = "CHFILT_I1" },
676 { .addr = CC1120_CHFILT_I0, .name = "CHFILT_I0" },
677 { .addr = CC1120_CHFILT_Q2, .name = "CHFILT_Q2" },
678 { .addr = CC1120_CHFILT_Q1, .name = "CHFILT_Q1" },
679 { .addr = CC1120_CHFILT_Q0, .name = "CHFILT_Q0" },
680 { .addr = CC1120_GPIO_STATUS, .name = "GPIO_STATUS" },
681 { .addr = CC1120_FSCAL_CTRL, .name = "FSCAL_CTRL" },
682 { .addr = CC1120_PHASE_ADJUST, .name = "PHASE_ADJUST" },
683 { .addr = CC1120_PARTNUMBER, .name = "PARTNUMBER" },
684 { .addr = CC1120_PARTVERSION, .name = "PARTVERSION" },
685 { .addr = CC1120_SERIAL_STATUS, .name = "SERIAL_STATUS" },
686 { .addr = CC1120_RX_STATUS, .name = "RX_STATUS" },
687 { .addr = CC1120_TX_STATUS, .name = "TX_STATUS" },
688 { .addr = CC1120_MARC_STATUS1, .name = "MARC_STATUS1" },
689 { .addr = CC1120_MARC_STATUS0, .name = "MARC_STATUS0" },
690 { .addr = CC1120_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
691 { .addr = CC1120_FSRF_TEST, .name = "FSRF_TEST" },
692 { .addr = CC1120_PRE_TEST, .name = "PRE_TEST" },
693 { .addr = CC1120_PRE_OVR, .name = "PRE_OVR" },
694 { .addr = CC1120_ADC_TEST, .name = "ADC_TEST" },
695 { .addr = CC1120_DVC_TEST, .name = "DVC_TEST" },
696 { .addr = CC1120_ATEST, .name = "ATEST" },
697 { .addr = CC1120_ATEST_LVDS, .name = "ATEST_LVDS" },
698 { .addr = CC1120_ATEST_MODE, .name = "ATEST_MODE" },
699 { .addr = CC1120_XOSC_TEST1, .name = "XOSC_TEST1" },
700 { .addr = CC1120_XOSC_TEST0, .name = "XOSC_TEST0" },
701 { .addr = CC1120_RXFIRST, .name = "RXFIRST" },
702 { .addr = CC1120_TXFIRST, .name = "TXFIRST" },
703 { .addr = CC1120_RXLAST, .name = "RXLAST" },
704 { .addr = CC1120_TXLAST, .name = "TXLAST" },
705 { .addr = CC1120_NUM_TXBYTES, .name = "NUM_TXBYTES" },
706 { .addr = CC1120_NUM_RXBYTES, .name = "NUM_RXBYTES" },
707 { .addr = CC1120_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
708 { .addr = CC1120_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
711 #define AO_NUM_CC1120_REG (sizeof ao_cc1120_reg / sizeof ao_cc1120_reg[0])
713 static void ao_radio_show(void) {
714 uint8_t status = ao_radio_status();
718 status = ao_radio_status();
719 printf ("Status: %02x\n", status);
720 printf ("CHIP_RDY: %d\n", (status >> CC1120_STATUS_CHIP_RDY) & 1);
721 printf ("STATE: %s\n", cc1120_state_name[(status >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK]);
722 printf ("MARC: %02x\n", ao_radio_marc_status());
724 for (i = 0; i < AO_NUM_CC1120_REG; i++)
725 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name);
729 static void ao_radio_beep(void) {
730 ao_radio_rdf(RDF_PACKET_LEN);
733 static void ao_radio_packet(void) {
734 static uint8_t packet[] = {
736 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
737 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
738 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
739 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
745 ao_radio_send(packet, sizeof (packet));
750 static const struct ao_cmds ao_radio_cmds[] = {
751 { ao_radio_test, "C <1 start, 0 stop, none both>\0Radio carrier test" },
753 { ao_radio_show, "R\0Show CC1120 status" },
754 { ao_radio_beep, "b\0Emit an RDF beacon" },
755 { ao_radio_packet, "p\0Send a test packet" },
765 ao_radio_configured = 0;
766 ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN));
768 AO_CC1120_SPI_CS_PORT.bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN));
769 for (i = 0; i < 10000; i++) {
770 if ((SPI_2_GPIO.idr & (1 << SPI_2_MISO)) == 0)
773 AO_CC1120_SPI_CS_PORT.bsrr = (1 << AO_CC1120_SPI_CS_PIN);
775 ao_panic(AO_PANIC_SELF_TEST);
777 /* Enable the EXTI interrupt for the appropriate pin */
778 ao_enable_port(AO_CC1120_INT_PORT);
779 ao_exti_setup(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_EXTI_MODE_FALLING, ao_radio_isr);
781 ao_cmd_register(&ao_radio_cmds[0]);