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_1MHz)
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(void)
676 ao_arch_block_interrupts();
677 while (!ao_radio_wake && !ao_radio_mcu_wake && !ao_radio_abort)
678 ao_sleep(&ao_radio_wake);
679 ao_arch_release_interrupts();
680 if (ao_radio_mcu_wake)
681 ao_radio_check_marc_status();
685 ao_radio_wait_tx(uint8_t wait_fifo)
687 uint8_t fifo_space = 0;
693 fifo_space = ao_radio_tx_fifo_space();
694 } while (!fifo_space && !ao_radio_abort);
698 static uint8_t tx_data[(AO_RADIO_MAX_SEND + 4) * 2];
701 ao_radio_send(const void *d, uint8_t size)
704 uint8_t *e = tx_data;
710 encode_len = ao_fec_encode(d, size, tx_data);
712 ao_radio_get(encode_len);
715 fifo_space = CC1120_FIFO_SIZE;
717 this_len = encode_len;
720 if (this_len > fifo_space) {
721 this_len = fifo_space;
722 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_BUF);
724 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_FINISH);
727 ao_radio_fifo_write(e, this_len);
729 encode_len -= this_len;
735 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
738 fifo_space = ao_radio_wait_tx(encode_len != 0);
739 if (ao_radio_abort) {
747 #define AO_RADIO_LOTS 64
750 ao_radio_send_lots(ao_radio_fill_func fill)
752 uint8_t buf[AO_RADIO_LOTS], *b;
760 fifo_space = CC1120_FIFO_SIZE;
762 cnt = (*fill)(buf, sizeof(buf));
769 /* At the last buffer, set the total length */
771 ao_radio_set_len(total & 0xff);
775 uint8_t this_len = cnt;
777 /* Wait for some space in the fifo */
778 while (!ao_radio_abort && (fifo_space = ao_radio_tx_fifo_space()) == 0) {
784 if (this_len > fifo_space)
785 this_len = fifo_space;
791 ao_radio_set_mode(AO_RADIO_MODE_APRS_LAST_BUF);
793 ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
795 ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
797 ao_radio_fifo_write(b, this_len);
804 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
806 if (ao_radio_abort) {
810 /* Wait for the transmitter to go idle */
817 static uint8_t rx_data[(AO_RADIO_MAX_RECV + 4) * 2 * 8];
818 static uint16_t rx_data_count;
819 static uint16_t rx_data_consumed;
820 static uint16_t rx_data_cur;
821 static uint8_t rx_ignore;
822 static uint8_t rx_waiting;
825 static uint32_t rx_start_tick, rx_packet_tick, rx_done_tick, rx_last_done_tick;
827 uint32_t ao_rx_start_tick, ao_rx_packet_tick, ao_rx_done_tick, ao_rx_last_done_tick;
829 #include <ao_profile.h>
833 ao_radio_rx_isr(void)
837 d = AO_CC1120_SPI.dr;
838 AO_CC1120_SPI.dr = 0;
839 if (rx_ignore == 0) {
840 if (rx_data_cur >= rx_data_count)
841 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
843 rx_data[rx_data_cur++] = d;
844 if (rx_waiting && rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) {
847 rx_packet_tick = ao_profile_tick();
848 if (rx_data_cur < rx_data_count)
852 ao_wakeup(&ao_radio_wake);
860 ao_radio_rx_wait(void)
863 if (ao_radio_mcu_wake)
864 ao_radio_check_marc_status();
865 ao_arch_block_interrupts();
867 while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&
871 if (ao_sleep(&ao_radio_wake))
875 ao_arch_release_interrupts();
876 } while (ao_radio_mcu_wake);
879 rx_data_consumed += AO_FEC_DECODE_BLOCK;
881 return rx_data_cur - rx_data_consumed;
883 return AO_FEC_DECODE_BLOCK;
887 ao_radio_recv(__xdata void *d, uint8_t size)
893 static int been_here = 0;
895 size -= 2; /* status bytes */
896 if (size > AO_RADIO_MAX_RECV) {
897 ao_delay(AO_SEC_TO_TICKS(1));
901 rx_start_tick = ao_profile_tick();
904 len = size + 2; /* CRC bytes */
905 len += 1 + ~(len & 1); /* 1 or two pad bytes */
906 len *= 2; /* 1/2 rate convolution */
907 rx_data_count = len * 8; /* bytes to bits */
909 rx_data_consumed = 0;
912 /* Must be set before changing the frequency; any abort
913 * after the frequency is set needs to terminate the read
914 * so that the registers can be reprogrammed
918 /* configure interrupt pin */
920 ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
923 ao_radio_mcu_wake = 0;
925 AO_CC1120_SPI.cr2 = 0;
928 (void) AO_CC1120_SPI.dr;
930 /* Have the radio signal when the preamble quality goes high */
931 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_PQT_REACHED);
932 ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
933 AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_HIGH);
934 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr);
935 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
936 ao_exti_enable(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN);
938 ao_radio_strobe(CC1120_SRX);
940 /* Wait for the preamble to appear */
945 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT);
946 ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
947 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
949 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
950 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
952 ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
954 ret = ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait);
956 ao_radio_burst_read_stop();
959 ao_radio_strobe(CC1120_SIDLE);
961 /* Convert from 'real' rssi to cc1111-style values */
963 rssi = AO_RADIO_FROM_RSSI(ao_radio_reg_read(CC1120_RSSI1));
967 /* Store the received RSSI value; the crc-OK byte is already done */
969 ((uint8_t *) d)[size] = (uint8_t) rssi;
972 rx_last_done_tick = rx_done_tick;
973 rx_done_tick = ao_profile_tick();
975 ao_rx_start_tick = rx_start_tick;
976 ao_rx_packet_tick = rx_packet_tick;
977 ao_rx_done_tick = rx_done_tick;
978 ao_rx_last_done_tick = rx_last_done_tick;
986 static char *cc1120_state_name[] = {
987 [CC1120_STATUS_STATE_IDLE] = "IDLE",
988 [CC1120_STATUS_STATE_RX] = "RX",
989 [CC1120_STATUS_STATE_TX] = "TX",
990 [CC1120_STATUS_STATE_FSTXON] = "FSTXON",
991 [CC1120_STATUS_STATE_CALIBRATE] = "CALIBRATE",
992 [CC1120_STATUS_STATE_SETTLING] = "SETTLING",
993 [CC1120_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
994 [CC1120_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
997 struct ao_cc1120_reg {
1002 const static struct ao_cc1120_reg ao_cc1120_reg[] = {
1003 { .addr = CC1120_IOCFG3, .name = "IOCFG3" },
1004 { .addr = CC1120_IOCFG2, .name = "IOCFG2" },
1005 { .addr = CC1120_IOCFG1, .name = "IOCFG1" },
1006 { .addr = CC1120_IOCFG0, .name = "IOCFG0" },
1007 { .addr = CC1120_SYNC3, .name = "SYNC3" },
1008 { .addr = CC1120_SYNC2, .name = "SYNC2" },
1009 { .addr = CC1120_SYNC1, .name = "SYNC1" },
1010 { .addr = CC1120_SYNC0, .name = "SYNC0" },
1011 { .addr = CC1120_SYNC_CFG1, .name = "SYNC_CFG1" },
1012 { .addr = CC1120_SYNC_CFG0, .name = "SYNC_CFG0" },
1013 { .addr = CC1120_DEVIATION_M, .name = "DEVIATION_M" },
1014 { .addr = CC1120_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
1015 { .addr = CC1120_DCFILT_CFG, .name = "DCFILT_CFG" },
1016 { .addr = CC1120_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
1017 { .addr = CC1120_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
1018 { .addr = CC1120_FREQ_IF_CFG, .name = "FREQ_IF_CFG" },
1019 { .addr = CC1120_IQIC, .name = "IQIC" },
1020 { .addr = CC1120_CHAN_BW, .name = "CHAN_BW" },
1021 { .addr = CC1120_MDMCFG1, .name = "MDMCFG1" },
1022 { .addr = CC1120_MDMCFG0, .name = "MDMCFG0" },
1023 { .addr = CC1120_DRATE2, .name = "DRATE2" },
1024 { .addr = CC1120_DRATE1, .name = "DRATE1" },
1025 { .addr = CC1120_DRATE0, .name = "DRATE0" },
1026 { .addr = CC1120_AGC_REF, .name = "AGC_REF" },
1027 { .addr = CC1120_AGC_CS_THR, .name = "AGC_CS_THR" },
1028 { .addr = CC1120_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
1029 { .addr = CC1120_AGC_CFG3, .name = "AGC_CFG3" },
1030 { .addr = CC1120_AGC_CFG2, .name = "AGC_CFG2" },
1031 { .addr = CC1120_AGC_CFG1, .name = "AGC_CFG1" },
1032 { .addr = CC1120_AGC_CFG0, .name = "AGC_CFG0" },
1033 { .addr = CC1120_FIFO_CFG, .name = "FIFO_CFG" },
1034 { .addr = CC1120_DEV_ADDR, .name = "DEV_ADDR" },
1035 { .addr = CC1120_SETTLING_CFG, .name = "SETTLING_CFG" },
1036 { .addr = CC1120_FS_CFG, .name = "FS_CFG" },
1037 { .addr = CC1120_WOR_CFG1, .name = "WOR_CFG1" },
1038 { .addr = CC1120_WOR_CFG0, .name = "WOR_CFG0" },
1039 { .addr = CC1120_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
1040 { .addr = CC1120_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
1041 { .addr = CC1120_PKT_CFG2, .name = "PKT_CFG2" },
1042 { .addr = CC1120_PKT_CFG1, .name = "PKT_CFG1" },
1043 { .addr = CC1120_PKT_CFG0, .name = "PKT_CFG0" },
1044 { .addr = CC1120_RFEND_CFG1, .name = "RFEND_CFG1" },
1045 { .addr = CC1120_RFEND_CFG0, .name = "RFEND_CFG0" },
1046 { .addr = CC1120_PA_CFG2, .name = "PA_CFG2" },
1047 { .addr = CC1120_PA_CFG1, .name = "PA_CFG1" },
1048 { .addr = CC1120_PA_CFG0, .name = "PA_CFG0" },
1049 { .addr = CC1120_PKT_LEN, .name = "PKT_LEN" },
1050 { .addr = CC1120_IF_MIX_CFG, .name = "IF_MIX_CFG" },
1051 { .addr = CC1120_FREQOFF_CFG, .name = "FREQOFF_CFG" },
1052 { .addr = CC1120_TOC_CFG, .name = "TOC_CFG" },
1053 { .addr = CC1120_MARC_SPARE, .name = "MARC_SPARE" },
1054 { .addr = CC1120_ECG_CFG, .name = "ECG_CFG" },
1055 { .addr = CC1120_SOFT_TX_DATA_CFG, .name = "SOFT_TX_DATA_CFG" },
1056 { .addr = CC1120_EXT_CTRL, .name = "EXT_CTRL" },
1057 { .addr = CC1120_RCCAL_FINE, .name = "RCCAL_FINE" },
1058 { .addr = CC1120_RCCAL_COARSE, .name = "RCCAL_COARSE" },
1059 { .addr = CC1120_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
1060 { .addr = CC1120_FREQOFF1, .name = "FREQOFF1" },
1061 { .addr = CC1120_FREQOFF0, .name = "FREQOFF0" },
1062 { .addr = CC1120_FREQ2, .name = "FREQ2" },
1063 { .addr = CC1120_FREQ1, .name = "FREQ1" },
1064 { .addr = CC1120_FREQ0, .name = "FREQ0" },
1065 { .addr = CC1120_IF_ADC2, .name = "IF_ADC2" },
1066 { .addr = CC1120_IF_ADC1, .name = "IF_ADC1" },
1067 { .addr = CC1120_IF_ADC0, .name = "IF_ADC0" },
1068 { .addr = CC1120_FS_DIG1, .name = "FS_DIG1" },
1069 { .addr = CC1120_FS_DIG0, .name = "FS_DIG0" },
1070 { .addr = CC1120_FS_CAL3, .name = "FS_CAL3" },
1071 { .addr = CC1120_FS_CAL2, .name = "FS_CAL2" },
1072 { .addr = CC1120_FS_CAL1, .name = "FS_CAL1" },
1073 { .addr = CC1120_FS_CAL0, .name = "FS_CAL0" },
1074 { .addr = CC1120_FS_CHP, .name = "FS_CHP" },
1075 { .addr = CC1120_FS_DIVTWO, .name = "FS_DIVTWO" },
1076 { .addr = CC1120_FS_DSM1, .name = "FS_DSM1" },
1077 { .addr = CC1120_FS_DSM0, .name = "FS_DSM0" },
1078 { .addr = CC1120_FS_DVC1, .name = "FS_DVC1" },
1079 { .addr = CC1120_FS_DVC0, .name = "FS_DVC0" },
1080 { .addr = CC1120_FS_LBI, .name = "FS_LBI" },
1081 { .addr = CC1120_FS_PFD, .name = "FS_PFD" },
1082 { .addr = CC1120_FS_PRE, .name = "FS_PRE" },
1083 { .addr = CC1120_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
1084 { .addr = CC1120_FS_SPARE, .name = "FS_SPARE" },
1085 { .addr = CC1120_FS_VCO4, .name = "FS_VCO4" },
1086 { .addr = CC1120_FS_VCO3, .name = "FS_VCO3" },
1087 { .addr = CC1120_FS_VCO2, .name = "FS_VCO2" },
1088 { .addr = CC1120_FS_VCO1, .name = "FS_VCO1" },
1089 { .addr = CC1120_FS_VCO0, .name = "FS_VCO0" },
1090 { .addr = CC1120_GBIAS6, .name = "GBIAS6" },
1091 { .addr = CC1120_GBIAS5, .name = "GBIAS5" },
1092 { .addr = CC1120_GBIAS4, .name = "GBIAS4" },
1093 { .addr = CC1120_GBIAS3, .name = "GBIAS3" },
1094 { .addr = CC1120_GBIAS2, .name = "GBIAS2" },
1095 { .addr = CC1120_GBIAS1, .name = "GBIAS1" },
1096 { .addr = CC1120_GBIAS0, .name = "GBIAS0" },
1097 { .addr = CC1120_IFAMP, .name = "IFAMP" },
1098 { .addr = CC1120_LNA, .name = "LNA" },
1099 { .addr = CC1120_RXMIX, .name = "RXMIX" },
1100 { .addr = CC1120_XOSC5, .name = "XOSC5" },
1101 { .addr = CC1120_XOSC4, .name = "XOSC4" },
1102 { .addr = CC1120_XOSC3, .name = "XOSC3" },
1103 { .addr = CC1120_XOSC2, .name = "XOSC2" },
1104 { .addr = CC1120_XOSC1, .name = "XOSC1" },
1105 { .addr = CC1120_XOSC0, .name = "XOSC0" },
1106 { .addr = CC1120_ANALOG_SPARE, .name = "ANALOG_SPARE" },
1107 { .addr = CC1120_PA_CFG3, .name = "PA_CFG3" },
1108 { .addr = CC1120_WOR_TIME1, .name = "WOR_TIME1" },
1109 { .addr = CC1120_WOR_TIME0, .name = "WOR_TIME0" },
1110 { .addr = CC1120_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
1111 { .addr = CC1120_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
1112 { .addr = CC1120_BIST, .name = "BIST" },
1113 { .addr = CC1120_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
1114 { .addr = CC1120_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
1115 { .addr = CC1120_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
1116 { .addr = CC1120_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
1117 { .addr = CC1120_IQIE_I1, .name = "IQIE_I1" },
1118 { .addr = CC1120_IQIE_I0, .name = "IQIE_I0" },
1119 { .addr = CC1120_IQIE_Q1, .name = "IQIE_Q1" },
1120 { .addr = CC1120_IQIE_Q0, .name = "IQIE_Q0" },
1121 { .addr = CC1120_RSSI1, .name = "RSSI1" },
1122 { .addr = CC1120_RSSI0, .name = "RSSI0" },
1123 { .addr = CC1120_MARCSTATE, .name = "MARCSTATE" },
1124 { .addr = CC1120_LQI_VAL, .name = "LQI_VAL" },
1125 { .addr = CC1120_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
1126 { .addr = CC1120_DEM_STATUS, .name = "DEM_STATUS" },
1127 { .addr = CC1120_FREQOFF_EST1, .name = "FREQOFF_EST1" },
1128 { .addr = CC1120_FREQOFF_EST0, .name = "FREQOFF_EST0" },
1129 { .addr = CC1120_AGC_GAIN3, .name = "AGC_GAIN3" },
1130 { .addr = CC1120_AGC_GAIN2, .name = "AGC_GAIN2" },
1131 { .addr = CC1120_AGC_GAIN1, .name = "AGC_GAIN1" },
1132 { .addr = CC1120_AGC_GAIN0, .name = "AGC_GAIN0" },
1133 { .addr = CC1120_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
1134 { .addr = CC1120_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
1135 { .addr = CC1120_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
1136 { .addr = CC1120_RNDGEN, .name = "RNDGEN" },
1137 { .addr = CC1120_MAGN2, .name = "MAGN2" },
1138 { .addr = CC1120_MAGN1, .name = "MAGN1" },
1139 { .addr = CC1120_MAGN0, .name = "MAGN0" },
1140 { .addr = CC1120_ANG1, .name = "ANG1" },
1141 { .addr = CC1120_ANG0, .name = "ANG0" },
1142 { .addr = CC1120_CHFILT_I2, .name = "CHFILT_I2" },
1143 { .addr = CC1120_CHFILT_I1, .name = "CHFILT_I1" },
1144 { .addr = CC1120_CHFILT_I0, .name = "CHFILT_I0" },
1145 { .addr = CC1120_CHFILT_Q2, .name = "CHFILT_Q2" },
1146 { .addr = CC1120_CHFILT_Q1, .name = "CHFILT_Q1" },
1147 { .addr = CC1120_CHFILT_Q0, .name = "CHFILT_Q0" },
1148 { .addr = CC1120_GPIO_STATUS, .name = "GPIO_STATUS" },
1149 { .addr = CC1120_FSCAL_CTRL, .name = "FSCAL_CTRL" },
1150 { .addr = CC1120_PHASE_ADJUST, .name = "PHASE_ADJUST" },
1151 { .addr = CC1120_PARTNUMBER, .name = "PARTNUMBER" },
1152 { .addr = CC1120_PARTVERSION, .name = "PARTVERSION" },
1153 { .addr = CC1120_SERIAL_STATUS, .name = "SERIAL_STATUS" },
1154 { .addr = CC1120_RX_STATUS, .name = "RX_STATUS" },
1155 { .addr = CC1120_TX_STATUS, .name = "TX_STATUS" },
1156 { .addr = CC1120_MARC_STATUS1, .name = "MARC_STATUS1" },
1157 { .addr = CC1120_MARC_STATUS0, .name = "MARC_STATUS0" },
1158 { .addr = CC1120_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
1159 { .addr = CC1120_FSRF_TEST, .name = "FSRF_TEST" },
1160 { .addr = CC1120_PRE_TEST, .name = "PRE_TEST" },
1161 { .addr = CC1120_PRE_OVR, .name = "PRE_OVR" },
1162 { .addr = CC1120_ADC_TEST, .name = "ADC_TEST" },
1163 { .addr = CC1120_DVC_TEST, .name = "DVC_TEST" },
1164 { .addr = CC1120_ATEST, .name = "ATEST" },
1165 { .addr = CC1120_ATEST_LVDS, .name = "ATEST_LVDS" },
1166 { .addr = CC1120_ATEST_MODE, .name = "ATEST_MODE" },
1167 { .addr = CC1120_XOSC_TEST1, .name = "XOSC_TEST1" },
1168 { .addr = CC1120_XOSC_TEST0, .name = "XOSC_TEST0" },
1169 { .addr = CC1120_RXFIRST, .name = "RXFIRST" },
1170 { .addr = CC1120_TXFIRST, .name = "TXFIRST" },
1171 { .addr = CC1120_RXLAST, .name = "RXLAST" },
1172 { .addr = CC1120_TXLAST, .name = "TXLAST" },
1173 { .addr = CC1120_NUM_TXBYTES, .name = "NUM_TXBYTES" },
1174 { .addr = CC1120_NUM_RXBYTES, .name = "NUM_RXBYTES" },
1175 { .addr = CC1120_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
1176 { .addr = CC1120_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
1179 #define AO_NUM_CC1120_REG (sizeof ao_cc1120_reg / sizeof ao_cc1120_reg[0])
1181 static void ao_radio_show(void) {
1182 uint8_t status = ao_radio_status();
1186 status = ao_radio_status();
1187 printf ("Status: %02x\n", status);
1188 printf ("CHIP_RDY: %d\n", (status >> CC1120_STATUS_CHIP_RDY) & 1);
1189 printf ("STATE: %s\n", cc1120_state_name[(status >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK]);
1190 printf ("MARC: %02x\n", ao_radio_get_marc_status());
1192 for (i = 0; i < AO_NUM_CC1120_REG; i++)
1193 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name);
1197 static void ao_radio_beep(void) {
1201 static void ao_radio_packet(void) {
1202 static const uint8_t packet[] = {
1204 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1205 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1206 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1207 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1213 ao_radio_send(packet, sizeof (packet));
1217 ao_radio_test_recv()
1222 if (ao_radio_recv(bytes, 34)) {
1223 if (bytes[33] & 0x80)
1227 printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32]));
1228 for (b = 0; b < 32; b++)
1229 printf (" %02x", bytes[b]);
1235 #include <ao_aprs.h>
1240 ao_packet_slave_stop();
1247 static const struct ao_cmds ao_radio_cmds[] = {
1248 { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
1251 { ao_radio_aprs, "G\0Send APRS packet" },
1253 { ao_radio_show, "R\0Show CC1120 status" },
1254 { ao_radio_beep, "b\0Emit an RDF beacon" },
1255 { ao_radio_packet, "p\0Send a test packet" },
1256 { ao_radio_test_recv, "q\0Recv a test packet" },
1266 ao_radio_configured = 0;
1267 ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN));
1270 AO_CC1120_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN));
1271 for (i = 0; i < 10000; i++) {
1272 if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0)
1275 AO_CC1120_SPI_CS_PORT->bsrr = (1 << AO_CC1120_SPI_CS_PIN);
1277 ao_panic(AO_PANIC_SELF_TEST_CC1120);
1280 /* Enable the EXTI interrupt for the appropriate pin */
1281 ao_enable_port(AO_CC1120_INT_PORT);
1282 ao_exti_setup(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1283 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
1286 /* Enable the hacked up GPIO3 pin */
1287 ao_enable_port(AO_CC1120_MCU_WAKEUP_PORT);
1288 ao_exti_setup(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN,
1289 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED,
1290 ao_radio_mcu_wakeup_isr);
1292 ao_cmd_register(&ao_radio_cmds[0]);