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