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 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
330 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
331 AO_CC1120_MARC_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP,
334 static const uint16_t packet_tx_setup[] = {
335 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
336 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
337 AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG,
340 static const uint16_t packet_rx_setup[] = {
341 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
342 (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT)),
343 AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT,
347 * RDF deviation is 5kHz
349 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
351 * 32e6Hz / (2 ** 24) * (256 + 71) * (2 ** 3) = 4989
356 #define RDF_PACKET_LEN 50
359 * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
361 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
362 * Rdata = -------------------------------------- * fosc
368 * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
370 #define RDF_DRATE_E 5
371 #define RDF_DRATE_M 25166
372 #define RDF_PACKET_LEN 50
374 static const uint16_t rdf_setup[] = {
375 CC1120_DEVIATION_M, RDF_DEV_M,
376 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
377 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
378 (RDF_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
379 CC1120_DRATE2, ((RDF_DRATE_E << CC1120_DRATE2_DATARATE_E) |
380 (((RDF_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
381 CC1120_DRATE1, ((RDF_DRATE_M >> 8) & 0xff),
382 CC1120_DRATE0, ((RDF_DRATE_M >> 0) & 0xff),
383 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
384 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
385 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
386 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
387 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
388 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
389 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
390 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
391 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
392 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
393 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
394 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
395 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
399 * APRS deviation is 3kHz
401 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
403 * 32e6Hz / (2 ** 24) * (256 + 137) * (2 ** 2) = 2998Hz
407 #define APRS_DEV_M 137
410 * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate)
412 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
413 * Rdata = -------------------------------------- * fosc
416 * DATARATE_M = 239914
419 * Rdata = 9599.998593330383301
422 #define APRS_DRATE_E 7
423 #define APRS_DRATE_M 239914
425 static const uint16_t aprs_setup[] = {
426 CC1120_DEVIATION_M, APRS_DEV_M,
427 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
428 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
429 (APRS_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
430 CC1120_DRATE2, ((APRS_DRATE_E << CC1120_DRATE2_DATARATE_E) |
431 (((APRS_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
432 CC1120_DRATE1, ((APRS_DRATE_M >> 8) & 0xff),
433 CC1120_DRATE0, ((APRS_DRATE_M >> 0) & 0xff),
434 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
435 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
436 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
437 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
438 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
439 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
440 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
441 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
444 #define AO_PKT_CFG0_INFINITE ((0 << CC1120_PKT_CFG0_RESERVED7) | \
445 (CC1120_PKT_CFG0_LENGTH_CONFIG_INFINITE << 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 #define AO_PKT_CFG0_FIXED ((0 << CC1120_PKT_CFG0_RESERVED7) | \
451 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) | \
452 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | \
453 (0 << CC1120_PKT_CFG0_UART_MODE_EN) | \
454 (0 << CC1120_PKT_CFG0_UART_SWAP_EN))
456 static uint16_t ao_radio_mode;
458 #define AO_RADIO_MODE_BITS_PACKET 1
459 #define AO_RADIO_MODE_BITS_PACKET_TX 2
460 #define AO_RADIO_MODE_BITS_TX_BUF 4
461 #define AO_RADIO_MODE_BITS_TX_FINISH 8
462 #define AO_RADIO_MODE_BITS_PACKET_RX 16
463 #define AO_RADIO_MODE_BITS_RDF 32
464 #define AO_RADIO_MODE_BITS_APRS 64
465 #define AO_RADIO_MODE_BITS_INFINITE 128
466 #define AO_RADIO_MODE_BITS_FIXED 256
468 #define AO_RADIO_MODE_NONE 0
469 #define AO_RADIO_MODE_PACKET_TX_BUF (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_BUF)
470 #define AO_RADIO_MODE_PACKET_TX_FINISH (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_FINISH)
471 #define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_RX)
472 #define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_TX_FINISH)
473 #define AO_RADIO_MODE_APRS_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
474 #define AO_RADIO_MODE_APRS_LAST_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_BUF)
475 #define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
478 ao_radio_set_mode(uint16_t new_mode)
483 if (new_mode == ao_radio_mode)
486 changes = new_mode & (~ao_radio_mode);
487 if (changes & AO_RADIO_MODE_BITS_PACKET)
488 for (i = 0; i < sizeof (packet_setup) / sizeof (packet_setup[0]); i += 2)
489 ao_radio_reg_write(packet_setup[i], packet_setup[i+1]);
491 if (changes & AO_RADIO_MODE_BITS_PACKET_TX)
492 for (i = 0; i < sizeof (packet_tx_setup) / sizeof (packet_tx_setup[0]); i += 2)
493 ao_radio_reg_write(packet_tx_setup[i], packet_tx_setup[i+1]);
495 if (changes & AO_RADIO_MODE_BITS_TX_BUF)
496 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_TXFIFO_THR);
498 if (changes & AO_RADIO_MODE_BITS_TX_FINISH)
499 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG);
501 if (changes & AO_RADIO_MODE_BITS_PACKET_RX)
502 for (i = 0; i < sizeof (packet_rx_setup) / sizeof (packet_rx_setup[0]); i += 2)
503 ao_radio_reg_write(packet_rx_setup[i], packet_rx_setup[i+1]);
505 if (changes & AO_RADIO_MODE_BITS_RDF)
506 for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2)
507 ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]);
509 if (changes & AO_RADIO_MODE_BITS_APRS)
510 for (i = 0; i < sizeof (aprs_setup) / sizeof (aprs_setup[0]); i += 2)
511 ao_radio_reg_write(aprs_setup[i], aprs_setup[i+1]);
513 if (changes & AO_RADIO_MODE_BITS_INFINITE)
514 ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_INFINITE);
516 if (changes & AO_RADIO_MODE_BITS_FIXED)
517 ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_FIXED);
519 ao_radio_mode = new_mode;
522 static const uint16_t radio_setup[] = {
523 #include "ao_cc1120_CC1120.h"
526 static uint8_t ao_radio_configured = 0;
533 ao_radio_strobe(CC1120_SRES);
535 for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2)
536 ao_radio_reg_write(radio_setup[i], radio_setup[i+1]);
542 ao_radio_configured = 1;
546 ao_radio_set_len(uint8_t len)
548 static uint8_t last_len;
550 if (len != last_len) {
551 ao_radio_reg_write(CC1120_PKT_LEN, len);
557 ao_radio_get(uint8_t len)
559 static uint32_t last_radio_setting;
561 ao_mutex_get(&ao_radio_mutex);
563 if (!ao_radio_configured)
565 if (ao_config.radio_setting != last_radio_setting) {
566 ao_radio_reg_write(CC1120_FREQ2, ao_config.radio_setting >> 16);
567 ao_radio_reg_write(CC1120_FREQ1, ao_config.radio_setting >> 8);
568 ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting);
569 last_radio_setting = ao_config.radio_setting;
571 ao_radio_set_len(len);
574 #define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
577 ao_rdf_start(uint8_t len)
582 ao_radio_set_mode(AO_RADIO_MODE_RDF);
592 ao_arch_block_interrupts();
593 while (!ao_radio_wake && !ao_radio_abort && !ao_radio_mcu_wake)
594 ao_sleep(&ao_radio_wake);
595 ao_arch_release_interrupts();
596 if (ao_radio_mcu_wake)
597 ao_radio_check_marc_status();
606 ao_rdf_start(AO_RADIO_RDF_LEN);
608 ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN);
614 ao_radio_continuity(uint8_t c)
619 ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN);
621 status = ao_radio_fifo_write_start();
622 for (i = 0; i < 3; i++) {
623 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
625 ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN);
627 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN);
629 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
630 status = ao_radio_fifo_write_stop(status);
636 ao_radio_rdf_abort(void)
639 ao_wakeup(&ao_radio_wake);
643 ao_radio_test_cmd(void)
646 static uint8_t radio_on;
648 if (ao_cmd_lex_c != '\n') {
650 mode = (uint8_t) ao_cmd_lex_u32;
653 if ((mode & 2) && !radio_on) {
655 ao_monitor_disable();
658 ao_packet_slave_stop();
661 ao_radio_set_mode(AO_RADIO_MODE_RDF);
662 ao_radio_strobe(CC1120_STX);
665 for (t = 0; t < 10; t++) {
666 printf ("status: %02x\n", ao_radio_status());
667 ao_delay(AO_MS_TO_TICKS(100));
674 printf ("Hit a character to stop..."); flush();
678 if ((mode & 1) && radio_on) {
689 ao_radio_wait_isr(uint16_t timeout)
693 ao_arch_block_interrupts();
694 while (!ao_radio_wake && !ao_radio_mcu_wake && !ao_radio_abort)
695 if (ao_sleep(&ao_radio_wake))
697 ao_arch_release_interrupts();
700 if (ao_radio_mcu_wake)
701 ao_radio_check_marc_status();
705 ao_radio_wait_tx(uint8_t wait_fifo)
707 uint8_t fifo_space = 0;
710 ao_radio_wait_isr(0);
713 fifo_space = ao_radio_tx_fifo_space();
714 } while (!fifo_space && !ao_radio_abort);
718 static uint8_t tx_data[(AO_RADIO_MAX_SEND + 4) * 2];
721 ao_radio_send(const void *d, uint8_t size)
724 uint8_t *e = tx_data;
731 encode_len = ao_fec_encode(d, size, tx_data);
733 ao_radio_get(encode_len);
737 /* Flush any pending TX bytes */
738 ao_radio_strobe(CC1120_SFTX);
741 fifo_space = CC1120_FIFO_SIZE;
743 this_len = encode_len;
746 if (this_len > fifo_space) {
747 this_len = fifo_space;
748 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_BUF);
750 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_FINISH);
753 ao_radio_fifo_write(e, this_len);
755 encode_len -= this_len;
761 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
764 fifo_space = ao_radio_wait_tx(encode_len != 0);
765 if (ao_radio_abort) {
770 while (started && !ao_radio_abort && !ao_radio_tx_finished)
771 ao_radio_wait_isr(0);
775 #define AO_RADIO_LOTS 64
778 ao_radio_send_aprs(ao_radio_fill_func fill)
780 uint8_t buf[AO_RADIO_LOTS], *b;
788 fifo_space = CC1120_FIFO_SIZE;
790 cnt = (*fill)(buf, sizeof(buf));
797 /* At the last buffer, set the total length */
799 ao_radio_set_len(total & 0xff);
803 uint8_t this_len = cnt;
805 /* Wait for some space in the fifo */
806 while (!ao_radio_abort && (fifo_space = ao_radio_tx_fifo_space()) == 0) {
808 ao_radio_wait_isr(0);
812 if (this_len > fifo_space)
813 this_len = fifo_space;
819 ao_radio_set_mode(AO_RADIO_MODE_APRS_LAST_BUF);
821 ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
823 ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
825 ao_radio_fifo_write(b, this_len);
832 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
834 if (ao_radio_abort) {
838 /* Wait for the transmitter to go idle */
840 ao_radio_wait_isr(0);
845 static uint8_t rx_data[(AO_RADIO_MAX_RECV + 4) * 2 * 8];
846 static uint16_t rx_data_count;
847 static uint16_t rx_data_consumed;
848 static uint16_t rx_data_cur;
849 static uint8_t rx_ignore;
850 static uint8_t rx_waiting;
853 static uint32_t rx_start_tick, rx_packet_tick, rx_done_tick, rx_last_done_tick;
855 uint32_t ao_rx_start_tick, ao_rx_packet_tick, ao_rx_done_tick, ao_rx_last_done_tick;
857 #include <ao_profile.h>
861 ao_radio_rx_isr(void)
865 d = AO_CC1120_SPI.dr;
866 AO_CC1120_SPI.dr = 0;
867 if (rx_ignore == 0) {
868 if (rx_data_cur >= rx_data_count)
869 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
871 rx_data[rx_data_cur++] = d;
872 if (rx_waiting && rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) {
875 rx_packet_tick = ao_profile_tick();
876 if (rx_data_cur < rx_data_count)
880 ao_wakeup(&ao_radio_wake);
888 ao_radio_rx_wait(void)
891 if (ao_radio_mcu_wake)
892 ao_radio_check_marc_status();
893 ao_alarm(AO_MS_TO_TICKS(100));
894 ao_arch_block_interrupts();
896 while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&
900 if (ao_sleep(&ao_radio_wake))
904 ao_arch_release_interrupts();
906 } while (ao_radio_mcu_wake);
909 rx_data_consumed += AO_FEC_DECODE_BLOCK;
911 return rx_data_cur - rx_data_consumed;
913 return AO_FEC_DECODE_BLOCK;
917 ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout)
921 uint8_t radio_rssi = 0;
924 static int been_here = 0;
926 size -= 2; /* status bytes */
927 if (size > AO_RADIO_MAX_RECV) {
928 ao_delay(AO_SEC_TO_TICKS(1));
932 rx_start_tick = ao_profile_tick();
935 len = size + 2; /* CRC bytes */
936 len += 1 + ~(len & 1); /* 1 or two pad bytes */
937 len *= 2; /* 1/2 rate convolution */
938 rx_data_count = len * 8; /* bytes to bits */
940 rx_data_consumed = 0;
943 /* Must be set before changing the frequency; any abort
944 * after the frequency is set needs to terminate the read
945 * so that the registers can be reprogrammed
949 /* configure interrupt pin */
951 ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
954 ao_radio_mcu_wake = 0;
956 AO_CC1120_SPI.cr2 = 0;
959 (void) AO_CC1120_SPI.dr;
961 /* Have the radio signal when the preamble quality goes high */
962 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_PQT_REACHED);
963 ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
964 AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_HIGH);
965 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr);
966 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
967 ao_exti_enable(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN);
969 ao_radio_strobe(CC1120_SRX);
971 /* Wait for the preamble to appear */
972 ao_radio_wait_isr(timeout);
973 if (ao_radio_abort) {
978 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT);
979 ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
980 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
982 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
983 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
985 ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
987 ret = ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait);
989 ao_radio_burst_read_stop();
992 /* Convert from 'real' rssi to cc1111-style values */
994 rssi0 = ao_radio_reg_read(CC1120_RSSI0);
996 int8_t rssi = ao_radio_reg_read(CC1120_RSSI1);
997 ao_radio_rssi = rssi;
999 /* Bound it to the representable range */
1002 radio_rssi = AO_RADIO_FROM_RSSI (rssi);
1005 ao_radio_strobe(CC1120_SIDLE);
1009 /* Store the received RSSI value; the crc-OK byte is already done */
1011 ((uint8_t *) d)[size] = radio_rssi;
1014 rx_last_done_tick = rx_done_tick;
1015 rx_done_tick = ao_profile_tick();
1017 ao_rx_start_tick = rx_start_tick;
1018 ao_rx_packet_tick = rx_packet_tick;
1019 ao_rx_done_tick = rx_done_tick;
1020 ao_rx_last_done_tick = rx_last_done_tick;
1028 static char *cc1120_state_name[] = {
1029 [CC1120_STATUS_STATE_IDLE] = "IDLE",
1030 [CC1120_STATUS_STATE_RX] = "RX",
1031 [CC1120_STATUS_STATE_TX] = "TX",
1032 [CC1120_STATUS_STATE_FSTXON] = "FSTXON",
1033 [CC1120_STATUS_STATE_CALIBRATE] = "CALIBRATE",
1034 [CC1120_STATUS_STATE_SETTLING] = "SETTLING",
1035 [CC1120_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
1036 [CC1120_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
1039 struct ao_cc1120_reg {
1044 const static struct ao_cc1120_reg ao_cc1120_reg[] = {
1045 { .addr = CC1120_IOCFG3, .name = "IOCFG3" },
1046 { .addr = CC1120_IOCFG2, .name = "IOCFG2" },
1047 { .addr = CC1120_IOCFG1, .name = "IOCFG1" },
1048 { .addr = CC1120_IOCFG0, .name = "IOCFG0" },
1049 { .addr = CC1120_SYNC3, .name = "SYNC3" },
1050 { .addr = CC1120_SYNC2, .name = "SYNC2" },
1051 { .addr = CC1120_SYNC1, .name = "SYNC1" },
1052 { .addr = CC1120_SYNC0, .name = "SYNC0" },
1053 { .addr = CC1120_SYNC_CFG1, .name = "SYNC_CFG1" },
1054 { .addr = CC1120_SYNC_CFG0, .name = "SYNC_CFG0" },
1055 { .addr = CC1120_DEVIATION_M, .name = "DEVIATION_M" },
1056 { .addr = CC1120_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
1057 { .addr = CC1120_DCFILT_CFG, .name = "DCFILT_CFG" },
1058 { .addr = CC1120_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
1059 { .addr = CC1120_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
1060 { .addr = CC1120_FREQ_IF_CFG, .name = "FREQ_IF_CFG" },
1061 { .addr = CC1120_IQIC, .name = "IQIC" },
1062 { .addr = CC1120_CHAN_BW, .name = "CHAN_BW" },
1063 { .addr = CC1120_MDMCFG1, .name = "MDMCFG1" },
1064 { .addr = CC1120_MDMCFG0, .name = "MDMCFG0" },
1065 { .addr = CC1120_DRATE2, .name = "DRATE2" },
1066 { .addr = CC1120_DRATE1, .name = "DRATE1" },
1067 { .addr = CC1120_DRATE0, .name = "DRATE0" },
1068 { .addr = CC1120_AGC_REF, .name = "AGC_REF" },
1069 { .addr = CC1120_AGC_CS_THR, .name = "AGC_CS_THR" },
1070 { .addr = CC1120_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
1071 { .addr = CC1120_AGC_CFG3, .name = "AGC_CFG3" },
1072 { .addr = CC1120_AGC_CFG2, .name = "AGC_CFG2" },
1073 { .addr = CC1120_AGC_CFG1, .name = "AGC_CFG1" },
1074 { .addr = CC1120_AGC_CFG0, .name = "AGC_CFG0" },
1075 { .addr = CC1120_FIFO_CFG, .name = "FIFO_CFG" },
1076 { .addr = CC1120_DEV_ADDR, .name = "DEV_ADDR" },
1077 { .addr = CC1120_SETTLING_CFG, .name = "SETTLING_CFG" },
1078 { .addr = CC1120_FS_CFG, .name = "FS_CFG" },
1079 { .addr = CC1120_WOR_CFG1, .name = "WOR_CFG1" },
1080 { .addr = CC1120_WOR_CFG0, .name = "WOR_CFG0" },
1081 { .addr = CC1120_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
1082 { .addr = CC1120_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
1083 { .addr = CC1120_PKT_CFG2, .name = "PKT_CFG2" },
1084 { .addr = CC1120_PKT_CFG1, .name = "PKT_CFG1" },
1085 { .addr = CC1120_PKT_CFG0, .name = "PKT_CFG0" },
1086 { .addr = CC1120_RFEND_CFG1, .name = "RFEND_CFG1" },
1087 { .addr = CC1120_RFEND_CFG0, .name = "RFEND_CFG0" },
1088 { .addr = CC1120_PA_CFG2, .name = "PA_CFG2" },
1089 { .addr = CC1120_PA_CFG1, .name = "PA_CFG1" },
1090 { .addr = CC1120_PA_CFG0, .name = "PA_CFG0" },
1091 { .addr = CC1120_PKT_LEN, .name = "PKT_LEN" },
1092 { .addr = CC1120_IF_MIX_CFG, .name = "IF_MIX_CFG" },
1093 { .addr = CC1120_FREQOFF_CFG, .name = "FREQOFF_CFG" },
1094 { .addr = CC1120_TOC_CFG, .name = "TOC_CFG" },
1095 { .addr = CC1120_MARC_SPARE, .name = "MARC_SPARE" },
1096 { .addr = CC1120_ECG_CFG, .name = "ECG_CFG" },
1097 { .addr = CC1120_SOFT_TX_DATA_CFG, .name = "SOFT_TX_DATA_CFG" },
1098 { .addr = CC1120_EXT_CTRL, .name = "EXT_CTRL" },
1099 { .addr = CC1120_RCCAL_FINE, .name = "RCCAL_FINE" },
1100 { .addr = CC1120_RCCAL_COARSE, .name = "RCCAL_COARSE" },
1101 { .addr = CC1120_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
1102 { .addr = CC1120_FREQOFF1, .name = "FREQOFF1" },
1103 { .addr = CC1120_FREQOFF0, .name = "FREQOFF0" },
1104 { .addr = CC1120_FREQ2, .name = "FREQ2" },
1105 { .addr = CC1120_FREQ1, .name = "FREQ1" },
1106 { .addr = CC1120_FREQ0, .name = "FREQ0" },
1107 { .addr = CC1120_IF_ADC2, .name = "IF_ADC2" },
1108 { .addr = CC1120_IF_ADC1, .name = "IF_ADC1" },
1109 { .addr = CC1120_IF_ADC0, .name = "IF_ADC0" },
1110 { .addr = CC1120_FS_DIG1, .name = "FS_DIG1" },
1111 { .addr = CC1120_FS_DIG0, .name = "FS_DIG0" },
1112 { .addr = CC1120_FS_CAL3, .name = "FS_CAL3" },
1113 { .addr = CC1120_FS_CAL2, .name = "FS_CAL2" },
1114 { .addr = CC1120_FS_CAL1, .name = "FS_CAL1" },
1115 { .addr = CC1120_FS_CAL0, .name = "FS_CAL0" },
1116 { .addr = CC1120_FS_CHP, .name = "FS_CHP" },
1117 { .addr = CC1120_FS_DIVTWO, .name = "FS_DIVTWO" },
1118 { .addr = CC1120_FS_DSM1, .name = "FS_DSM1" },
1119 { .addr = CC1120_FS_DSM0, .name = "FS_DSM0" },
1120 { .addr = CC1120_FS_DVC1, .name = "FS_DVC1" },
1121 { .addr = CC1120_FS_DVC0, .name = "FS_DVC0" },
1122 { .addr = CC1120_FS_LBI, .name = "FS_LBI" },
1123 { .addr = CC1120_FS_PFD, .name = "FS_PFD" },
1124 { .addr = CC1120_FS_PRE, .name = "FS_PRE" },
1125 { .addr = CC1120_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
1126 { .addr = CC1120_FS_SPARE, .name = "FS_SPARE" },
1127 { .addr = CC1120_FS_VCO4, .name = "FS_VCO4" },
1128 { .addr = CC1120_FS_VCO3, .name = "FS_VCO3" },
1129 { .addr = CC1120_FS_VCO2, .name = "FS_VCO2" },
1130 { .addr = CC1120_FS_VCO1, .name = "FS_VCO1" },
1131 { .addr = CC1120_FS_VCO0, .name = "FS_VCO0" },
1132 { .addr = CC1120_GBIAS6, .name = "GBIAS6" },
1133 { .addr = CC1120_GBIAS5, .name = "GBIAS5" },
1134 { .addr = CC1120_GBIAS4, .name = "GBIAS4" },
1135 { .addr = CC1120_GBIAS3, .name = "GBIAS3" },
1136 { .addr = CC1120_GBIAS2, .name = "GBIAS2" },
1137 { .addr = CC1120_GBIAS1, .name = "GBIAS1" },
1138 { .addr = CC1120_GBIAS0, .name = "GBIAS0" },
1139 { .addr = CC1120_IFAMP, .name = "IFAMP" },
1140 { .addr = CC1120_LNA, .name = "LNA" },
1141 { .addr = CC1120_RXMIX, .name = "RXMIX" },
1142 { .addr = CC1120_XOSC5, .name = "XOSC5" },
1143 { .addr = CC1120_XOSC4, .name = "XOSC4" },
1144 { .addr = CC1120_XOSC3, .name = "XOSC3" },
1145 { .addr = CC1120_XOSC2, .name = "XOSC2" },
1146 { .addr = CC1120_XOSC1, .name = "XOSC1" },
1147 { .addr = CC1120_XOSC0, .name = "XOSC0" },
1148 { .addr = CC1120_ANALOG_SPARE, .name = "ANALOG_SPARE" },
1149 { .addr = CC1120_PA_CFG3, .name = "PA_CFG3" },
1150 { .addr = CC1120_WOR_TIME1, .name = "WOR_TIME1" },
1151 { .addr = CC1120_WOR_TIME0, .name = "WOR_TIME0" },
1152 { .addr = CC1120_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
1153 { .addr = CC1120_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
1154 { .addr = CC1120_BIST, .name = "BIST" },
1155 { .addr = CC1120_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
1156 { .addr = CC1120_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
1157 { .addr = CC1120_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
1158 { .addr = CC1120_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
1159 { .addr = CC1120_IQIE_I1, .name = "IQIE_I1" },
1160 { .addr = CC1120_IQIE_I0, .name = "IQIE_I0" },
1161 { .addr = CC1120_IQIE_Q1, .name = "IQIE_Q1" },
1162 { .addr = CC1120_IQIE_Q0, .name = "IQIE_Q0" },
1163 { .addr = CC1120_RSSI1, .name = "RSSI1" },
1164 { .addr = CC1120_RSSI0, .name = "RSSI0" },
1165 { .addr = CC1120_MARCSTATE, .name = "MARCSTATE" },
1166 { .addr = CC1120_LQI_VAL, .name = "LQI_VAL" },
1167 { .addr = CC1120_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
1168 { .addr = CC1120_DEM_STATUS, .name = "DEM_STATUS" },
1169 { .addr = CC1120_FREQOFF_EST1, .name = "FREQOFF_EST1" },
1170 { .addr = CC1120_FREQOFF_EST0, .name = "FREQOFF_EST0" },
1171 { .addr = CC1120_AGC_GAIN3, .name = "AGC_GAIN3" },
1172 { .addr = CC1120_AGC_GAIN2, .name = "AGC_GAIN2" },
1173 { .addr = CC1120_AGC_GAIN1, .name = "AGC_GAIN1" },
1174 { .addr = CC1120_AGC_GAIN0, .name = "AGC_GAIN0" },
1175 { .addr = CC1120_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
1176 { .addr = CC1120_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
1177 { .addr = CC1120_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
1178 { .addr = CC1120_RNDGEN, .name = "RNDGEN" },
1179 { .addr = CC1120_MAGN2, .name = "MAGN2" },
1180 { .addr = CC1120_MAGN1, .name = "MAGN1" },
1181 { .addr = CC1120_MAGN0, .name = "MAGN0" },
1182 { .addr = CC1120_ANG1, .name = "ANG1" },
1183 { .addr = CC1120_ANG0, .name = "ANG0" },
1184 { .addr = CC1120_CHFILT_I2, .name = "CHFILT_I2" },
1185 { .addr = CC1120_CHFILT_I1, .name = "CHFILT_I1" },
1186 { .addr = CC1120_CHFILT_I0, .name = "CHFILT_I0" },
1187 { .addr = CC1120_CHFILT_Q2, .name = "CHFILT_Q2" },
1188 { .addr = CC1120_CHFILT_Q1, .name = "CHFILT_Q1" },
1189 { .addr = CC1120_CHFILT_Q0, .name = "CHFILT_Q0" },
1190 { .addr = CC1120_GPIO_STATUS, .name = "GPIO_STATUS" },
1191 { .addr = CC1120_FSCAL_CTRL, .name = "FSCAL_CTRL" },
1192 { .addr = CC1120_PHASE_ADJUST, .name = "PHASE_ADJUST" },
1193 { .addr = CC1120_PARTNUMBER, .name = "PARTNUMBER" },
1194 { .addr = CC1120_PARTVERSION, .name = "PARTVERSION" },
1195 { .addr = CC1120_SERIAL_STATUS, .name = "SERIAL_STATUS" },
1196 { .addr = CC1120_RX_STATUS, .name = "RX_STATUS" },
1197 { .addr = CC1120_TX_STATUS, .name = "TX_STATUS" },
1198 { .addr = CC1120_MARC_STATUS1, .name = "MARC_STATUS1" },
1199 { .addr = CC1120_MARC_STATUS0, .name = "MARC_STATUS0" },
1200 { .addr = CC1120_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
1201 { .addr = CC1120_FSRF_TEST, .name = "FSRF_TEST" },
1202 { .addr = CC1120_PRE_TEST, .name = "PRE_TEST" },
1203 { .addr = CC1120_PRE_OVR, .name = "PRE_OVR" },
1204 { .addr = CC1120_ADC_TEST, .name = "ADC_TEST" },
1205 { .addr = CC1120_DVC_TEST, .name = "DVC_TEST" },
1206 { .addr = CC1120_ATEST, .name = "ATEST" },
1207 { .addr = CC1120_ATEST_LVDS, .name = "ATEST_LVDS" },
1208 { .addr = CC1120_ATEST_MODE, .name = "ATEST_MODE" },
1209 { .addr = CC1120_XOSC_TEST1, .name = "XOSC_TEST1" },
1210 { .addr = CC1120_XOSC_TEST0, .name = "XOSC_TEST0" },
1211 { .addr = CC1120_RXFIRST, .name = "RXFIRST" },
1212 { .addr = CC1120_TXFIRST, .name = "TXFIRST" },
1213 { .addr = CC1120_RXLAST, .name = "RXLAST" },
1214 { .addr = CC1120_TXLAST, .name = "TXLAST" },
1215 { .addr = CC1120_NUM_TXBYTES, .name = "NUM_TXBYTES" },
1216 { .addr = CC1120_NUM_RXBYTES, .name = "NUM_RXBYTES" },
1217 { .addr = CC1120_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
1218 { .addr = CC1120_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
1221 #define AO_NUM_CC1120_REG (sizeof ao_cc1120_reg / sizeof ao_cc1120_reg[0])
1223 static void ao_radio_show(void) {
1224 uint8_t status = ao_radio_status();
1228 status = ao_radio_status();
1229 printf ("Status: %02x\n", status);
1230 printf ("CHIP_RDY: %d\n", (status >> CC1120_STATUS_CHIP_RDY) & 1);
1231 printf ("STATE: %s\n", cc1120_state_name[(status >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK]);
1232 printf ("MARC: %02x\n", ao_radio_get_marc_status());
1234 for (i = 0; i < AO_NUM_CC1120_REG; i++)
1235 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name);
1239 static void ao_radio_beep(void) {
1243 static void ao_radio_packet(void) {
1244 static const uint8_t packet[] = {
1246 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1247 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1248 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1249 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1255 ao_radio_send(packet, sizeof (packet));
1259 ao_radio_test_recv()
1264 if (ao_radio_recv(bytes, 34)) {
1265 if (bytes[33] & 0x80)
1269 printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32]));
1270 for (b = 0; b < 32; b++)
1271 printf (" %02x", bytes[b]);
1277 #include <ao_aprs.h>
1282 ao_packet_slave_stop();
1289 static const struct ao_cmds ao_radio_cmds[] = {
1290 { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
1293 { ao_radio_aprs, "G\0Send APRS packet" },
1295 { ao_radio_show, "R\0Show CC1120 status" },
1296 { ao_radio_beep, "b\0Emit an RDF beacon" },
1297 { ao_radio_packet, "p\0Send a test packet" },
1298 { ao_radio_test_recv, "q\0Recv a test packet" },
1308 ao_radio_configured = 0;
1309 ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN));
1312 AO_CC1120_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN));
1313 for (i = 0; i < 10000; i++) {
1314 if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0)
1317 AO_CC1120_SPI_CS_PORT->bsrr = (1 << AO_CC1120_SPI_CS_PIN);
1319 ao_panic(AO_PANIC_SELF_TEST_CC1120);
1322 /* Enable the EXTI interrupt for the appropriate pin */
1323 ao_enable_port(AO_CC1120_INT_PORT);
1324 ao_exti_setup(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1325 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
1328 /* Enable the hacked up GPIO3 pin */
1329 ao_enable_port(AO_CC1120_MCU_WAKEUP_PORT);
1330 ao_exti_setup(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN,
1331 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED,
1332 ao_radio_mcu_wakeup_isr);
1334 ao_cmd_register(&ao_radio_cmds[0]);