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 */
34 #define CC1120_DEBUG AO_FEC_DEBUG
35 #define CC1120_TRACE 0
37 extern const uint32_t ao_radio_cal;
41 #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)
42 #define ao_radio_deselect() ao_spi_put_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS)
43 #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1120_SPI_BUS)
44 #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1120_SPI_BUS)
45 #define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1120_SPI_BUS)
46 #define ao_radio_duplex(o,i,l) ao_spi_duplex((o), (i), (l), AO_CC1120_SPI_BUS)
49 ao_radio_reg_read(uint16_t addr)
55 printf("\t\tao_radio_reg_read (%04x): ", addr); flush();
57 if (CC1120_IS_EXTENDED(addr)) {
58 data[0] = ((1 << CC1120_READ) |
64 data[0] = ((1 << CC1120_READ) |
70 ao_radio_spi_send(data, d);
71 ao_radio_spi_recv(data, 1);
74 printf (" %02x\n", data[0]);
80 ao_radio_reg_write(uint16_t addr, uint8_t value)
86 printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value);
88 if (CC1120_IS_EXTENDED(addr)) {
89 data[0] = ((0 << CC1120_READ) |
95 data[0] = ((0 << CC1120_READ) |
102 ao_radio_spi_send(data, d+1);
107 ao_radio_burst_read_start (uint16_t addr)
112 if (CC1120_IS_EXTENDED(addr)) {
113 data[0] = ((1 << CC1120_READ) |
114 (1 << CC1120_BURST) |
119 data[0] = ((1 << CC1120_READ) |
120 (1 << CC1120_BURST) |
125 ao_radio_spi_send(data, d);
129 ao_radio_burst_read_stop (void)
136 ao_radio_strobe(uint8_t addr)
141 printf("\t\tao_radio_strobe (%02x): ", addr); flush();
144 ao_radio_duplex(&addr, &in, 1);
147 printf("%02x\n", in); flush();
153 ao_radio_fifo_read(uint8_t *data, uint8_t len)
155 uint8_t addr = ((1 << CC1120_READ) |
156 (1 << CC1120_BURST) |
161 ao_radio_duplex(&addr, &status, 1);
162 ao_radio_spi_recv(data, len);
168 ao_radio_fifo_write_start(void)
170 uint8_t addr = ((0 << CC1120_READ) |
171 (1 << CC1120_BURST) |
176 ao_radio_duplex(&addr, &status, 1);
180 static inline uint8_t ao_radio_fifo_write_stop(uint8_t status) {
186 ao_radio_fifo_write(uint8_t *data, uint8_t len)
188 uint8_t status = ao_radio_fifo_write_start();
189 ao_radio_spi_send(data, len);
190 return ao_radio_fifo_write_stop(status);
194 ao_radio_fifo_write_fixed(uint8_t data, uint8_t len)
196 uint8_t status = ao_radio_fifo_write_start();
197 ao_radio_spi_send_fixed(data, len);
198 return ao_radio_fifo_write_stop(status);
202 ao_radio_tx_fifo_space(void)
204 return CC1120_FIFO_SIZE - ao_radio_reg_read(CC1120_NUM_TXBYTES);
208 ao_radio_status(void)
210 return ao_radio_strobe (CC1120_SNOP);
214 ao_radio_recv_abort(void)
217 ao_wakeup(&ao_radio_wake);
220 #define ao_radio_rdf_value 0x55
223 ao_radio_get_marc_status(void)
225 return ao_radio_reg_read(CC1120_MARC_STATUS1);
229 ao_radio_mcu_wakeup_isr(void)
231 ao_radio_mcu_wake = 1;
232 ao_wakeup(&ao_radio_wake);
237 ao_radio_check_marc_status(void)
239 ao_radio_mcu_wake = 0;
240 ao_radio_marc_status = ao_radio_get_marc_status();
242 /* Anyt other than 'tx/rx finished' means an error occurred */
243 if (ao_radio_marc_status & ~(CC1120_MARC_STATUS1_TX_FINISHED|CC1120_MARC_STATUS1_RX_FINISHED))
250 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
252 ao_wakeup(&ao_radio_wake);
256 ao_radio_start_tx(void)
258 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr);
259 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
260 ao_exti_enable(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN);
261 ao_radio_strobe(CC1120_STX);
268 uint8_t state = ao_radio_strobe(CC1120_SIDLE);
269 if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_IDLE)
272 /* Flush any pending TX bytes */
273 ao_radio_strobe(CC1120_SFTX);
277 * Packet deviation is 20.5kHz
279 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
281 * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz
284 #define PACKET_DEV_E 5
285 #define PACKET_DEV_M 80
288 * For our packet data, set the symbol rate to 38400 Baud
290 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
291 * Rdata = -------------------------------------- * fosc
295 * DATARATE_M = 239914
298 #define PACKET_DRATE_E 9
299 #define PACKET_DRATE_M 239914
301 static const uint16_t packet_setup[] = {
302 CC1120_DEVIATION_M, PACKET_DEV_M,
303 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
304 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
305 (PACKET_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
306 CC1120_DRATE2, ((PACKET_DRATE_E << CC1120_DRATE2_DATARATE_E) |
307 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
308 CC1120_DRATE1, ((PACKET_DRATE_M >> 8) & 0xff),
309 CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff),
310 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
311 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
312 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
313 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
314 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
315 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
316 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
317 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
318 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
319 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
320 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
321 AO_CC1120_MARC_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP,
324 static const uint16_t packet_tx_setup[] = {
325 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
326 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
327 AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG,
330 static const uint16_t packet_rx_setup[] = {
331 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
332 (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT)),
333 AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT,
337 * RDF deviation is 5kHz
339 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
341 * 32e6Hz / (2 ** 24) * (256 + 71) * (2 ** 3) = 4989
346 #define RDF_PACKET_LEN 50
349 * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
351 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
352 * Rdata = -------------------------------------- * fosc
358 * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
360 #define RDF_DRATE_E 5
361 #define RDF_DRATE_M 25166
362 #define RDF_PACKET_LEN 50
364 static const uint16_t rdf_setup[] = {
365 CC1120_DEVIATION_M, RDF_DEV_M,
366 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
367 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
368 (RDF_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
369 CC1120_DRATE2, ((RDF_DRATE_E << CC1120_DRATE2_DATARATE_E) |
370 (((RDF_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
371 CC1120_DRATE1, ((RDF_DRATE_M >> 8) & 0xff),
372 CC1120_DRATE0, ((RDF_DRATE_M >> 0) & 0xff),
373 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
374 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
375 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
376 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
377 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
378 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
379 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
380 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
381 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
382 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
383 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
387 * APRS deviation is 5kHz
389 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
391 * 32e6Hz / (2 ** 24) * (256 + 71) * (2 ** 3) = 4989
395 #define APRS_DEV_M 71
396 #define APRS_PACKET_LEN 50
399 * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate)
401 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
402 * Rdata = -------------------------------------- * fosc
405 * DATARATE_M = 239914
408 * Rdata = 9599.998593330383301
411 #define APRS_DRATE_E 7
412 #define APRS_DRATE_M 239914
414 static const uint16_t aprs_setup[] = {
415 CC1120_DEVIATION_M, APRS_DEV_M,
416 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
417 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
418 (APRS_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
419 CC1120_DRATE2, ((APRS_DRATE_E << CC1120_DRATE2_DATARATE_E) |
420 (((APRS_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
421 CC1120_DRATE1, ((APRS_DRATE_M >> 8) & 0xff),
422 CC1120_DRATE0, ((APRS_DRATE_M >> 0) & 0xff),
423 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
424 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
425 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
426 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
427 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
428 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
431 #define AO_PKT_CFG0_INFINITE ((0 << CC1120_PKT_CFG0_RESERVED7) | \
432 (CC1120_PKT_CFG0_LENGTH_CONFIG_INFINITE << CC1120_PKT_CFG0_LENGTH_CONFIG) | \
433 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | \
434 (0 << CC1120_PKT_CFG0_UART_MODE_EN) | \
435 (0 << CC1120_PKT_CFG0_UART_SWAP_EN))
437 #define AO_PKT_CFG0_FIXED ((0 << CC1120_PKT_CFG0_RESERVED7) | \
438 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) | \
439 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | \
440 (0 << CC1120_PKT_CFG0_UART_MODE_EN) | \
441 (0 << CC1120_PKT_CFG0_UART_SWAP_EN))
443 static uint16_t ao_radio_mode;
445 #define AO_RADIO_MODE_BITS_PACKET 1
446 #define AO_RADIO_MODE_BITS_PACKET_TX 2
447 #define AO_RADIO_MODE_BITS_TX_BUF 4
448 #define AO_RADIO_MODE_BITS_TX_FINISH 8
449 #define AO_RADIO_MODE_BITS_PACKET_RX 16
450 #define AO_RADIO_MODE_BITS_RDF 32
451 #define AO_RADIO_MODE_BITS_APRS 64
452 #define AO_RADIO_MODE_BITS_INFINITE 128
453 #define AO_RADIO_MODE_BITS_FIXED 256
455 #define AO_RADIO_MODE_NONE 0
456 #define AO_RADIO_MODE_PACKET_TX_BUF (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_BUF)
457 #define AO_RADIO_MODE_PACKET_TX_FINISH (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_FINISH)
458 #define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_RX)
459 #define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_TX_FINISH)
460 #define AO_RADIO_MODE_APRS_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
461 #define AO_RADIO_MODE_APRS_LAST_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_BUF)
462 #define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
465 ao_radio_set_mode(uint16_t new_mode)
470 if (new_mode == ao_radio_mode)
473 changes = new_mode & (~ao_radio_mode);
474 if (changes & AO_RADIO_MODE_BITS_PACKET)
475 for (i = 0; i < sizeof (packet_setup) / sizeof (packet_setup[0]); i += 2)
476 ao_radio_reg_write(packet_setup[i], packet_setup[i+1]);
478 if (changes & AO_RADIO_MODE_BITS_PACKET_TX)
479 for (i = 0; i < sizeof (packet_tx_setup) / sizeof (packet_tx_setup[0]); i += 2)
480 ao_radio_reg_write(packet_tx_setup[i], packet_tx_setup[i+1]);
482 if (changes & AO_RADIO_MODE_BITS_TX_BUF)
483 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_TXFIFO_THR);
485 if (changes & AO_RADIO_MODE_BITS_TX_FINISH)
486 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG);
488 if (changes & AO_RADIO_MODE_BITS_PACKET_RX)
489 for (i = 0; i < sizeof (packet_rx_setup) / sizeof (packet_rx_setup[0]); i += 2)
490 ao_radio_reg_write(packet_rx_setup[i], packet_rx_setup[i+1]);
492 if (changes & AO_RADIO_MODE_BITS_RDF)
493 for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2)
494 ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]);
496 if (changes & AO_RADIO_MODE_BITS_APRS)
497 for (i = 0; i < sizeof (aprs_setup) / sizeof (aprs_setup[0]); i += 2)
498 ao_radio_reg_write(aprs_setup[i], aprs_setup[i+1]);
500 if (changes & AO_RADIO_MODE_BITS_INFINITE)
501 ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_INFINITE);
503 if (changes & AO_RADIO_MODE_BITS_FIXED)
504 ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_FIXED);
506 ao_radio_mode = new_mode;
509 static const uint16_t radio_setup[] = {
510 #include "ao_cc1120_CC1120.h"
513 static uint8_t ao_radio_configured = 0;
520 ao_radio_strobe(CC1120_SRES);
522 for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2)
523 ao_radio_reg_write(radio_setup[i], radio_setup[i+1]);
529 ao_radio_configured = 1;
533 ao_radio_set_len(uint8_t len)
535 static uint8_t last_len;
537 if (len != last_len) {
538 ao_radio_reg_write(CC1120_PKT_LEN, len);
544 ao_radio_get(uint8_t len)
546 static uint32_t last_radio_setting;
548 ao_mutex_get(&ao_radio_mutex);
549 if (!ao_radio_configured)
551 if (ao_config.radio_setting != last_radio_setting) {
552 ao_radio_reg_write(CC1120_FREQ2, ao_config.radio_setting >> 16);
553 ao_radio_reg_write(CC1120_FREQ1, ao_config.radio_setting >> 8);
554 ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting);
555 last_radio_setting = ao_config.radio_setting;
557 ao_radio_set_len(len);
560 #define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
563 ao_rdf_start(uint8_t len)
568 ao_radio_set_mode(AO_RADIO_MODE_RDF);
578 ao_arch_block_interrupts();
579 while (!ao_radio_wake && !ao_radio_abort && !ao_radio_mcu_wake)
580 ao_sleep(&ao_radio_wake);
581 ao_arch_release_interrupts();
582 if (ao_radio_mcu_wake)
583 ao_radio_check_marc_status();
592 ao_rdf_start(AO_RADIO_RDF_LEN);
594 ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN);
600 ao_radio_continuity(uint8_t c)
605 ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN);
607 status = ao_radio_fifo_write_start();
608 for (i = 0; i < 3; i++) {
609 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
611 ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN);
613 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN);
615 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
616 status = ao_radio_fifo_write_stop(status);
622 ao_radio_rdf_abort(void)
625 ao_wakeup(&ao_radio_wake);
629 ao_radio_test_cmd(void)
632 static uint8_t radio_on;
634 if (ao_cmd_lex_c != '\n') {
636 mode = (uint8_t) ao_cmd_lex_u32;
639 if ((mode & 2) && !radio_on) {
641 ao_monitor_disable();
644 ao_packet_slave_stop();
647 ao_radio_strobe(CC1120_STX);
650 for (t = 0; t < 10; t++) {
651 printf ("status: %02x\n", ao_radio_status());
652 ao_delay(AO_MS_TO_TICKS(100));
659 printf ("Hit a character to stop..."); flush();
663 if ((mode & 1) && radio_on) {
674 ao_radio_wait_isr(uint16_t timeout)
678 ao_arch_block_interrupts();
679 while (!ao_radio_wake && !ao_radio_mcu_wake && !ao_radio_abort)
680 if (ao_sleep(&ao_radio_wake))
682 ao_arch_release_interrupts();
685 if (ao_radio_mcu_wake)
686 ao_radio_check_marc_status();
690 ao_radio_wait_tx(uint8_t wait_fifo)
692 uint8_t fifo_space = 0;
695 ao_radio_wait_isr(0);
698 fifo_space = ao_radio_tx_fifo_space();
699 } while (!fifo_space && !ao_radio_abort);
703 static uint8_t tx_data[(AO_RADIO_MAX_SEND + 4) * 2];
706 ao_radio_send(const void *d, uint8_t size)
709 uint8_t *e = tx_data;
715 encode_len = ao_fec_encode(d, size, tx_data);
717 ao_radio_get(encode_len);
720 fifo_space = CC1120_FIFO_SIZE;
722 this_len = encode_len;
725 if (this_len > fifo_space) {
726 this_len = fifo_space;
727 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_BUF);
729 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_FINISH);
732 ao_radio_fifo_write(e, this_len);
734 encode_len -= this_len;
740 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
743 fifo_space = ao_radio_wait_tx(encode_len != 0);
744 if (ao_radio_abort) {
752 #define AO_RADIO_LOTS 64
755 ao_radio_send_aprs(ao_radio_fill_func fill)
757 uint8_t buf[AO_RADIO_LOTS], *b;
765 fifo_space = CC1120_FIFO_SIZE;
767 cnt = (*fill)(buf, sizeof(buf));
774 /* At the last buffer, set the total length */
776 ao_radio_set_len(total & 0xff);
780 uint8_t this_len = cnt;
782 /* Wait for some space in the fifo */
783 while (!ao_radio_abort && (fifo_space = ao_radio_tx_fifo_space()) == 0) {
785 ao_radio_wait_isr(0);
789 if (this_len > fifo_space)
790 this_len = fifo_space;
796 ao_radio_set_mode(AO_RADIO_MODE_APRS_LAST_BUF);
798 ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
800 ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
802 ao_radio_fifo_write(b, this_len);
809 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
811 if (ao_radio_abort) {
815 /* Wait for the transmitter to go idle */
817 ao_radio_wait_isr(0);
822 static uint8_t rx_data[(AO_RADIO_MAX_RECV + 4) * 2 * 8];
823 static uint16_t rx_data_count;
824 static uint16_t rx_data_consumed;
825 static uint16_t rx_data_cur;
826 static uint8_t rx_ignore;
827 static uint8_t rx_waiting;
830 static uint32_t rx_start_tick, rx_packet_tick, rx_done_tick, rx_last_done_tick;
832 uint32_t ao_rx_start_tick, ao_rx_packet_tick, ao_rx_done_tick, ao_rx_last_done_tick;
834 #include <ao_profile.h>
838 ao_radio_rx_isr(void)
842 d = AO_CC1120_SPI.dr;
843 AO_CC1120_SPI.dr = 0;
844 if (rx_ignore == 0) {
845 if (rx_data_cur >= rx_data_count)
846 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
848 rx_data[rx_data_cur++] = d;
849 if (rx_waiting && rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) {
852 rx_packet_tick = ao_profile_tick();
853 if (rx_data_cur < rx_data_count)
857 ao_wakeup(&ao_radio_wake);
865 ao_radio_rx_wait(void)
868 if (ao_radio_mcu_wake)
869 ao_radio_check_marc_status();
870 ao_alarm(AO_MS_TO_TICKS(100));
871 ao_arch_block_interrupts();
873 while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&
877 if (ao_sleep(&ao_radio_wake))
881 ao_arch_release_interrupts();
883 } while (ao_radio_mcu_wake);
886 rx_data_consumed += AO_FEC_DECODE_BLOCK;
888 return rx_data_cur - rx_data_consumed;
890 return AO_FEC_DECODE_BLOCK;
894 ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout)
900 static int been_here = 0;
902 size -= 2; /* status bytes */
903 if (size > AO_RADIO_MAX_RECV) {
904 ao_delay(AO_SEC_TO_TICKS(1));
908 rx_start_tick = ao_profile_tick();
911 len = size + 2; /* CRC bytes */
912 len += 1 + ~(len & 1); /* 1 or two pad bytes */
913 len *= 2; /* 1/2 rate convolution */
914 rx_data_count = len * 8; /* bytes to bits */
916 rx_data_consumed = 0;
919 /* Must be set before changing the frequency; any abort
920 * after the frequency is set needs to terminate the read
921 * so that the registers can be reprogrammed
925 /* configure interrupt pin */
927 ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
930 ao_radio_mcu_wake = 0;
932 AO_CC1120_SPI.cr2 = 0;
935 (void) AO_CC1120_SPI.dr;
937 /* Have the radio signal when the preamble quality goes high */
938 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_PQT_REACHED);
939 ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
940 AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_HIGH);
941 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr);
942 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
943 ao_exti_enable(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN);
945 ao_radio_strobe(CC1120_SRX);
947 /* Wait for the preamble to appear */
948 ao_radio_wait_isr(timeout);
952 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT);
953 ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
954 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
956 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
957 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
959 ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
961 ret = ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait);
963 ao_radio_burst_read_stop();
966 ao_radio_strobe(CC1120_SIDLE);
968 /* Convert from 'real' rssi to cc1111-style values */
970 rssi = AO_RADIO_FROM_RSSI(ao_radio_reg_read(CC1120_RSSI1));
974 /* Store the received RSSI value; the crc-OK byte is already done */
976 ((uint8_t *) d)[size] = (uint8_t) rssi;
979 rx_last_done_tick = rx_done_tick;
980 rx_done_tick = ao_profile_tick();
982 ao_rx_start_tick = rx_start_tick;
983 ao_rx_packet_tick = rx_packet_tick;
984 ao_rx_done_tick = rx_done_tick;
985 ao_rx_last_done_tick = rx_last_done_tick;
993 static char *cc1120_state_name[] = {
994 [CC1120_STATUS_STATE_IDLE] = "IDLE",
995 [CC1120_STATUS_STATE_RX] = "RX",
996 [CC1120_STATUS_STATE_TX] = "TX",
997 [CC1120_STATUS_STATE_FSTXON] = "FSTXON",
998 [CC1120_STATUS_STATE_CALIBRATE] = "CALIBRATE",
999 [CC1120_STATUS_STATE_SETTLING] = "SETTLING",
1000 [CC1120_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
1001 [CC1120_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
1004 struct ao_cc1120_reg {
1009 const static struct ao_cc1120_reg ao_cc1120_reg[] = {
1010 { .addr = CC1120_IOCFG3, .name = "IOCFG3" },
1011 { .addr = CC1120_IOCFG2, .name = "IOCFG2" },
1012 { .addr = CC1120_IOCFG1, .name = "IOCFG1" },
1013 { .addr = CC1120_IOCFG0, .name = "IOCFG0" },
1014 { .addr = CC1120_SYNC3, .name = "SYNC3" },
1015 { .addr = CC1120_SYNC2, .name = "SYNC2" },
1016 { .addr = CC1120_SYNC1, .name = "SYNC1" },
1017 { .addr = CC1120_SYNC0, .name = "SYNC0" },
1018 { .addr = CC1120_SYNC_CFG1, .name = "SYNC_CFG1" },
1019 { .addr = CC1120_SYNC_CFG0, .name = "SYNC_CFG0" },
1020 { .addr = CC1120_DEVIATION_M, .name = "DEVIATION_M" },
1021 { .addr = CC1120_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
1022 { .addr = CC1120_DCFILT_CFG, .name = "DCFILT_CFG" },
1023 { .addr = CC1120_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
1024 { .addr = CC1120_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
1025 { .addr = CC1120_FREQ_IF_CFG, .name = "FREQ_IF_CFG" },
1026 { .addr = CC1120_IQIC, .name = "IQIC" },
1027 { .addr = CC1120_CHAN_BW, .name = "CHAN_BW" },
1028 { .addr = CC1120_MDMCFG1, .name = "MDMCFG1" },
1029 { .addr = CC1120_MDMCFG0, .name = "MDMCFG0" },
1030 { .addr = CC1120_DRATE2, .name = "DRATE2" },
1031 { .addr = CC1120_DRATE1, .name = "DRATE1" },
1032 { .addr = CC1120_DRATE0, .name = "DRATE0" },
1033 { .addr = CC1120_AGC_REF, .name = "AGC_REF" },
1034 { .addr = CC1120_AGC_CS_THR, .name = "AGC_CS_THR" },
1035 { .addr = CC1120_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
1036 { .addr = CC1120_AGC_CFG3, .name = "AGC_CFG3" },
1037 { .addr = CC1120_AGC_CFG2, .name = "AGC_CFG2" },
1038 { .addr = CC1120_AGC_CFG1, .name = "AGC_CFG1" },
1039 { .addr = CC1120_AGC_CFG0, .name = "AGC_CFG0" },
1040 { .addr = CC1120_FIFO_CFG, .name = "FIFO_CFG" },
1041 { .addr = CC1120_DEV_ADDR, .name = "DEV_ADDR" },
1042 { .addr = CC1120_SETTLING_CFG, .name = "SETTLING_CFG" },
1043 { .addr = CC1120_FS_CFG, .name = "FS_CFG" },
1044 { .addr = CC1120_WOR_CFG1, .name = "WOR_CFG1" },
1045 { .addr = CC1120_WOR_CFG0, .name = "WOR_CFG0" },
1046 { .addr = CC1120_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
1047 { .addr = CC1120_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
1048 { .addr = CC1120_PKT_CFG2, .name = "PKT_CFG2" },
1049 { .addr = CC1120_PKT_CFG1, .name = "PKT_CFG1" },
1050 { .addr = CC1120_PKT_CFG0, .name = "PKT_CFG0" },
1051 { .addr = CC1120_RFEND_CFG1, .name = "RFEND_CFG1" },
1052 { .addr = CC1120_RFEND_CFG0, .name = "RFEND_CFG0" },
1053 { .addr = CC1120_PA_CFG2, .name = "PA_CFG2" },
1054 { .addr = CC1120_PA_CFG1, .name = "PA_CFG1" },
1055 { .addr = CC1120_PA_CFG0, .name = "PA_CFG0" },
1056 { .addr = CC1120_PKT_LEN, .name = "PKT_LEN" },
1057 { .addr = CC1120_IF_MIX_CFG, .name = "IF_MIX_CFG" },
1058 { .addr = CC1120_FREQOFF_CFG, .name = "FREQOFF_CFG" },
1059 { .addr = CC1120_TOC_CFG, .name = "TOC_CFG" },
1060 { .addr = CC1120_MARC_SPARE, .name = "MARC_SPARE" },
1061 { .addr = CC1120_ECG_CFG, .name = "ECG_CFG" },
1062 { .addr = CC1120_SOFT_TX_DATA_CFG, .name = "SOFT_TX_DATA_CFG" },
1063 { .addr = CC1120_EXT_CTRL, .name = "EXT_CTRL" },
1064 { .addr = CC1120_RCCAL_FINE, .name = "RCCAL_FINE" },
1065 { .addr = CC1120_RCCAL_COARSE, .name = "RCCAL_COARSE" },
1066 { .addr = CC1120_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
1067 { .addr = CC1120_FREQOFF1, .name = "FREQOFF1" },
1068 { .addr = CC1120_FREQOFF0, .name = "FREQOFF0" },
1069 { .addr = CC1120_FREQ2, .name = "FREQ2" },
1070 { .addr = CC1120_FREQ1, .name = "FREQ1" },
1071 { .addr = CC1120_FREQ0, .name = "FREQ0" },
1072 { .addr = CC1120_IF_ADC2, .name = "IF_ADC2" },
1073 { .addr = CC1120_IF_ADC1, .name = "IF_ADC1" },
1074 { .addr = CC1120_IF_ADC0, .name = "IF_ADC0" },
1075 { .addr = CC1120_FS_DIG1, .name = "FS_DIG1" },
1076 { .addr = CC1120_FS_DIG0, .name = "FS_DIG0" },
1077 { .addr = CC1120_FS_CAL3, .name = "FS_CAL3" },
1078 { .addr = CC1120_FS_CAL2, .name = "FS_CAL2" },
1079 { .addr = CC1120_FS_CAL1, .name = "FS_CAL1" },
1080 { .addr = CC1120_FS_CAL0, .name = "FS_CAL0" },
1081 { .addr = CC1120_FS_CHP, .name = "FS_CHP" },
1082 { .addr = CC1120_FS_DIVTWO, .name = "FS_DIVTWO" },
1083 { .addr = CC1120_FS_DSM1, .name = "FS_DSM1" },
1084 { .addr = CC1120_FS_DSM0, .name = "FS_DSM0" },
1085 { .addr = CC1120_FS_DVC1, .name = "FS_DVC1" },
1086 { .addr = CC1120_FS_DVC0, .name = "FS_DVC0" },
1087 { .addr = CC1120_FS_LBI, .name = "FS_LBI" },
1088 { .addr = CC1120_FS_PFD, .name = "FS_PFD" },
1089 { .addr = CC1120_FS_PRE, .name = "FS_PRE" },
1090 { .addr = CC1120_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
1091 { .addr = CC1120_FS_SPARE, .name = "FS_SPARE" },
1092 { .addr = CC1120_FS_VCO4, .name = "FS_VCO4" },
1093 { .addr = CC1120_FS_VCO3, .name = "FS_VCO3" },
1094 { .addr = CC1120_FS_VCO2, .name = "FS_VCO2" },
1095 { .addr = CC1120_FS_VCO1, .name = "FS_VCO1" },
1096 { .addr = CC1120_FS_VCO0, .name = "FS_VCO0" },
1097 { .addr = CC1120_GBIAS6, .name = "GBIAS6" },
1098 { .addr = CC1120_GBIAS5, .name = "GBIAS5" },
1099 { .addr = CC1120_GBIAS4, .name = "GBIAS4" },
1100 { .addr = CC1120_GBIAS3, .name = "GBIAS3" },
1101 { .addr = CC1120_GBIAS2, .name = "GBIAS2" },
1102 { .addr = CC1120_GBIAS1, .name = "GBIAS1" },
1103 { .addr = CC1120_GBIAS0, .name = "GBIAS0" },
1104 { .addr = CC1120_IFAMP, .name = "IFAMP" },
1105 { .addr = CC1120_LNA, .name = "LNA" },
1106 { .addr = CC1120_RXMIX, .name = "RXMIX" },
1107 { .addr = CC1120_XOSC5, .name = "XOSC5" },
1108 { .addr = CC1120_XOSC4, .name = "XOSC4" },
1109 { .addr = CC1120_XOSC3, .name = "XOSC3" },
1110 { .addr = CC1120_XOSC2, .name = "XOSC2" },
1111 { .addr = CC1120_XOSC1, .name = "XOSC1" },
1112 { .addr = CC1120_XOSC0, .name = "XOSC0" },
1113 { .addr = CC1120_ANALOG_SPARE, .name = "ANALOG_SPARE" },
1114 { .addr = CC1120_PA_CFG3, .name = "PA_CFG3" },
1115 { .addr = CC1120_WOR_TIME1, .name = "WOR_TIME1" },
1116 { .addr = CC1120_WOR_TIME0, .name = "WOR_TIME0" },
1117 { .addr = CC1120_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
1118 { .addr = CC1120_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
1119 { .addr = CC1120_BIST, .name = "BIST" },
1120 { .addr = CC1120_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
1121 { .addr = CC1120_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
1122 { .addr = CC1120_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
1123 { .addr = CC1120_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
1124 { .addr = CC1120_IQIE_I1, .name = "IQIE_I1" },
1125 { .addr = CC1120_IQIE_I0, .name = "IQIE_I0" },
1126 { .addr = CC1120_IQIE_Q1, .name = "IQIE_Q1" },
1127 { .addr = CC1120_IQIE_Q0, .name = "IQIE_Q0" },
1128 { .addr = CC1120_RSSI1, .name = "RSSI1" },
1129 { .addr = CC1120_RSSI0, .name = "RSSI0" },
1130 { .addr = CC1120_MARCSTATE, .name = "MARCSTATE" },
1131 { .addr = CC1120_LQI_VAL, .name = "LQI_VAL" },
1132 { .addr = CC1120_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
1133 { .addr = CC1120_DEM_STATUS, .name = "DEM_STATUS" },
1134 { .addr = CC1120_FREQOFF_EST1, .name = "FREQOFF_EST1" },
1135 { .addr = CC1120_FREQOFF_EST0, .name = "FREQOFF_EST0" },
1136 { .addr = CC1120_AGC_GAIN3, .name = "AGC_GAIN3" },
1137 { .addr = CC1120_AGC_GAIN2, .name = "AGC_GAIN2" },
1138 { .addr = CC1120_AGC_GAIN1, .name = "AGC_GAIN1" },
1139 { .addr = CC1120_AGC_GAIN0, .name = "AGC_GAIN0" },
1140 { .addr = CC1120_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
1141 { .addr = CC1120_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
1142 { .addr = CC1120_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
1143 { .addr = CC1120_RNDGEN, .name = "RNDGEN" },
1144 { .addr = CC1120_MAGN2, .name = "MAGN2" },
1145 { .addr = CC1120_MAGN1, .name = "MAGN1" },
1146 { .addr = CC1120_MAGN0, .name = "MAGN0" },
1147 { .addr = CC1120_ANG1, .name = "ANG1" },
1148 { .addr = CC1120_ANG0, .name = "ANG0" },
1149 { .addr = CC1120_CHFILT_I2, .name = "CHFILT_I2" },
1150 { .addr = CC1120_CHFILT_I1, .name = "CHFILT_I1" },
1151 { .addr = CC1120_CHFILT_I0, .name = "CHFILT_I0" },
1152 { .addr = CC1120_CHFILT_Q2, .name = "CHFILT_Q2" },
1153 { .addr = CC1120_CHFILT_Q1, .name = "CHFILT_Q1" },
1154 { .addr = CC1120_CHFILT_Q0, .name = "CHFILT_Q0" },
1155 { .addr = CC1120_GPIO_STATUS, .name = "GPIO_STATUS" },
1156 { .addr = CC1120_FSCAL_CTRL, .name = "FSCAL_CTRL" },
1157 { .addr = CC1120_PHASE_ADJUST, .name = "PHASE_ADJUST" },
1158 { .addr = CC1120_PARTNUMBER, .name = "PARTNUMBER" },
1159 { .addr = CC1120_PARTVERSION, .name = "PARTVERSION" },
1160 { .addr = CC1120_SERIAL_STATUS, .name = "SERIAL_STATUS" },
1161 { .addr = CC1120_RX_STATUS, .name = "RX_STATUS" },
1162 { .addr = CC1120_TX_STATUS, .name = "TX_STATUS" },
1163 { .addr = CC1120_MARC_STATUS1, .name = "MARC_STATUS1" },
1164 { .addr = CC1120_MARC_STATUS0, .name = "MARC_STATUS0" },
1165 { .addr = CC1120_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
1166 { .addr = CC1120_FSRF_TEST, .name = "FSRF_TEST" },
1167 { .addr = CC1120_PRE_TEST, .name = "PRE_TEST" },
1168 { .addr = CC1120_PRE_OVR, .name = "PRE_OVR" },
1169 { .addr = CC1120_ADC_TEST, .name = "ADC_TEST" },
1170 { .addr = CC1120_DVC_TEST, .name = "DVC_TEST" },
1171 { .addr = CC1120_ATEST, .name = "ATEST" },
1172 { .addr = CC1120_ATEST_LVDS, .name = "ATEST_LVDS" },
1173 { .addr = CC1120_ATEST_MODE, .name = "ATEST_MODE" },
1174 { .addr = CC1120_XOSC_TEST1, .name = "XOSC_TEST1" },
1175 { .addr = CC1120_XOSC_TEST0, .name = "XOSC_TEST0" },
1176 { .addr = CC1120_RXFIRST, .name = "RXFIRST" },
1177 { .addr = CC1120_TXFIRST, .name = "TXFIRST" },
1178 { .addr = CC1120_RXLAST, .name = "RXLAST" },
1179 { .addr = CC1120_TXLAST, .name = "TXLAST" },
1180 { .addr = CC1120_NUM_TXBYTES, .name = "NUM_TXBYTES" },
1181 { .addr = CC1120_NUM_RXBYTES, .name = "NUM_RXBYTES" },
1182 { .addr = CC1120_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
1183 { .addr = CC1120_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
1186 #define AO_NUM_CC1120_REG (sizeof ao_cc1120_reg / sizeof ao_cc1120_reg[0])
1188 static void ao_radio_show(void) {
1189 uint8_t status = ao_radio_status();
1193 status = ao_radio_status();
1194 printf ("Status: %02x\n", status);
1195 printf ("CHIP_RDY: %d\n", (status >> CC1120_STATUS_CHIP_RDY) & 1);
1196 printf ("STATE: %s\n", cc1120_state_name[(status >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK]);
1197 printf ("MARC: %02x\n", ao_radio_get_marc_status());
1199 for (i = 0; i < AO_NUM_CC1120_REG; i++)
1200 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name);
1204 static void ao_radio_beep(void) {
1208 static void ao_radio_packet(void) {
1209 static const uint8_t packet[] = {
1211 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1212 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1213 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1214 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1220 ao_radio_send(packet, sizeof (packet));
1224 ao_radio_test_recv()
1229 if (ao_radio_recv(bytes, 34)) {
1230 if (bytes[33] & 0x80)
1234 printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32]));
1235 for (b = 0; b < 32; b++)
1236 printf (" %02x", bytes[b]);
1242 #include <ao_aprs.h>
1247 ao_packet_slave_stop();
1254 static const struct ao_cmds ao_radio_cmds[] = {
1255 { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
1258 { ao_radio_aprs, "G\0Send APRS packet" },
1260 { ao_radio_show, "R\0Show CC1120 status" },
1261 { ao_radio_beep, "b\0Emit an RDF beacon" },
1262 { ao_radio_packet, "p\0Send a test packet" },
1263 { ao_radio_test_recv, "q\0Recv a test packet" },
1273 ao_radio_configured = 0;
1274 ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN));
1277 AO_CC1120_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN));
1278 for (i = 0; i < 10000; i++) {
1279 if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0)
1282 AO_CC1120_SPI_CS_PORT->bsrr = (1 << AO_CC1120_SPI_CS_PIN);
1284 ao_panic(AO_PANIC_SELF_TEST_CC1120);
1287 /* Enable the EXTI interrupt for the appropriate pin */
1288 ao_enable_port(AO_CC1120_INT_PORT);
1289 ao_exti_setup(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1290 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
1293 /* Enable the hacked up GPIO3 pin */
1294 ao_enable_port(AO_CC1120_MCU_WAKEUP_PORT);
1295 ao_exti_setup(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN,
1296 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED,
1297 ao_radio_mcu_wakeup_isr);
1299 ao_cmd_register(&ao_radio_cmds[0]);