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 static uint8_t ao_radio_mutex;
29 static uint8_t ao_radio_wake; /* radio ready. Also used as sleep address */
30 static uint8_t ao_radio_abort; /* radio operation should abort */
31 static uint8_t ao_radio_mcu_wake; /* MARC status change */
32 static uint8_t ao_radio_marc_status; /* Last read MARC status value */
33 static uint8_t ao_radio_tx_finished; /* MARC status indicates TX finished */
35 #define CC1120_DEBUG AO_FEC_DEBUG
36 #define CC1120_TRACE 0
38 extern const uint32_t ao_radio_cal;
42 #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_4MHz)
43 #define ao_radio_deselect() ao_spi_put_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS)
44 #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1120_SPI_BUS)
45 #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1120_SPI_BUS)
46 #define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1120_SPI_BUS)
47 #define ao_radio_duplex(o,i,l) ao_spi_duplex((o), (i), (l), AO_CC1120_SPI_BUS)
50 ao_radio_reg_read(uint16_t addr)
56 printf("\t\tao_radio_reg_read (%04x): ", addr); flush();
58 if (CC1120_IS_EXTENDED(addr)) {
59 data[0] = ((1 << CC1120_READ) |
65 data[0] = ((1 << CC1120_READ) |
71 ao_radio_spi_send(data, d);
72 ao_radio_spi_recv(data, 1);
75 printf (" %02x\n", data[0]);
81 ao_radio_reg_write(uint16_t addr, uint8_t value)
87 printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value);
89 if (CC1120_IS_EXTENDED(addr)) {
90 data[0] = ((0 << CC1120_READ) |
96 data[0] = ((0 << CC1120_READ) |
103 ao_radio_spi_send(data, d+1);
108 ao_radio_burst_read_start (uint16_t addr)
113 if (CC1120_IS_EXTENDED(addr)) {
114 data[0] = ((1 << CC1120_READ) |
115 (1 << CC1120_BURST) |
120 data[0] = ((1 << CC1120_READ) |
121 (1 << CC1120_BURST) |
126 ao_radio_spi_send(data, d);
130 ao_radio_burst_read_stop (void)
137 ao_radio_strobe(uint8_t addr)
142 printf("\t\tao_radio_strobe (%02x): ", addr); flush();
145 ao_radio_duplex(&addr, &in, 1);
148 printf("%02x\n", in); flush();
154 ao_radio_fifo_read(uint8_t *data, uint8_t len)
156 uint8_t addr = ((1 << CC1120_READ) |
157 (1 << CC1120_BURST) |
162 ao_radio_duplex(&addr, &status, 1);
163 ao_radio_spi_recv(data, len);
169 ao_radio_fifo_write_start(void)
171 uint8_t addr = ((0 << CC1120_READ) |
172 (1 << CC1120_BURST) |
177 ao_radio_duplex(&addr, &status, 1);
181 static inline uint8_t ao_radio_fifo_write_stop(uint8_t status) {
187 ao_radio_fifo_write(uint8_t *data, uint8_t len)
189 uint8_t status = ao_radio_fifo_write_start();
190 ao_radio_spi_send(data, len);
191 return ao_radio_fifo_write_stop(status);
195 ao_radio_fifo_write_fixed(uint8_t data, uint8_t len)
197 uint8_t status = ao_radio_fifo_write_start();
198 ao_radio_spi_send_fixed(data, len);
199 return ao_radio_fifo_write_stop(status);
203 ao_radio_tx_fifo_space(void)
205 return CC1120_FIFO_SIZE - ao_radio_reg_read(CC1120_NUM_TXBYTES);
209 ao_radio_status(void)
211 return ao_radio_strobe (CC1120_SNOP);
215 ao_radio_recv_abort(void)
218 ao_wakeup(&ao_radio_wake);
221 #define ao_radio_rdf_value 0x55
224 ao_radio_get_marc_status(void)
226 return ao_radio_reg_read(CC1120_MARC_STATUS1);
230 ao_radio_mcu_wakeup_isr(void)
232 ao_radio_mcu_wake = 1;
233 ao_wakeup(&ao_radio_wake);
238 ao_radio_check_marc_status(void)
240 ao_radio_mcu_wake = 0;
241 ao_radio_marc_status = ao_radio_get_marc_status();
243 /* Anyt other than 'tx/rx finished' means an error occurred */
244 if (ao_radio_marc_status & ~(CC1120_MARC_STATUS1_TX_FINISHED|CC1120_MARC_STATUS1_RX_FINISHED))
246 if (ao_radio_marc_status & (CC1120_MARC_STATUS1_TX_FINISHED))
247 ao_radio_tx_finished = 1;
253 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
255 ao_wakeup(&ao_radio_wake);
259 ao_radio_start_tx(void)
261 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr);
262 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
263 ao_exti_enable(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN);
264 ao_radio_tx_finished = 0;
265 ao_radio_strobe(CC1120_STX);
272 uint8_t state = ao_radio_strobe(CC1120_SIDLE);
273 if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_IDLE)
276 /* Flush any pending TX bytes */
277 ao_radio_strobe(CC1120_SFTX);
281 * Packet deviation is 20.5kHz
283 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
285 * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz
288 #define PACKET_DEV_E 5
289 #define PACKET_DEV_M 80
292 * For our packet data, set the symbol rate to 38400 Baud
294 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
295 * Rdata = -------------------------------------- * fosc
299 * DATARATE_M = 239914
302 #define PACKET_DRATE_E 9
303 #define PACKET_DRATE_M 239914
305 static const uint16_t packet_setup[] = {
306 CC1120_DEVIATION_M, PACKET_DEV_M,
307 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
308 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
309 (PACKET_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
310 CC1120_DRATE2, ((PACKET_DRATE_E << CC1120_DRATE2_DATARATE_E) |
311 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
312 CC1120_DRATE1, ((PACKET_DRATE_M >> 8) & 0xff),
313 CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff),
314 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
315 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
316 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
317 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
318 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
319 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
320 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
321 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
322 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
323 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
324 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
325 AO_CC1120_MARC_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP,
328 static const uint16_t packet_tx_setup[] = {
329 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
330 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
331 AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG,
334 static const uint16_t packet_rx_setup[] = {
335 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
336 (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT)),
337 AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT,
341 * RDF deviation is 5kHz
343 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
345 * 32e6Hz / (2 ** 24) * (256 + 71) * (2 ** 3) = 4989
350 #define RDF_PACKET_LEN 50
353 * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
355 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
356 * Rdata = -------------------------------------- * fosc
362 * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
364 #define RDF_DRATE_E 5
365 #define RDF_DRATE_M 25166
366 #define RDF_PACKET_LEN 50
368 static const uint16_t rdf_setup[] = {
369 CC1120_DEVIATION_M, RDF_DEV_M,
370 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
371 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
372 (RDF_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
373 CC1120_DRATE2, ((RDF_DRATE_E << CC1120_DRATE2_DATARATE_E) |
374 (((RDF_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
375 CC1120_DRATE1, ((RDF_DRATE_M >> 8) & 0xff),
376 CC1120_DRATE0, ((RDF_DRATE_M >> 0) & 0xff),
377 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
378 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
379 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
380 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
381 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
382 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
383 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
384 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
385 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
386 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
387 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
391 * APRS deviation is 5kHz
393 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
395 * 32e6Hz / (2 ** 24) * (256 + 71) * (2 ** 3) = 4989
399 #define APRS_DEV_M 71
400 #define APRS_PACKET_LEN 50
403 * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate)
405 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
406 * Rdata = -------------------------------------- * fosc
409 * DATARATE_M = 239914
412 * Rdata = 9599.998593330383301
415 #define APRS_DRATE_E 7
416 #define APRS_DRATE_M 239914
418 static const uint16_t aprs_setup[] = {
419 CC1120_DEVIATION_M, APRS_DEV_M,
420 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
421 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
422 (APRS_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
423 CC1120_DRATE2, ((APRS_DRATE_E << CC1120_DRATE2_DATARATE_E) |
424 (((APRS_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
425 CC1120_DRATE1, ((APRS_DRATE_M >> 8) & 0xff),
426 CC1120_DRATE0, ((APRS_DRATE_M >> 0) & 0xff),
427 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
428 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
429 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
430 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
431 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
432 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
435 #define AO_PKT_CFG0_INFINITE ((0 << CC1120_PKT_CFG0_RESERVED7) | \
436 (CC1120_PKT_CFG0_LENGTH_CONFIG_INFINITE << CC1120_PKT_CFG0_LENGTH_CONFIG) | \
437 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | \
438 (0 << CC1120_PKT_CFG0_UART_MODE_EN) | \
439 (0 << CC1120_PKT_CFG0_UART_SWAP_EN))
441 #define AO_PKT_CFG0_FIXED ((0 << CC1120_PKT_CFG0_RESERVED7) | \
442 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) | \
443 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | \
444 (0 << CC1120_PKT_CFG0_UART_MODE_EN) | \
445 (0 << CC1120_PKT_CFG0_UART_SWAP_EN))
447 static uint16_t ao_radio_mode;
449 #define AO_RADIO_MODE_BITS_PACKET 1
450 #define AO_RADIO_MODE_BITS_PACKET_TX 2
451 #define AO_RADIO_MODE_BITS_TX_BUF 4
452 #define AO_RADIO_MODE_BITS_TX_FINISH 8
453 #define AO_RADIO_MODE_BITS_PACKET_RX 16
454 #define AO_RADIO_MODE_BITS_RDF 32
455 #define AO_RADIO_MODE_BITS_APRS 64
456 #define AO_RADIO_MODE_BITS_INFINITE 128
457 #define AO_RADIO_MODE_BITS_FIXED 256
459 #define AO_RADIO_MODE_NONE 0
460 #define AO_RADIO_MODE_PACKET_TX_BUF (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_BUF)
461 #define AO_RADIO_MODE_PACKET_TX_FINISH (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_FINISH)
462 #define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_RX)
463 #define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_TX_FINISH)
464 #define AO_RADIO_MODE_APRS_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
465 #define AO_RADIO_MODE_APRS_LAST_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_BUF)
466 #define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
469 ao_radio_set_mode(uint16_t new_mode)
474 if (new_mode == ao_radio_mode)
477 changes = new_mode & (~ao_radio_mode);
478 if (changes & AO_RADIO_MODE_BITS_PACKET)
479 for (i = 0; i < sizeof (packet_setup) / sizeof (packet_setup[0]); i += 2)
480 ao_radio_reg_write(packet_setup[i], packet_setup[i+1]);
482 if (changes & AO_RADIO_MODE_BITS_PACKET_TX)
483 for (i = 0; i < sizeof (packet_tx_setup) / sizeof (packet_tx_setup[0]); i += 2)
484 ao_radio_reg_write(packet_tx_setup[i], packet_tx_setup[i+1]);
486 if (changes & AO_RADIO_MODE_BITS_TX_BUF)
487 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_TXFIFO_THR);
489 if (changes & AO_RADIO_MODE_BITS_TX_FINISH)
490 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG);
492 if (changes & AO_RADIO_MODE_BITS_PACKET_RX)
493 for (i = 0; i < sizeof (packet_rx_setup) / sizeof (packet_rx_setup[0]); i += 2)
494 ao_radio_reg_write(packet_rx_setup[i], packet_rx_setup[i+1]);
496 if (changes & AO_RADIO_MODE_BITS_RDF)
497 for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2)
498 ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]);
500 if (changes & AO_RADIO_MODE_BITS_APRS)
501 for (i = 0; i < sizeof (aprs_setup) / sizeof (aprs_setup[0]); i += 2)
502 ao_radio_reg_write(aprs_setup[i], aprs_setup[i+1]);
504 if (changes & AO_RADIO_MODE_BITS_INFINITE)
505 ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_INFINITE);
507 if (changes & AO_RADIO_MODE_BITS_FIXED)
508 ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_FIXED);
510 ao_radio_mode = new_mode;
513 static const uint16_t radio_setup[] = {
514 #include "ao_cc1120_CC1120.h"
517 static uint8_t ao_radio_configured = 0;
524 ao_radio_strobe(CC1120_SRES);
526 for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2)
527 ao_radio_reg_write(radio_setup[i], radio_setup[i+1]);
533 ao_radio_configured = 1;
537 ao_radio_set_len(uint8_t len)
539 static uint8_t last_len;
541 if (len != last_len) {
542 ao_radio_reg_write(CC1120_PKT_LEN, len);
548 ao_radio_get(uint8_t len)
550 static uint32_t last_radio_setting;
552 ao_mutex_get(&ao_radio_mutex);
553 if (!ao_radio_configured)
555 if (ao_config.radio_setting != last_radio_setting) {
556 ao_radio_reg_write(CC1120_FREQ2, ao_config.radio_setting >> 16);
557 ao_radio_reg_write(CC1120_FREQ1, ao_config.radio_setting >> 8);
558 ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting);
559 last_radio_setting = ao_config.radio_setting;
561 ao_radio_set_len(len);
564 #define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
567 ao_rdf_start(uint8_t len)
572 ao_radio_set_mode(AO_RADIO_MODE_RDF);
582 ao_arch_block_interrupts();
583 while (!ao_radio_wake && !ao_radio_abort && !ao_radio_mcu_wake)
584 ao_sleep(&ao_radio_wake);
585 ao_arch_release_interrupts();
586 if (ao_radio_mcu_wake)
587 ao_radio_check_marc_status();
596 ao_rdf_start(AO_RADIO_RDF_LEN);
598 ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN);
604 ao_radio_continuity(uint8_t c)
609 ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN);
611 status = ao_radio_fifo_write_start();
612 for (i = 0; i < 3; i++) {
613 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
615 ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN);
617 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN);
619 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
620 status = ao_radio_fifo_write_stop(status);
626 ao_radio_rdf_abort(void)
629 ao_wakeup(&ao_radio_wake);
633 ao_radio_test_cmd(void)
636 static uint8_t radio_on;
638 if (ao_cmd_lex_c != '\n') {
640 mode = (uint8_t) ao_cmd_lex_u32;
643 if ((mode & 2) && !radio_on) {
645 ao_monitor_disable();
648 ao_packet_slave_stop();
651 ao_radio_strobe(CC1120_STX);
654 for (t = 0; t < 10; t++) {
655 printf ("status: %02x\n", ao_radio_status());
656 ao_delay(AO_MS_TO_TICKS(100));
663 printf ("Hit a character to stop..."); flush();
667 if ((mode & 1) && radio_on) {
678 ao_radio_wait_isr(uint16_t timeout)
682 ao_arch_block_interrupts();
683 while (!ao_radio_wake && !ao_radio_mcu_wake && !ao_radio_abort)
684 if (ao_sleep(&ao_radio_wake))
686 ao_arch_release_interrupts();
689 if (ao_radio_mcu_wake)
690 ao_radio_check_marc_status();
694 ao_radio_wait_tx(uint8_t wait_fifo)
696 uint8_t fifo_space = 0;
699 ao_radio_wait_isr(0);
702 fifo_space = ao_radio_tx_fifo_space();
703 } while (!fifo_space && !ao_radio_abort);
707 static uint8_t tx_data[(AO_RADIO_MAX_SEND + 4) * 2];
710 ao_radio_send(const void *d, uint8_t size)
713 uint8_t *e = tx_data;
719 encode_len = ao_fec_encode(d, size, tx_data);
721 ao_radio_get(encode_len);
724 fifo_space = CC1120_FIFO_SIZE;
726 this_len = encode_len;
729 if (this_len > fifo_space) {
730 this_len = fifo_space;
731 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_BUF);
733 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_FINISH);
736 ao_radio_fifo_write(e, this_len);
738 encode_len -= this_len;
744 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
747 fifo_space = ao_radio_wait_tx(encode_len != 0);
748 if (ao_radio_abort) {
753 while (started && !ao_radio_abort && !ao_radio_tx_finished)
754 ao_radio_wait_isr(0);
758 #define AO_RADIO_LOTS 64
761 ao_radio_send_aprs(ao_radio_fill_func fill)
763 uint8_t buf[AO_RADIO_LOTS], *b;
771 fifo_space = CC1120_FIFO_SIZE;
773 cnt = (*fill)(buf, sizeof(buf));
780 /* At the last buffer, set the total length */
782 ao_radio_set_len(total & 0xff);
786 uint8_t this_len = cnt;
788 /* Wait for some space in the fifo */
789 while (!ao_radio_abort && (fifo_space = ao_radio_tx_fifo_space()) == 0) {
791 ao_radio_wait_isr(0);
795 if (this_len > fifo_space)
796 this_len = fifo_space;
802 ao_radio_set_mode(AO_RADIO_MODE_APRS_LAST_BUF);
804 ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
806 ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
808 ao_radio_fifo_write(b, this_len);
815 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
817 if (ao_radio_abort) {
821 /* Wait for the transmitter to go idle */
823 ao_radio_wait_isr(0);
828 static uint8_t rx_data[(AO_RADIO_MAX_RECV + 4) * 2 * 8];
829 static uint16_t rx_data_count;
830 static uint16_t rx_data_consumed;
831 static uint16_t rx_data_cur;
832 static uint8_t rx_ignore;
833 static uint8_t rx_waiting;
836 static uint32_t rx_start_tick, rx_packet_tick, rx_done_tick, rx_last_done_tick;
838 uint32_t ao_rx_start_tick, ao_rx_packet_tick, ao_rx_done_tick, ao_rx_last_done_tick;
840 #include <ao_profile.h>
844 ao_radio_rx_isr(void)
848 d = AO_CC1120_SPI.dr;
849 AO_CC1120_SPI.dr = 0;
850 if (rx_ignore == 0) {
851 if (rx_data_cur >= rx_data_count)
852 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
854 rx_data[rx_data_cur++] = d;
855 if (rx_waiting && rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) {
858 rx_packet_tick = ao_profile_tick();
859 if (rx_data_cur < rx_data_count)
863 ao_wakeup(&ao_radio_wake);
871 ao_radio_rx_wait(void)
874 if (ao_radio_mcu_wake)
875 ao_radio_check_marc_status();
876 ao_alarm(AO_MS_TO_TICKS(100));
877 ao_arch_block_interrupts();
879 while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&
883 if (ao_sleep(&ao_radio_wake))
887 ao_arch_release_interrupts();
889 } while (ao_radio_mcu_wake);
892 rx_data_consumed += AO_FEC_DECODE_BLOCK;
894 return rx_data_cur - rx_data_consumed;
896 return AO_FEC_DECODE_BLOCK;
900 ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout)
906 static int been_here = 0;
908 size -= 2; /* status bytes */
909 if (size > AO_RADIO_MAX_RECV) {
910 ao_delay(AO_SEC_TO_TICKS(1));
914 rx_start_tick = ao_profile_tick();
917 len = size + 2; /* CRC bytes */
918 len += 1 + ~(len & 1); /* 1 or two pad bytes */
919 len *= 2; /* 1/2 rate convolution */
920 rx_data_count = len * 8; /* bytes to bits */
922 rx_data_consumed = 0;
925 /* Must be set before changing the frequency; any abort
926 * after the frequency is set needs to terminate the read
927 * so that the registers can be reprogrammed
931 /* configure interrupt pin */
933 ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
936 ao_radio_mcu_wake = 0;
938 AO_CC1120_SPI.cr2 = 0;
941 (void) AO_CC1120_SPI.dr;
943 /* Have the radio signal when the preamble quality goes high */
944 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_PQT_REACHED);
945 ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
946 AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_HIGH);
947 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr);
948 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
949 ao_exti_enable(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN);
951 ao_radio_strobe(CC1120_SRX);
953 /* Wait for the preamble to appear */
954 ao_radio_wait_isr(timeout);
958 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT);
959 ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
960 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
962 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
963 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
965 ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
967 ret = ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait);
969 ao_radio_burst_read_stop();
972 ao_radio_strobe(CC1120_SIDLE);
974 /* Convert from 'real' rssi to cc1111-style values */
976 rssi = AO_RADIO_FROM_RSSI(ao_radio_reg_read(CC1120_RSSI1));
980 /* Store the received RSSI value; the crc-OK byte is already done */
982 ((uint8_t *) d)[size] = (uint8_t) rssi;
985 rx_last_done_tick = rx_done_tick;
986 rx_done_tick = ao_profile_tick();
988 ao_rx_start_tick = rx_start_tick;
989 ao_rx_packet_tick = rx_packet_tick;
990 ao_rx_done_tick = rx_done_tick;
991 ao_rx_last_done_tick = rx_last_done_tick;
999 static char *cc1120_state_name[] = {
1000 [CC1120_STATUS_STATE_IDLE] = "IDLE",
1001 [CC1120_STATUS_STATE_RX] = "RX",
1002 [CC1120_STATUS_STATE_TX] = "TX",
1003 [CC1120_STATUS_STATE_FSTXON] = "FSTXON",
1004 [CC1120_STATUS_STATE_CALIBRATE] = "CALIBRATE",
1005 [CC1120_STATUS_STATE_SETTLING] = "SETTLING",
1006 [CC1120_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
1007 [CC1120_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
1010 struct ao_cc1120_reg {
1015 const static struct ao_cc1120_reg ao_cc1120_reg[] = {
1016 { .addr = CC1120_IOCFG3, .name = "IOCFG3" },
1017 { .addr = CC1120_IOCFG2, .name = "IOCFG2" },
1018 { .addr = CC1120_IOCFG1, .name = "IOCFG1" },
1019 { .addr = CC1120_IOCFG0, .name = "IOCFG0" },
1020 { .addr = CC1120_SYNC3, .name = "SYNC3" },
1021 { .addr = CC1120_SYNC2, .name = "SYNC2" },
1022 { .addr = CC1120_SYNC1, .name = "SYNC1" },
1023 { .addr = CC1120_SYNC0, .name = "SYNC0" },
1024 { .addr = CC1120_SYNC_CFG1, .name = "SYNC_CFG1" },
1025 { .addr = CC1120_SYNC_CFG0, .name = "SYNC_CFG0" },
1026 { .addr = CC1120_DEVIATION_M, .name = "DEVIATION_M" },
1027 { .addr = CC1120_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
1028 { .addr = CC1120_DCFILT_CFG, .name = "DCFILT_CFG" },
1029 { .addr = CC1120_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
1030 { .addr = CC1120_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
1031 { .addr = CC1120_FREQ_IF_CFG, .name = "FREQ_IF_CFG" },
1032 { .addr = CC1120_IQIC, .name = "IQIC" },
1033 { .addr = CC1120_CHAN_BW, .name = "CHAN_BW" },
1034 { .addr = CC1120_MDMCFG1, .name = "MDMCFG1" },
1035 { .addr = CC1120_MDMCFG0, .name = "MDMCFG0" },
1036 { .addr = CC1120_DRATE2, .name = "DRATE2" },
1037 { .addr = CC1120_DRATE1, .name = "DRATE1" },
1038 { .addr = CC1120_DRATE0, .name = "DRATE0" },
1039 { .addr = CC1120_AGC_REF, .name = "AGC_REF" },
1040 { .addr = CC1120_AGC_CS_THR, .name = "AGC_CS_THR" },
1041 { .addr = CC1120_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
1042 { .addr = CC1120_AGC_CFG3, .name = "AGC_CFG3" },
1043 { .addr = CC1120_AGC_CFG2, .name = "AGC_CFG2" },
1044 { .addr = CC1120_AGC_CFG1, .name = "AGC_CFG1" },
1045 { .addr = CC1120_AGC_CFG0, .name = "AGC_CFG0" },
1046 { .addr = CC1120_FIFO_CFG, .name = "FIFO_CFG" },
1047 { .addr = CC1120_DEV_ADDR, .name = "DEV_ADDR" },
1048 { .addr = CC1120_SETTLING_CFG, .name = "SETTLING_CFG" },
1049 { .addr = CC1120_FS_CFG, .name = "FS_CFG" },
1050 { .addr = CC1120_WOR_CFG1, .name = "WOR_CFG1" },
1051 { .addr = CC1120_WOR_CFG0, .name = "WOR_CFG0" },
1052 { .addr = CC1120_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
1053 { .addr = CC1120_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
1054 { .addr = CC1120_PKT_CFG2, .name = "PKT_CFG2" },
1055 { .addr = CC1120_PKT_CFG1, .name = "PKT_CFG1" },
1056 { .addr = CC1120_PKT_CFG0, .name = "PKT_CFG0" },
1057 { .addr = CC1120_RFEND_CFG1, .name = "RFEND_CFG1" },
1058 { .addr = CC1120_RFEND_CFG0, .name = "RFEND_CFG0" },
1059 { .addr = CC1120_PA_CFG2, .name = "PA_CFG2" },
1060 { .addr = CC1120_PA_CFG1, .name = "PA_CFG1" },
1061 { .addr = CC1120_PA_CFG0, .name = "PA_CFG0" },
1062 { .addr = CC1120_PKT_LEN, .name = "PKT_LEN" },
1063 { .addr = CC1120_IF_MIX_CFG, .name = "IF_MIX_CFG" },
1064 { .addr = CC1120_FREQOFF_CFG, .name = "FREQOFF_CFG" },
1065 { .addr = CC1120_TOC_CFG, .name = "TOC_CFG" },
1066 { .addr = CC1120_MARC_SPARE, .name = "MARC_SPARE" },
1067 { .addr = CC1120_ECG_CFG, .name = "ECG_CFG" },
1068 { .addr = CC1120_SOFT_TX_DATA_CFG, .name = "SOFT_TX_DATA_CFG" },
1069 { .addr = CC1120_EXT_CTRL, .name = "EXT_CTRL" },
1070 { .addr = CC1120_RCCAL_FINE, .name = "RCCAL_FINE" },
1071 { .addr = CC1120_RCCAL_COARSE, .name = "RCCAL_COARSE" },
1072 { .addr = CC1120_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
1073 { .addr = CC1120_FREQOFF1, .name = "FREQOFF1" },
1074 { .addr = CC1120_FREQOFF0, .name = "FREQOFF0" },
1075 { .addr = CC1120_FREQ2, .name = "FREQ2" },
1076 { .addr = CC1120_FREQ1, .name = "FREQ1" },
1077 { .addr = CC1120_FREQ0, .name = "FREQ0" },
1078 { .addr = CC1120_IF_ADC2, .name = "IF_ADC2" },
1079 { .addr = CC1120_IF_ADC1, .name = "IF_ADC1" },
1080 { .addr = CC1120_IF_ADC0, .name = "IF_ADC0" },
1081 { .addr = CC1120_FS_DIG1, .name = "FS_DIG1" },
1082 { .addr = CC1120_FS_DIG0, .name = "FS_DIG0" },
1083 { .addr = CC1120_FS_CAL3, .name = "FS_CAL3" },
1084 { .addr = CC1120_FS_CAL2, .name = "FS_CAL2" },
1085 { .addr = CC1120_FS_CAL1, .name = "FS_CAL1" },
1086 { .addr = CC1120_FS_CAL0, .name = "FS_CAL0" },
1087 { .addr = CC1120_FS_CHP, .name = "FS_CHP" },
1088 { .addr = CC1120_FS_DIVTWO, .name = "FS_DIVTWO" },
1089 { .addr = CC1120_FS_DSM1, .name = "FS_DSM1" },
1090 { .addr = CC1120_FS_DSM0, .name = "FS_DSM0" },
1091 { .addr = CC1120_FS_DVC1, .name = "FS_DVC1" },
1092 { .addr = CC1120_FS_DVC0, .name = "FS_DVC0" },
1093 { .addr = CC1120_FS_LBI, .name = "FS_LBI" },
1094 { .addr = CC1120_FS_PFD, .name = "FS_PFD" },
1095 { .addr = CC1120_FS_PRE, .name = "FS_PRE" },
1096 { .addr = CC1120_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
1097 { .addr = CC1120_FS_SPARE, .name = "FS_SPARE" },
1098 { .addr = CC1120_FS_VCO4, .name = "FS_VCO4" },
1099 { .addr = CC1120_FS_VCO3, .name = "FS_VCO3" },
1100 { .addr = CC1120_FS_VCO2, .name = "FS_VCO2" },
1101 { .addr = CC1120_FS_VCO1, .name = "FS_VCO1" },
1102 { .addr = CC1120_FS_VCO0, .name = "FS_VCO0" },
1103 { .addr = CC1120_GBIAS6, .name = "GBIAS6" },
1104 { .addr = CC1120_GBIAS5, .name = "GBIAS5" },
1105 { .addr = CC1120_GBIAS4, .name = "GBIAS4" },
1106 { .addr = CC1120_GBIAS3, .name = "GBIAS3" },
1107 { .addr = CC1120_GBIAS2, .name = "GBIAS2" },
1108 { .addr = CC1120_GBIAS1, .name = "GBIAS1" },
1109 { .addr = CC1120_GBIAS0, .name = "GBIAS0" },
1110 { .addr = CC1120_IFAMP, .name = "IFAMP" },
1111 { .addr = CC1120_LNA, .name = "LNA" },
1112 { .addr = CC1120_RXMIX, .name = "RXMIX" },
1113 { .addr = CC1120_XOSC5, .name = "XOSC5" },
1114 { .addr = CC1120_XOSC4, .name = "XOSC4" },
1115 { .addr = CC1120_XOSC3, .name = "XOSC3" },
1116 { .addr = CC1120_XOSC2, .name = "XOSC2" },
1117 { .addr = CC1120_XOSC1, .name = "XOSC1" },
1118 { .addr = CC1120_XOSC0, .name = "XOSC0" },
1119 { .addr = CC1120_ANALOG_SPARE, .name = "ANALOG_SPARE" },
1120 { .addr = CC1120_PA_CFG3, .name = "PA_CFG3" },
1121 { .addr = CC1120_WOR_TIME1, .name = "WOR_TIME1" },
1122 { .addr = CC1120_WOR_TIME0, .name = "WOR_TIME0" },
1123 { .addr = CC1120_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
1124 { .addr = CC1120_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
1125 { .addr = CC1120_BIST, .name = "BIST" },
1126 { .addr = CC1120_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
1127 { .addr = CC1120_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
1128 { .addr = CC1120_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
1129 { .addr = CC1120_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
1130 { .addr = CC1120_IQIE_I1, .name = "IQIE_I1" },
1131 { .addr = CC1120_IQIE_I0, .name = "IQIE_I0" },
1132 { .addr = CC1120_IQIE_Q1, .name = "IQIE_Q1" },
1133 { .addr = CC1120_IQIE_Q0, .name = "IQIE_Q0" },
1134 { .addr = CC1120_RSSI1, .name = "RSSI1" },
1135 { .addr = CC1120_RSSI0, .name = "RSSI0" },
1136 { .addr = CC1120_MARCSTATE, .name = "MARCSTATE" },
1137 { .addr = CC1120_LQI_VAL, .name = "LQI_VAL" },
1138 { .addr = CC1120_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
1139 { .addr = CC1120_DEM_STATUS, .name = "DEM_STATUS" },
1140 { .addr = CC1120_FREQOFF_EST1, .name = "FREQOFF_EST1" },
1141 { .addr = CC1120_FREQOFF_EST0, .name = "FREQOFF_EST0" },
1142 { .addr = CC1120_AGC_GAIN3, .name = "AGC_GAIN3" },
1143 { .addr = CC1120_AGC_GAIN2, .name = "AGC_GAIN2" },
1144 { .addr = CC1120_AGC_GAIN1, .name = "AGC_GAIN1" },
1145 { .addr = CC1120_AGC_GAIN0, .name = "AGC_GAIN0" },
1146 { .addr = CC1120_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
1147 { .addr = CC1120_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
1148 { .addr = CC1120_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
1149 { .addr = CC1120_RNDGEN, .name = "RNDGEN" },
1150 { .addr = CC1120_MAGN2, .name = "MAGN2" },
1151 { .addr = CC1120_MAGN1, .name = "MAGN1" },
1152 { .addr = CC1120_MAGN0, .name = "MAGN0" },
1153 { .addr = CC1120_ANG1, .name = "ANG1" },
1154 { .addr = CC1120_ANG0, .name = "ANG0" },
1155 { .addr = CC1120_CHFILT_I2, .name = "CHFILT_I2" },
1156 { .addr = CC1120_CHFILT_I1, .name = "CHFILT_I1" },
1157 { .addr = CC1120_CHFILT_I0, .name = "CHFILT_I0" },
1158 { .addr = CC1120_CHFILT_Q2, .name = "CHFILT_Q2" },
1159 { .addr = CC1120_CHFILT_Q1, .name = "CHFILT_Q1" },
1160 { .addr = CC1120_CHFILT_Q0, .name = "CHFILT_Q0" },
1161 { .addr = CC1120_GPIO_STATUS, .name = "GPIO_STATUS" },
1162 { .addr = CC1120_FSCAL_CTRL, .name = "FSCAL_CTRL" },
1163 { .addr = CC1120_PHASE_ADJUST, .name = "PHASE_ADJUST" },
1164 { .addr = CC1120_PARTNUMBER, .name = "PARTNUMBER" },
1165 { .addr = CC1120_PARTVERSION, .name = "PARTVERSION" },
1166 { .addr = CC1120_SERIAL_STATUS, .name = "SERIAL_STATUS" },
1167 { .addr = CC1120_RX_STATUS, .name = "RX_STATUS" },
1168 { .addr = CC1120_TX_STATUS, .name = "TX_STATUS" },
1169 { .addr = CC1120_MARC_STATUS1, .name = "MARC_STATUS1" },
1170 { .addr = CC1120_MARC_STATUS0, .name = "MARC_STATUS0" },
1171 { .addr = CC1120_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
1172 { .addr = CC1120_FSRF_TEST, .name = "FSRF_TEST" },
1173 { .addr = CC1120_PRE_TEST, .name = "PRE_TEST" },
1174 { .addr = CC1120_PRE_OVR, .name = "PRE_OVR" },
1175 { .addr = CC1120_ADC_TEST, .name = "ADC_TEST" },
1176 { .addr = CC1120_DVC_TEST, .name = "DVC_TEST" },
1177 { .addr = CC1120_ATEST, .name = "ATEST" },
1178 { .addr = CC1120_ATEST_LVDS, .name = "ATEST_LVDS" },
1179 { .addr = CC1120_ATEST_MODE, .name = "ATEST_MODE" },
1180 { .addr = CC1120_XOSC_TEST1, .name = "XOSC_TEST1" },
1181 { .addr = CC1120_XOSC_TEST0, .name = "XOSC_TEST0" },
1182 { .addr = CC1120_RXFIRST, .name = "RXFIRST" },
1183 { .addr = CC1120_TXFIRST, .name = "TXFIRST" },
1184 { .addr = CC1120_RXLAST, .name = "RXLAST" },
1185 { .addr = CC1120_TXLAST, .name = "TXLAST" },
1186 { .addr = CC1120_NUM_TXBYTES, .name = "NUM_TXBYTES" },
1187 { .addr = CC1120_NUM_RXBYTES, .name = "NUM_RXBYTES" },
1188 { .addr = CC1120_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
1189 { .addr = CC1120_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
1192 #define AO_NUM_CC1120_REG (sizeof ao_cc1120_reg / sizeof ao_cc1120_reg[0])
1194 static void ao_radio_show(void) {
1195 uint8_t status = ao_radio_status();
1199 status = ao_radio_status();
1200 printf ("Status: %02x\n", status);
1201 printf ("CHIP_RDY: %d\n", (status >> CC1120_STATUS_CHIP_RDY) & 1);
1202 printf ("STATE: %s\n", cc1120_state_name[(status >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK]);
1203 printf ("MARC: %02x\n", ao_radio_get_marc_status());
1205 for (i = 0; i < AO_NUM_CC1120_REG; i++)
1206 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name);
1210 static void ao_radio_beep(void) {
1214 static void ao_radio_packet(void) {
1215 static const uint8_t packet[] = {
1217 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1218 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1219 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1220 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1226 ao_radio_send(packet, sizeof (packet));
1230 ao_radio_test_recv()
1235 if (ao_radio_recv(bytes, 34)) {
1236 if (bytes[33] & 0x80)
1240 printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32]));
1241 for (b = 0; b < 32; b++)
1242 printf (" %02x", bytes[b]);
1248 #include <ao_aprs.h>
1253 ao_packet_slave_stop();
1260 static const struct ao_cmds ao_radio_cmds[] = {
1261 { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
1264 { ao_radio_aprs, "G\0Send APRS packet" },
1266 { ao_radio_show, "R\0Show CC1120 status" },
1267 { ao_radio_beep, "b\0Emit an RDF beacon" },
1268 { ao_radio_packet, "p\0Send a test packet" },
1269 { ao_radio_test_recv, "q\0Recv a test packet" },
1279 ao_radio_configured = 0;
1280 ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN));
1283 AO_CC1120_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN));
1284 for (i = 0; i < 10000; i++) {
1285 if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0)
1288 AO_CC1120_SPI_CS_PORT->bsrr = (1 << AO_CC1120_SPI_CS_PIN);
1290 ao_panic(AO_PANIC_SELF_TEST_CC1120);
1293 /* Enable the EXTI interrupt for the appropriate pin */
1294 ao_enable_port(AO_CC1120_INT_PORT);
1295 ao_exti_setup(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1296 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
1299 /* Enable the hacked up GPIO3 pin */
1300 ao_enable_port(AO_CC1120_MCU_WAKEUP_PORT);
1301 ao_exti_setup(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN,
1302 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED,
1303 ao_radio_mcu_wakeup_isr);
1305 ao_cmd_register(&ao_radio_cmds[0]);