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 int8_t ao_radio_rssi; /* Last received RSSI value */
37 #define CC1120_DEBUG AO_FEC_DEBUG
38 #define CC1120_TRACE 0
40 extern const uint32_t ao_radio_cal;
44 #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)
45 #define ao_radio_deselect() ao_spi_put_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS)
46 #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1120_SPI_BUS)
47 #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1120_SPI_BUS)
48 #define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1120_SPI_BUS)
49 #define ao_radio_duplex(o,i,l) ao_spi_duplex((o), (i), (l), AO_CC1120_SPI_BUS)
52 ao_radio_reg_read(uint16_t addr)
58 printf("\t\tao_radio_reg_read (%04x): ", addr); flush();
60 if (CC1120_IS_EXTENDED(addr)) {
61 data[0] = ((1 << CC1120_READ) |
67 data[0] = ((1 << CC1120_READ) |
73 ao_radio_spi_send(data, d);
74 ao_radio_spi_recv(data, 1);
77 printf (" %02x\n", data[0]);
83 ao_radio_reg_write(uint16_t addr, uint8_t value)
89 printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value);
91 if (CC1120_IS_EXTENDED(addr)) {
92 data[0] = ((0 << CC1120_READ) |
98 data[0] = ((0 << CC1120_READ) |
105 ao_radio_spi_send(data, d+1);
110 ao_radio_burst_read_start (uint16_t addr)
115 if (CC1120_IS_EXTENDED(addr)) {
116 data[0] = ((1 << CC1120_READ) |
117 (1 << CC1120_BURST) |
122 data[0] = ((1 << CC1120_READ) |
123 (1 << CC1120_BURST) |
128 ao_radio_spi_send(data, d);
132 ao_radio_burst_read_stop (void)
139 ao_radio_strobe(uint8_t addr)
144 printf("\t\tao_radio_strobe (%02x): ", addr); flush();
147 ao_radio_duplex(&addr, &in, 1);
150 printf("%02x\n", in); flush();
156 ao_radio_fifo_read(uint8_t *data, uint8_t len)
158 uint8_t addr = ((1 << CC1120_READ) |
159 (1 << CC1120_BURST) |
164 ao_radio_duplex(&addr, &status, 1);
165 ao_radio_spi_recv(data, len);
171 ao_radio_fifo_write_start(void)
173 uint8_t addr = ((0 << CC1120_READ) |
174 (1 << CC1120_BURST) |
179 ao_radio_duplex(&addr, &status, 1);
183 static inline uint8_t ao_radio_fifo_write_stop(uint8_t status) {
189 ao_radio_fifo_write(uint8_t *data, uint8_t len)
191 uint8_t status = ao_radio_fifo_write_start();
192 ao_radio_spi_send(data, len);
193 return ao_radio_fifo_write_stop(status);
197 ao_radio_fifo_write_fixed(uint8_t data, uint8_t len)
199 uint8_t status = ao_radio_fifo_write_start();
200 ao_radio_spi_send_fixed(data, len);
201 return ao_radio_fifo_write_stop(status);
205 ao_radio_tx_fifo_space(void)
207 return CC1120_FIFO_SIZE - ao_radio_reg_read(CC1120_NUM_TXBYTES);
211 ao_radio_status(void)
213 return ao_radio_strobe (CC1120_SNOP);
217 ao_radio_recv_abort(void)
220 ao_wakeup(&ao_radio_wake);
223 #define ao_radio_rdf_value 0x55
226 ao_radio_get_marc_status(void)
228 return ao_radio_reg_read(CC1120_MARC_STATUS1);
232 ao_radio_mcu_wakeup_isr(void)
234 ao_radio_mcu_wake = 1;
235 ao_wakeup(&ao_radio_wake);
240 ao_radio_check_marc_status(void)
242 ao_radio_mcu_wake = 0;
243 ao_radio_marc_status = ao_radio_get_marc_status();
245 /* Anyt other than 'tx/rx finished' means an error occurred */
246 if (ao_radio_marc_status & ~(CC1120_MARC_STATUS1_TX_FINISHED|CC1120_MARC_STATUS1_RX_FINISHED))
248 if (ao_radio_marc_status & (CC1120_MARC_STATUS1_TX_FINISHED))
249 ao_radio_tx_finished = 1;
255 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
257 ao_wakeup(&ao_radio_wake);
261 ao_radio_start_tx(void)
263 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr);
264 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
265 ao_exti_enable(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN);
266 ao_radio_tx_finished = 0;
267 ao_radio_strobe(CC1120_STX);
274 uint8_t state = ao_radio_strobe(CC1120_SIDLE);
275 if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_IDLE)
277 if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_TX_FIFO_ERROR)
278 ao_radio_strobe(CC1120_SFTX);
280 /* Flush any pending TX bytes */
281 ao_radio_strobe(CC1120_SFTX);
285 * Packet deviation is 20.5kHz
287 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
289 * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz
292 #define PACKET_DEV_E 5
293 #define PACKET_DEV_M 80
296 * For our packet data, set the symbol rate to 38400 Baud
298 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
299 * Rdata = -------------------------------------- * fosc
303 * DATARATE_M = 239914
306 #define PACKET_DRATE_E 9
307 #define PACKET_DRATE_M 239914
309 static const uint16_t packet_setup[] = {
310 CC1120_DEVIATION_M, PACKET_DEV_M,
311 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
312 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
313 (PACKET_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
314 CC1120_DRATE2, ((PACKET_DRATE_E << CC1120_DRATE2_DATARATE_E) |
315 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
316 CC1120_DRATE1, ((PACKET_DRATE_M >> 8) & 0xff),
317 CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff),
318 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
319 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
320 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
321 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
322 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
323 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
324 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
325 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
326 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
327 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
328 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
329 AO_CC1120_MARC_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP,
332 static const uint16_t packet_tx_setup[] = {
333 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
334 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
335 AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG,
338 static const uint16_t packet_rx_setup[] = {
339 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
340 (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT)),
341 AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT,
345 * RDF deviation is 5kHz
347 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
349 * 32e6Hz / (2 ** 24) * (256 + 71) * (2 ** 3) = 4989
354 #define RDF_PACKET_LEN 50
357 * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
359 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
360 * Rdata = -------------------------------------- * fosc
366 * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
368 #define RDF_DRATE_E 5
369 #define RDF_DRATE_M 25166
370 #define RDF_PACKET_LEN 50
372 static const uint16_t rdf_setup[] = {
373 CC1120_DEVIATION_M, RDF_DEV_M,
374 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
375 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
376 (RDF_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
377 CC1120_DRATE2, ((RDF_DRATE_E << CC1120_DRATE2_DATARATE_E) |
378 (((RDF_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
379 CC1120_DRATE1, ((RDF_DRATE_M >> 8) & 0xff),
380 CC1120_DRATE0, ((RDF_DRATE_M >> 0) & 0xff),
381 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
382 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
383 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
384 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
385 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
386 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
387 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
388 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
389 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
390 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
391 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
395 * APRS deviation is 3kHz
397 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
399 * 32e6Hz / (2 ** 24) * (256 + 137) * (2 ** 2) = 2998Hz
403 #define APRS_DEV_M 137
406 * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate)
408 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
409 * Rdata = -------------------------------------- * fosc
412 * DATARATE_M = 239914
415 * Rdata = 9599.998593330383301
418 #define APRS_DRATE_E 7
419 #define APRS_DRATE_M 239914
421 static const uint16_t aprs_setup[] = {
422 CC1120_DEVIATION_M, APRS_DEV_M,
423 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
424 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
425 (APRS_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
426 CC1120_DRATE2, ((APRS_DRATE_E << CC1120_DRATE2_DATARATE_E) |
427 (((APRS_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
428 CC1120_DRATE1, ((APRS_DRATE_M >> 8) & 0xff),
429 CC1120_DRATE0, ((APRS_DRATE_M >> 0) & 0xff),
430 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
431 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
432 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
433 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
434 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
435 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
438 #define AO_PKT_CFG0_INFINITE ((0 << CC1120_PKT_CFG0_RESERVED7) | \
439 (CC1120_PKT_CFG0_LENGTH_CONFIG_INFINITE << CC1120_PKT_CFG0_LENGTH_CONFIG) | \
440 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | \
441 (0 << CC1120_PKT_CFG0_UART_MODE_EN) | \
442 (0 << CC1120_PKT_CFG0_UART_SWAP_EN))
444 #define AO_PKT_CFG0_FIXED ((0 << CC1120_PKT_CFG0_RESERVED7) | \
445 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) | \
446 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | \
447 (0 << CC1120_PKT_CFG0_UART_MODE_EN) | \
448 (0 << CC1120_PKT_CFG0_UART_SWAP_EN))
450 static uint16_t ao_radio_mode;
452 #define AO_RADIO_MODE_BITS_PACKET 1
453 #define AO_RADIO_MODE_BITS_PACKET_TX 2
454 #define AO_RADIO_MODE_BITS_TX_BUF 4
455 #define AO_RADIO_MODE_BITS_TX_FINISH 8
456 #define AO_RADIO_MODE_BITS_PACKET_RX 16
457 #define AO_RADIO_MODE_BITS_RDF 32
458 #define AO_RADIO_MODE_BITS_APRS 64
459 #define AO_RADIO_MODE_BITS_INFINITE 128
460 #define AO_RADIO_MODE_BITS_FIXED 256
462 #define AO_RADIO_MODE_NONE 0
463 #define AO_RADIO_MODE_PACKET_TX_BUF (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_BUF)
464 #define AO_RADIO_MODE_PACKET_TX_FINISH (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_FINISH)
465 #define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_RX)
466 #define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_TX_FINISH)
467 #define AO_RADIO_MODE_APRS_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
468 #define AO_RADIO_MODE_APRS_LAST_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_BUF)
469 #define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
472 ao_radio_set_mode(uint16_t new_mode)
477 if (new_mode == ao_radio_mode)
480 changes = new_mode & (~ao_radio_mode);
481 if (changes & AO_RADIO_MODE_BITS_PACKET)
482 for (i = 0; i < sizeof (packet_setup) / sizeof (packet_setup[0]); i += 2)
483 ao_radio_reg_write(packet_setup[i], packet_setup[i+1]);
485 if (changes & AO_RADIO_MODE_BITS_PACKET_TX)
486 for (i = 0; i < sizeof (packet_tx_setup) / sizeof (packet_tx_setup[0]); i += 2)
487 ao_radio_reg_write(packet_tx_setup[i], packet_tx_setup[i+1]);
489 if (changes & AO_RADIO_MODE_BITS_TX_BUF)
490 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_TXFIFO_THR);
492 if (changes & AO_RADIO_MODE_BITS_TX_FINISH)
493 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG);
495 if (changes & AO_RADIO_MODE_BITS_PACKET_RX)
496 for (i = 0; i < sizeof (packet_rx_setup) / sizeof (packet_rx_setup[0]); i += 2)
497 ao_radio_reg_write(packet_rx_setup[i], packet_rx_setup[i+1]);
499 if (changes & AO_RADIO_MODE_BITS_RDF)
500 for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2)
501 ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]);
503 if (changes & AO_RADIO_MODE_BITS_APRS)
504 for (i = 0; i < sizeof (aprs_setup) / sizeof (aprs_setup[0]); i += 2)
505 ao_radio_reg_write(aprs_setup[i], aprs_setup[i+1]);
507 if (changes & AO_RADIO_MODE_BITS_INFINITE)
508 ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_INFINITE);
510 if (changes & AO_RADIO_MODE_BITS_FIXED)
511 ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_FIXED);
513 ao_radio_mode = new_mode;
516 static const uint16_t radio_setup[] = {
517 #include "ao_cc1120_CC1120.h"
520 static uint8_t ao_radio_configured = 0;
527 ao_radio_strobe(CC1120_SRES);
529 for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2)
530 ao_radio_reg_write(radio_setup[i], radio_setup[i+1]);
536 ao_radio_configured = 1;
540 ao_radio_set_len(uint8_t len)
542 static uint8_t last_len;
544 if (len != last_len) {
545 ao_radio_reg_write(CC1120_PKT_LEN, len);
551 ao_radio_get(uint8_t len)
553 static uint32_t last_radio_setting;
555 ao_mutex_get(&ao_radio_mutex);
557 if (!ao_radio_configured)
559 if (ao_config.radio_setting != last_radio_setting) {
560 ao_radio_reg_write(CC1120_FREQ2, ao_config.radio_setting >> 16);
561 ao_radio_reg_write(CC1120_FREQ1, ao_config.radio_setting >> 8);
562 ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting);
563 last_radio_setting = ao_config.radio_setting;
565 ao_radio_set_len(len);
568 #define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
571 ao_rdf_start(uint8_t len)
576 ao_radio_set_mode(AO_RADIO_MODE_RDF);
586 ao_arch_block_interrupts();
587 while (!ao_radio_wake && !ao_radio_abort && !ao_radio_mcu_wake)
588 ao_sleep(&ao_radio_wake);
589 ao_arch_release_interrupts();
590 if (ao_radio_mcu_wake)
591 ao_radio_check_marc_status();
600 ao_rdf_start(AO_RADIO_RDF_LEN);
602 ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN);
608 ao_radio_continuity(uint8_t c)
613 ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN);
615 status = ao_radio_fifo_write_start();
616 for (i = 0; i < 3; i++) {
617 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
619 ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN);
621 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN);
623 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
624 status = ao_radio_fifo_write_stop(status);
630 ao_radio_rdf_abort(void)
633 ao_wakeup(&ao_radio_wake);
637 ao_radio_test_cmd(void)
640 static uint8_t radio_on;
642 if (ao_cmd_lex_c != '\n') {
644 mode = (uint8_t) ao_cmd_lex_u32;
647 if ((mode & 2) && !radio_on) {
649 ao_monitor_disable();
652 ao_packet_slave_stop();
655 ao_radio_set_mode(AO_RADIO_MODE_RDF);
656 ao_radio_strobe(CC1120_STX);
659 for (t = 0; t < 10; t++) {
660 printf ("status: %02x\n", ao_radio_status());
661 ao_delay(AO_MS_TO_TICKS(100));
668 printf ("Hit a character to stop..."); flush();
672 if ((mode & 1) && radio_on) {
683 ao_radio_wait_isr(uint16_t timeout)
687 ao_arch_block_interrupts();
688 while (!ao_radio_wake && !ao_radio_mcu_wake && !ao_radio_abort)
689 if (ao_sleep(&ao_radio_wake))
691 ao_arch_release_interrupts();
694 if (ao_radio_mcu_wake)
695 ao_radio_check_marc_status();
699 ao_radio_wait_tx(uint8_t wait_fifo)
701 uint8_t fifo_space = 0;
704 ao_radio_wait_isr(0);
707 fifo_space = ao_radio_tx_fifo_space();
708 } while (!fifo_space && !ao_radio_abort);
712 static uint8_t tx_data[(AO_RADIO_MAX_SEND + 4) * 2];
715 ao_radio_send(const void *d, uint8_t size)
718 uint8_t *e = tx_data;
725 encode_len = ao_fec_encode(d, size, tx_data);
727 ao_radio_get(encode_len);
731 /* Flush any pending TX bytes */
732 ao_radio_strobe(CC1120_SFTX);
735 fifo_space = CC1120_FIFO_SIZE;
737 this_len = encode_len;
740 if (this_len > fifo_space) {
741 this_len = fifo_space;
742 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_BUF);
744 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_FINISH);
747 ao_radio_fifo_write(e, this_len);
749 encode_len -= this_len;
755 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
758 fifo_space = ao_radio_wait_tx(encode_len != 0);
759 if (ao_radio_abort) {
764 while (started && !ao_radio_abort && !ao_radio_tx_finished)
765 ao_radio_wait_isr(0);
769 #define AO_RADIO_LOTS 64
772 ao_radio_send_aprs(ao_radio_fill_func fill)
774 uint8_t buf[AO_RADIO_LOTS], *b;
782 fifo_space = CC1120_FIFO_SIZE;
784 cnt = (*fill)(buf, sizeof(buf));
791 /* At the last buffer, set the total length */
793 ao_radio_set_len(total & 0xff);
797 uint8_t this_len = cnt;
799 /* Wait for some space in the fifo */
800 while (!ao_radio_abort && (fifo_space = ao_radio_tx_fifo_space()) == 0) {
802 ao_radio_wait_isr(0);
806 if (this_len > fifo_space)
807 this_len = fifo_space;
813 ao_radio_set_mode(AO_RADIO_MODE_APRS_LAST_BUF);
815 ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
817 ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
819 ao_radio_fifo_write(b, this_len);
826 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
828 if (ao_radio_abort) {
832 /* Wait for the transmitter to go idle */
834 ao_radio_wait_isr(0);
839 static uint8_t rx_data[(AO_RADIO_MAX_RECV + 4) * 2 * 8];
840 static uint16_t rx_data_count;
841 static uint16_t rx_data_consumed;
842 static uint16_t rx_data_cur;
843 static uint8_t rx_ignore;
844 static uint8_t rx_waiting;
847 static uint32_t rx_start_tick, rx_packet_tick, rx_done_tick, rx_last_done_tick;
849 uint32_t ao_rx_start_tick, ao_rx_packet_tick, ao_rx_done_tick, ao_rx_last_done_tick;
851 #include <ao_profile.h>
855 ao_radio_rx_isr(void)
859 d = AO_CC1120_SPI.dr;
860 AO_CC1120_SPI.dr = 0;
861 if (rx_ignore == 0) {
862 if (rx_data_cur >= rx_data_count)
863 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
865 rx_data[rx_data_cur++] = d;
866 if (rx_waiting && rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) {
869 rx_packet_tick = ao_profile_tick();
870 if (rx_data_cur < rx_data_count)
874 ao_wakeup(&ao_radio_wake);
882 ao_radio_rx_wait(void)
885 if (ao_radio_mcu_wake)
886 ao_radio_check_marc_status();
887 ao_alarm(AO_MS_TO_TICKS(100));
888 ao_arch_block_interrupts();
890 while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&
894 if (ao_sleep(&ao_radio_wake))
898 ao_arch_release_interrupts();
900 } while (ao_radio_mcu_wake);
903 rx_data_consumed += AO_FEC_DECODE_BLOCK;
905 return rx_data_cur - rx_data_consumed;
907 return AO_FEC_DECODE_BLOCK;
911 ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout)
915 uint8_t radio_rssi = 0;
918 static int been_here = 0;
920 size -= 2; /* status bytes */
921 if (size > AO_RADIO_MAX_RECV) {
922 ao_delay(AO_SEC_TO_TICKS(1));
926 rx_start_tick = ao_profile_tick();
929 len = size + 2; /* CRC bytes */
930 len += 1 + ~(len & 1); /* 1 or two pad bytes */
931 len *= 2; /* 1/2 rate convolution */
932 rx_data_count = len * 8; /* bytes to bits */
934 rx_data_consumed = 0;
937 /* Must be set before changing the frequency; any abort
938 * after the frequency is set needs to terminate the read
939 * so that the registers can be reprogrammed
943 /* configure interrupt pin */
945 ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
948 ao_radio_mcu_wake = 0;
950 AO_CC1120_SPI.cr2 = 0;
953 (void) AO_CC1120_SPI.dr;
955 /* Have the radio signal when the preamble quality goes high */
956 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_PQT_REACHED);
957 ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
958 AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_HIGH);
959 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr);
960 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
961 ao_exti_enable(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN);
963 ao_radio_strobe(CC1120_SRX);
965 /* Wait for the preamble to appear */
966 ao_radio_wait_isr(timeout);
967 if (ao_radio_abort) {
972 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT);
973 ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
974 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
976 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
977 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
979 ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
981 ret = ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait);
983 ao_radio_burst_read_stop();
986 /* Convert from 'real' rssi to cc1111-style values */
988 rssi0 = ao_radio_reg_read(CC1120_RSSI0);
990 int8_t rssi = ao_radio_reg_read(CC1120_RSSI1);
991 ao_radio_rssi = rssi;
993 /* Bound it to the representable range */
996 radio_rssi = AO_RADIO_FROM_RSSI (rssi);
999 ao_radio_strobe(CC1120_SIDLE);
1003 /* Store the received RSSI value; the crc-OK byte is already done */
1005 ((uint8_t *) d)[size] = radio_rssi;
1008 rx_last_done_tick = rx_done_tick;
1009 rx_done_tick = ao_profile_tick();
1011 ao_rx_start_tick = rx_start_tick;
1012 ao_rx_packet_tick = rx_packet_tick;
1013 ao_rx_done_tick = rx_done_tick;
1014 ao_rx_last_done_tick = rx_last_done_tick;
1022 static char *cc1120_state_name[] = {
1023 [CC1120_STATUS_STATE_IDLE] = "IDLE",
1024 [CC1120_STATUS_STATE_RX] = "RX",
1025 [CC1120_STATUS_STATE_TX] = "TX",
1026 [CC1120_STATUS_STATE_FSTXON] = "FSTXON",
1027 [CC1120_STATUS_STATE_CALIBRATE] = "CALIBRATE",
1028 [CC1120_STATUS_STATE_SETTLING] = "SETTLING",
1029 [CC1120_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
1030 [CC1120_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
1033 struct ao_cc1120_reg {
1038 const static struct ao_cc1120_reg ao_cc1120_reg[] = {
1039 { .addr = CC1120_IOCFG3, .name = "IOCFG3" },
1040 { .addr = CC1120_IOCFG2, .name = "IOCFG2" },
1041 { .addr = CC1120_IOCFG1, .name = "IOCFG1" },
1042 { .addr = CC1120_IOCFG0, .name = "IOCFG0" },
1043 { .addr = CC1120_SYNC3, .name = "SYNC3" },
1044 { .addr = CC1120_SYNC2, .name = "SYNC2" },
1045 { .addr = CC1120_SYNC1, .name = "SYNC1" },
1046 { .addr = CC1120_SYNC0, .name = "SYNC0" },
1047 { .addr = CC1120_SYNC_CFG1, .name = "SYNC_CFG1" },
1048 { .addr = CC1120_SYNC_CFG0, .name = "SYNC_CFG0" },
1049 { .addr = CC1120_DEVIATION_M, .name = "DEVIATION_M" },
1050 { .addr = CC1120_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
1051 { .addr = CC1120_DCFILT_CFG, .name = "DCFILT_CFG" },
1052 { .addr = CC1120_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
1053 { .addr = CC1120_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
1054 { .addr = CC1120_FREQ_IF_CFG, .name = "FREQ_IF_CFG" },
1055 { .addr = CC1120_IQIC, .name = "IQIC" },
1056 { .addr = CC1120_CHAN_BW, .name = "CHAN_BW" },
1057 { .addr = CC1120_MDMCFG1, .name = "MDMCFG1" },
1058 { .addr = CC1120_MDMCFG0, .name = "MDMCFG0" },
1059 { .addr = CC1120_DRATE2, .name = "DRATE2" },
1060 { .addr = CC1120_DRATE1, .name = "DRATE1" },
1061 { .addr = CC1120_DRATE0, .name = "DRATE0" },
1062 { .addr = CC1120_AGC_REF, .name = "AGC_REF" },
1063 { .addr = CC1120_AGC_CS_THR, .name = "AGC_CS_THR" },
1064 { .addr = CC1120_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
1065 { .addr = CC1120_AGC_CFG3, .name = "AGC_CFG3" },
1066 { .addr = CC1120_AGC_CFG2, .name = "AGC_CFG2" },
1067 { .addr = CC1120_AGC_CFG1, .name = "AGC_CFG1" },
1068 { .addr = CC1120_AGC_CFG0, .name = "AGC_CFG0" },
1069 { .addr = CC1120_FIFO_CFG, .name = "FIFO_CFG" },
1070 { .addr = CC1120_DEV_ADDR, .name = "DEV_ADDR" },
1071 { .addr = CC1120_SETTLING_CFG, .name = "SETTLING_CFG" },
1072 { .addr = CC1120_FS_CFG, .name = "FS_CFG" },
1073 { .addr = CC1120_WOR_CFG1, .name = "WOR_CFG1" },
1074 { .addr = CC1120_WOR_CFG0, .name = "WOR_CFG0" },
1075 { .addr = CC1120_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
1076 { .addr = CC1120_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
1077 { .addr = CC1120_PKT_CFG2, .name = "PKT_CFG2" },
1078 { .addr = CC1120_PKT_CFG1, .name = "PKT_CFG1" },
1079 { .addr = CC1120_PKT_CFG0, .name = "PKT_CFG0" },
1080 { .addr = CC1120_RFEND_CFG1, .name = "RFEND_CFG1" },
1081 { .addr = CC1120_RFEND_CFG0, .name = "RFEND_CFG0" },
1082 { .addr = CC1120_PA_CFG2, .name = "PA_CFG2" },
1083 { .addr = CC1120_PA_CFG1, .name = "PA_CFG1" },
1084 { .addr = CC1120_PA_CFG0, .name = "PA_CFG0" },
1085 { .addr = CC1120_PKT_LEN, .name = "PKT_LEN" },
1086 { .addr = CC1120_IF_MIX_CFG, .name = "IF_MIX_CFG" },
1087 { .addr = CC1120_FREQOFF_CFG, .name = "FREQOFF_CFG" },
1088 { .addr = CC1120_TOC_CFG, .name = "TOC_CFG" },
1089 { .addr = CC1120_MARC_SPARE, .name = "MARC_SPARE" },
1090 { .addr = CC1120_ECG_CFG, .name = "ECG_CFG" },
1091 { .addr = CC1120_SOFT_TX_DATA_CFG, .name = "SOFT_TX_DATA_CFG" },
1092 { .addr = CC1120_EXT_CTRL, .name = "EXT_CTRL" },
1093 { .addr = CC1120_RCCAL_FINE, .name = "RCCAL_FINE" },
1094 { .addr = CC1120_RCCAL_COARSE, .name = "RCCAL_COARSE" },
1095 { .addr = CC1120_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
1096 { .addr = CC1120_FREQOFF1, .name = "FREQOFF1" },
1097 { .addr = CC1120_FREQOFF0, .name = "FREQOFF0" },
1098 { .addr = CC1120_FREQ2, .name = "FREQ2" },
1099 { .addr = CC1120_FREQ1, .name = "FREQ1" },
1100 { .addr = CC1120_FREQ0, .name = "FREQ0" },
1101 { .addr = CC1120_IF_ADC2, .name = "IF_ADC2" },
1102 { .addr = CC1120_IF_ADC1, .name = "IF_ADC1" },
1103 { .addr = CC1120_IF_ADC0, .name = "IF_ADC0" },
1104 { .addr = CC1120_FS_DIG1, .name = "FS_DIG1" },
1105 { .addr = CC1120_FS_DIG0, .name = "FS_DIG0" },
1106 { .addr = CC1120_FS_CAL3, .name = "FS_CAL3" },
1107 { .addr = CC1120_FS_CAL2, .name = "FS_CAL2" },
1108 { .addr = CC1120_FS_CAL1, .name = "FS_CAL1" },
1109 { .addr = CC1120_FS_CAL0, .name = "FS_CAL0" },
1110 { .addr = CC1120_FS_CHP, .name = "FS_CHP" },
1111 { .addr = CC1120_FS_DIVTWO, .name = "FS_DIVTWO" },
1112 { .addr = CC1120_FS_DSM1, .name = "FS_DSM1" },
1113 { .addr = CC1120_FS_DSM0, .name = "FS_DSM0" },
1114 { .addr = CC1120_FS_DVC1, .name = "FS_DVC1" },
1115 { .addr = CC1120_FS_DVC0, .name = "FS_DVC0" },
1116 { .addr = CC1120_FS_LBI, .name = "FS_LBI" },
1117 { .addr = CC1120_FS_PFD, .name = "FS_PFD" },
1118 { .addr = CC1120_FS_PRE, .name = "FS_PRE" },
1119 { .addr = CC1120_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
1120 { .addr = CC1120_FS_SPARE, .name = "FS_SPARE" },
1121 { .addr = CC1120_FS_VCO4, .name = "FS_VCO4" },
1122 { .addr = CC1120_FS_VCO3, .name = "FS_VCO3" },
1123 { .addr = CC1120_FS_VCO2, .name = "FS_VCO2" },
1124 { .addr = CC1120_FS_VCO1, .name = "FS_VCO1" },
1125 { .addr = CC1120_FS_VCO0, .name = "FS_VCO0" },
1126 { .addr = CC1120_GBIAS6, .name = "GBIAS6" },
1127 { .addr = CC1120_GBIAS5, .name = "GBIAS5" },
1128 { .addr = CC1120_GBIAS4, .name = "GBIAS4" },
1129 { .addr = CC1120_GBIAS3, .name = "GBIAS3" },
1130 { .addr = CC1120_GBIAS2, .name = "GBIAS2" },
1131 { .addr = CC1120_GBIAS1, .name = "GBIAS1" },
1132 { .addr = CC1120_GBIAS0, .name = "GBIAS0" },
1133 { .addr = CC1120_IFAMP, .name = "IFAMP" },
1134 { .addr = CC1120_LNA, .name = "LNA" },
1135 { .addr = CC1120_RXMIX, .name = "RXMIX" },
1136 { .addr = CC1120_XOSC5, .name = "XOSC5" },
1137 { .addr = CC1120_XOSC4, .name = "XOSC4" },
1138 { .addr = CC1120_XOSC3, .name = "XOSC3" },
1139 { .addr = CC1120_XOSC2, .name = "XOSC2" },
1140 { .addr = CC1120_XOSC1, .name = "XOSC1" },
1141 { .addr = CC1120_XOSC0, .name = "XOSC0" },
1142 { .addr = CC1120_ANALOG_SPARE, .name = "ANALOG_SPARE" },
1143 { .addr = CC1120_PA_CFG3, .name = "PA_CFG3" },
1144 { .addr = CC1120_WOR_TIME1, .name = "WOR_TIME1" },
1145 { .addr = CC1120_WOR_TIME0, .name = "WOR_TIME0" },
1146 { .addr = CC1120_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
1147 { .addr = CC1120_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
1148 { .addr = CC1120_BIST, .name = "BIST" },
1149 { .addr = CC1120_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
1150 { .addr = CC1120_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
1151 { .addr = CC1120_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
1152 { .addr = CC1120_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
1153 { .addr = CC1120_IQIE_I1, .name = "IQIE_I1" },
1154 { .addr = CC1120_IQIE_I0, .name = "IQIE_I0" },
1155 { .addr = CC1120_IQIE_Q1, .name = "IQIE_Q1" },
1156 { .addr = CC1120_IQIE_Q0, .name = "IQIE_Q0" },
1157 { .addr = CC1120_RSSI1, .name = "RSSI1" },
1158 { .addr = CC1120_RSSI0, .name = "RSSI0" },
1159 { .addr = CC1120_MARCSTATE, .name = "MARCSTATE" },
1160 { .addr = CC1120_LQI_VAL, .name = "LQI_VAL" },
1161 { .addr = CC1120_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
1162 { .addr = CC1120_DEM_STATUS, .name = "DEM_STATUS" },
1163 { .addr = CC1120_FREQOFF_EST1, .name = "FREQOFF_EST1" },
1164 { .addr = CC1120_FREQOFF_EST0, .name = "FREQOFF_EST0" },
1165 { .addr = CC1120_AGC_GAIN3, .name = "AGC_GAIN3" },
1166 { .addr = CC1120_AGC_GAIN2, .name = "AGC_GAIN2" },
1167 { .addr = CC1120_AGC_GAIN1, .name = "AGC_GAIN1" },
1168 { .addr = CC1120_AGC_GAIN0, .name = "AGC_GAIN0" },
1169 { .addr = CC1120_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
1170 { .addr = CC1120_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
1171 { .addr = CC1120_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
1172 { .addr = CC1120_RNDGEN, .name = "RNDGEN" },
1173 { .addr = CC1120_MAGN2, .name = "MAGN2" },
1174 { .addr = CC1120_MAGN1, .name = "MAGN1" },
1175 { .addr = CC1120_MAGN0, .name = "MAGN0" },
1176 { .addr = CC1120_ANG1, .name = "ANG1" },
1177 { .addr = CC1120_ANG0, .name = "ANG0" },
1178 { .addr = CC1120_CHFILT_I2, .name = "CHFILT_I2" },
1179 { .addr = CC1120_CHFILT_I1, .name = "CHFILT_I1" },
1180 { .addr = CC1120_CHFILT_I0, .name = "CHFILT_I0" },
1181 { .addr = CC1120_CHFILT_Q2, .name = "CHFILT_Q2" },
1182 { .addr = CC1120_CHFILT_Q1, .name = "CHFILT_Q1" },
1183 { .addr = CC1120_CHFILT_Q0, .name = "CHFILT_Q0" },
1184 { .addr = CC1120_GPIO_STATUS, .name = "GPIO_STATUS" },
1185 { .addr = CC1120_FSCAL_CTRL, .name = "FSCAL_CTRL" },
1186 { .addr = CC1120_PHASE_ADJUST, .name = "PHASE_ADJUST" },
1187 { .addr = CC1120_PARTNUMBER, .name = "PARTNUMBER" },
1188 { .addr = CC1120_PARTVERSION, .name = "PARTVERSION" },
1189 { .addr = CC1120_SERIAL_STATUS, .name = "SERIAL_STATUS" },
1190 { .addr = CC1120_RX_STATUS, .name = "RX_STATUS" },
1191 { .addr = CC1120_TX_STATUS, .name = "TX_STATUS" },
1192 { .addr = CC1120_MARC_STATUS1, .name = "MARC_STATUS1" },
1193 { .addr = CC1120_MARC_STATUS0, .name = "MARC_STATUS0" },
1194 { .addr = CC1120_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
1195 { .addr = CC1120_FSRF_TEST, .name = "FSRF_TEST" },
1196 { .addr = CC1120_PRE_TEST, .name = "PRE_TEST" },
1197 { .addr = CC1120_PRE_OVR, .name = "PRE_OVR" },
1198 { .addr = CC1120_ADC_TEST, .name = "ADC_TEST" },
1199 { .addr = CC1120_DVC_TEST, .name = "DVC_TEST" },
1200 { .addr = CC1120_ATEST, .name = "ATEST" },
1201 { .addr = CC1120_ATEST_LVDS, .name = "ATEST_LVDS" },
1202 { .addr = CC1120_ATEST_MODE, .name = "ATEST_MODE" },
1203 { .addr = CC1120_XOSC_TEST1, .name = "XOSC_TEST1" },
1204 { .addr = CC1120_XOSC_TEST0, .name = "XOSC_TEST0" },
1205 { .addr = CC1120_RXFIRST, .name = "RXFIRST" },
1206 { .addr = CC1120_TXFIRST, .name = "TXFIRST" },
1207 { .addr = CC1120_RXLAST, .name = "RXLAST" },
1208 { .addr = CC1120_TXLAST, .name = "TXLAST" },
1209 { .addr = CC1120_NUM_TXBYTES, .name = "NUM_TXBYTES" },
1210 { .addr = CC1120_NUM_RXBYTES, .name = "NUM_RXBYTES" },
1211 { .addr = CC1120_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
1212 { .addr = CC1120_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
1215 #define AO_NUM_CC1120_REG (sizeof ao_cc1120_reg / sizeof ao_cc1120_reg[0])
1217 static void ao_radio_show(void) {
1218 uint8_t status = ao_radio_status();
1222 status = ao_radio_status();
1223 printf ("Status: %02x\n", status);
1224 printf ("CHIP_RDY: %d\n", (status >> CC1120_STATUS_CHIP_RDY) & 1);
1225 printf ("STATE: %s\n", cc1120_state_name[(status >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK]);
1226 printf ("MARC: %02x\n", ao_radio_get_marc_status());
1228 for (i = 0; i < AO_NUM_CC1120_REG; i++)
1229 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name);
1233 static void ao_radio_beep(void) {
1237 static void ao_radio_packet(void) {
1238 static const uint8_t packet[] = {
1240 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1241 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1242 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1243 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1249 ao_radio_send(packet, sizeof (packet));
1253 ao_radio_test_recv()
1258 if (ao_radio_recv(bytes, 34)) {
1259 if (bytes[33] & 0x80)
1263 printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32]));
1264 for (b = 0; b < 32; b++)
1265 printf (" %02x", bytes[b]);
1271 #include <ao_aprs.h>
1276 ao_packet_slave_stop();
1283 static const struct ao_cmds ao_radio_cmds[] = {
1284 { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
1287 { ao_radio_aprs, "G\0Send APRS packet" },
1289 { ao_radio_show, "R\0Show CC1120 status" },
1290 { ao_radio_beep, "b\0Emit an RDF beacon" },
1291 { ao_radio_packet, "p\0Send a test packet" },
1292 { ao_radio_test_recv, "q\0Recv a test packet" },
1302 ao_radio_configured = 0;
1303 ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN));
1306 AO_CC1120_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN));
1307 for (i = 0; i < 10000; i++) {
1308 if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0)
1311 AO_CC1120_SPI_CS_PORT->bsrr = (1 << AO_CC1120_SPI_CS_PIN);
1313 ao_panic(AO_PANIC_SELF_TEST_CC1120);
1316 /* Enable the EXTI interrupt for the appropriate pin */
1317 ao_enable_port(AO_CC1120_INT_PORT);
1318 ao_exti_setup(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1319 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
1322 /* Enable the hacked up GPIO3 pin */
1323 ao_enable_port(AO_CC1120_MCU_WAKEUP_PORT);
1324 ao_exti_setup(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN,
1325 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED,
1326 ao_radio_mcu_wakeup_isr);
1328 ao_cmd_register(&ao_radio_cmds[0]);