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();
157 ao_radio_fifo_read(uint8_t *data, uint8_t len)
159 uint8_t addr = ((1 << CC1120_READ) |
160 (1 << CC1120_BURST) |
165 ao_radio_duplex(&addr, &status, 1);
166 ao_radio_spi_recv(data, len);
173 ao_radio_fifo_write_start(void)
175 uint8_t addr = ((0 << CC1120_READ) |
176 (1 << CC1120_BURST) |
181 ao_radio_duplex(&addr, &status, 1);
185 static inline uint8_t ao_radio_fifo_write_stop(uint8_t status) {
191 ao_radio_fifo_write(uint8_t *data, uint8_t len)
193 uint8_t status = ao_radio_fifo_write_start();
194 ao_radio_spi_send(data, len);
195 return ao_radio_fifo_write_stop(status);
199 ao_radio_fifo_write_fixed(uint8_t data, uint8_t len)
201 uint8_t status = ao_radio_fifo_write_start();
202 ao_radio_spi_send_fixed(data, len);
203 return ao_radio_fifo_write_stop(status);
207 ao_radio_tx_fifo_space(void)
209 return CC1120_FIFO_SIZE - ao_radio_reg_read(CC1120_NUM_TXBYTES);
214 ao_radio_status(void)
216 return ao_radio_strobe (CC1120_SNOP);
221 ao_radio_recv_abort(void)
224 ao_wakeup(&ao_radio_wake);
227 #define ao_radio_rdf_value 0x55
230 ao_radio_get_marc_status(void)
232 return ao_radio_reg_read(CC1120_MARC_STATUS1);
236 ao_radio_mcu_wakeup_isr(void)
238 ao_radio_mcu_wake = 1;
239 ao_wakeup(&ao_radio_wake);
244 ao_radio_check_marc_status(void)
246 ao_radio_mcu_wake = 0;
247 ao_radio_marc_status = ao_radio_get_marc_status();
249 /* Anyt other than 'tx/rx finished' means an error occurred */
250 if (ao_radio_marc_status & ~(CC1120_MARC_STATUS1_TX_FINISHED|CC1120_MARC_STATUS1_RX_FINISHED))
252 if (ao_radio_marc_status & (CC1120_MARC_STATUS1_TX_FINISHED))
253 ao_radio_tx_finished = 1;
259 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
261 ao_wakeup(&ao_radio_wake);
265 ao_radio_start_tx(void)
267 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr);
268 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
269 ao_exti_enable(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN);
270 ao_radio_tx_finished = 0;
271 ao_radio_strobe(CC1120_STX);
278 uint8_t state = ao_radio_strobe(CC1120_SIDLE);
279 if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_IDLE)
281 if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_TX_FIFO_ERROR)
282 ao_radio_strobe(CC1120_SFTX);
284 /* Flush any pending TX bytes */
285 ao_radio_strobe(CC1120_SFTX);
289 * Packet deviation is 20.5kHz
291 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
293 * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz
296 #define PACKET_DEV_E 5
297 #define PACKET_DEV_M 80
300 * For our packet data, set the symbol rate to 38400 Baud
302 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
303 * Rdata = -------------------------------------- * fosc
307 * DATARATE_M = 239914
310 #define PACKET_DRATE_E 9
311 #define PACKET_DRATE_M 239914
313 static const uint16_t packet_setup[] = {
314 CC1120_DEVIATION_M, PACKET_DEV_M,
315 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
316 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
317 (PACKET_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
318 CC1120_DRATE2, ((PACKET_DRATE_E << CC1120_DRATE2_DATARATE_E) |
319 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
320 CC1120_DRATE1, ((PACKET_DRATE_M >> 8) & 0xff),
321 CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff),
322 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
323 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
324 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
325 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
326 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
327 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
328 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
329 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
330 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
331 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
332 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
333 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
334 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
335 AO_CC1120_MARC_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP,
338 static const uint16_t packet_tx_setup[] = {
339 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
340 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
341 AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG,
344 static const uint16_t packet_rx_setup[] = {
345 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
346 (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT)),
347 AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT,
351 * RDF deviation is 5kHz
353 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
355 * 32e6Hz / (2 ** 24) * (256 + 71) * (2 ** 3) = 4989
360 #define RDF_PACKET_LEN 50
363 * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
365 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
366 * Rdata = -------------------------------------- * fosc
372 * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
374 #define RDF_DRATE_E 5
375 #define RDF_DRATE_M 25166
376 #define RDF_PACKET_LEN 50
378 static const uint16_t rdf_setup[] = {
379 CC1120_DEVIATION_M, RDF_DEV_M,
380 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
381 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
382 (RDF_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
383 CC1120_DRATE2, ((RDF_DRATE_E << CC1120_DRATE2_DATARATE_E) |
384 (((RDF_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
385 CC1120_DRATE1, ((RDF_DRATE_M >> 8) & 0xff),
386 CC1120_DRATE0, ((RDF_DRATE_M >> 0) & 0xff),
387 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
388 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
389 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
390 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
391 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
392 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
393 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
394 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
395 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
396 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
397 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
398 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
399 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
403 * APRS deviation is 3kHz
405 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
407 * 32e6Hz / (2 ** 24) * (256 + 137) * (2 ** 2) = 2998Hz
411 #define APRS_DEV_M 137
414 * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate)
416 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
417 * Rdata = -------------------------------------- * fosc
420 * DATARATE_M = 239914
423 * Rdata = 9599.998593330383301
426 #define APRS_DRATE_E 7
427 #define APRS_DRATE_M 239914
429 static const uint16_t aprs_setup[] = {
430 CC1120_DEVIATION_M, APRS_DEV_M,
431 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
432 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
433 (APRS_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
434 CC1120_DRATE2, ((APRS_DRATE_E << CC1120_DRATE2_DATARATE_E) |
435 (((APRS_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
436 CC1120_DRATE1, ((APRS_DRATE_M >> 8) & 0xff),
437 CC1120_DRATE0, ((APRS_DRATE_M >> 0) & 0xff),
438 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
439 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
440 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
441 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
442 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
443 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
444 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
445 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
449 * For Test mode, we want an unmodulated carrier. To do that, we
450 * set the deviation to zero and enable a preamble so that the radio
451 * turns on before we send any data
454 static const uint16_t test_setup[] = {
455 CC1120_DEVIATION_M, 0,
456 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
457 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
458 (0 << CC1120_MODCFG_DEV_E_DEV_E)),
459 CC1120_DRATE2, ((APRS_DRATE_E << CC1120_DRATE2_DATARATE_E) |
460 (((APRS_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
461 CC1120_DRATE1, ((APRS_DRATE_M >> 8) & 0xff),
462 CC1120_DRATE0, ((APRS_DRATE_M >> 0) & 0xff),
463 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
464 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
465 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
466 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
467 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
468 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
469 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
470 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
473 #define AO_PKT_CFG0_INFINITE ((0 << CC1120_PKT_CFG0_RESERVED7) | \
474 (CC1120_PKT_CFG0_LENGTH_CONFIG_INFINITE << CC1120_PKT_CFG0_LENGTH_CONFIG) | \
475 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | \
476 (0 << CC1120_PKT_CFG0_UART_MODE_EN) | \
477 (0 << CC1120_PKT_CFG0_UART_SWAP_EN))
479 #define AO_PKT_CFG0_FIXED ((0 << CC1120_PKT_CFG0_RESERVED7) | \
480 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) | \
481 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | \
482 (0 << CC1120_PKT_CFG0_UART_MODE_EN) | \
483 (0 << CC1120_PKT_CFG0_UART_SWAP_EN))
485 static uint16_t ao_radio_mode;
487 #define AO_RADIO_MODE_BITS_PACKET 1
488 #define AO_RADIO_MODE_BITS_PACKET_TX 2
489 #define AO_RADIO_MODE_BITS_TX_BUF 4
490 #define AO_RADIO_MODE_BITS_TX_FINISH 8
491 #define AO_RADIO_MODE_BITS_PACKET_RX 16
492 #define AO_RADIO_MODE_BITS_RDF 32
493 #define AO_RADIO_MODE_BITS_APRS 64
494 #define AO_RADIO_MODE_BITS_TEST 128
495 #define AO_RADIO_MODE_BITS_INFINITE 256
496 #define AO_RADIO_MODE_BITS_FIXED 512
498 #define AO_RADIO_MODE_NONE 0
499 #define AO_RADIO_MODE_PACKET_TX_BUF (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_BUF)
500 #define AO_RADIO_MODE_PACKET_TX_FINISH (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_FINISH)
501 #define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_RX)
502 #define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_TX_FINISH)
503 #define AO_RADIO_MODE_APRS_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
504 #define AO_RADIO_MODE_APRS_LAST_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_BUF)
505 #define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
506 #define AO_RADIO_MODE_TEST (AO_RADIO_MODE_BITS_TEST | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
509 ao_radio_set_mode(uint16_t new_mode)
514 if (new_mode == ao_radio_mode)
517 changes = new_mode & (~ao_radio_mode);
518 if (changes & AO_RADIO_MODE_BITS_PACKET)
519 for (i = 0; i < sizeof (packet_setup) / sizeof (packet_setup[0]); i += 2)
520 ao_radio_reg_write(packet_setup[i], packet_setup[i+1]);
522 if (changes & AO_RADIO_MODE_BITS_PACKET_TX)
523 for (i = 0; i < sizeof (packet_tx_setup) / sizeof (packet_tx_setup[0]); i += 2)
524 ao_radio_reg_write(packet_tx_setup[i], packet_tx_setup[i+1]);
526 if (changes & AO_RADIO_MODE_BITS_TX_BUF)
527 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_TXFIFO_THR);
529 if (changes & AO_RADIO_MODE_BITS_TX_FINISH)
530 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG);
532 if (changes & AO_RADIO_MODE_BITS_PACKET_RX)
533 for (i = 0; i < sizeof (packet_rx_setup) / sizeof (packet_rx_setup[0]); i += 2)
534 ao_radio_reg_write(packet_rx_setup[i], packet_rx_setup[i+1]);
536 if (changes & AO_RADIO_MODE_BITS_RDF)
537 for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2)
538 ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]);
540 if (changes & AO_RADIO_MODE_BITS_APRS)
541 for (i = 0; i < sizeof (aprs_setup) / sizeof (aprs_setup[0]); i += 2)
542 ao_radio_reg_write(aprs_setup[i], aprs_setup[i+1]);
544 if (changes & AO_RADIO_MODE_BITS_TEST)
545 for (i = 0; i < sizeof (test_setup) / sizeof (test_setup[0]); i += 2)
546 ao_radio_reg_write(test_setup[i], test_setup[i+1]);
548 if (changes & AO_RADIO_MODE_BITS_INFINITE)
549 ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_INFINITE);
551 if (changes & AO_RADIO_MODE_BITS_FIXED)
552 ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_FIXED);
554 ao_radio_mode = new_mode;
557 static const uint16_t radio_setup[] = {
558 #include "ao_cc1120_CC1120.h"
561 static uint8_t ao_radio_configured = 0;
568 ao_radio_strobe(CC1120_SRES);
570 for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2)
571 ao_radio_reg_write(radio_setup[i], radio_setup[i+1]);
577 ao_radio_configured = 1;
581 ao_radio_set_len(uint8_t len)
583 static uint8_t last_len;
585 if (len != last_len) {
586 ao_radio_reg_write(CC1120_PKT_LEN, len);
592 ao_radio_get(uint8_t len)
594 static uint32_t last_radio_setting;
596 ao_mutex_get(&ao_radio_mutex);
598 if (!ao_radio_configured)
600 if (ao_config.radio_setting != last_radio_setting) {
601 ao_radio_reg_write(CC1120_FREQ2, ao_config.radio_setting >> 16);
602 ao_radio_reg_write(CC1120_FREQ1, ao_config.radio_setting >> 8);
603 ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting);
604 last_radio_setting = ao_config.radio_setting;
606 ao_radio_set_len(len);
609 #define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
612 ao_rdf_start(uint8_t len)
617 ao_radio_set_mode(AO_RADIO_MODE_RDF);
627 ao_arch_block_interrupts();
628 while (!ao_radio_wake && !ao_radio_abort && !ao_radio_mcu_wake)
629 ao_sleep(&ao_radio_wake);
630 ao_arch_release_interrupts();
631 if (ao_radio_mcu_wake)
632 ao_radio_check_marc_status();
641 ao_rdf_start(AO_RADIO_RDF_LEN);
643 ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN);
649 ao_radio_continuity(uint8_t c)
654 ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN);
656 status = ao_radio_fifo_write_start();
657 for (i = 0; i < 3; i++) {
658 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
660 ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN);
662 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN);
664 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
665 status = ao_radio_fifo_write_stop(status);
671 ao_radio_rdf_abort(void)
674 ao_wakeup(&ao_radio_wake);
678 ao_radio_test_cmd(void)
681 static uint8_t radio_on;
683 if (ao_cmd_lex_c != '\n') {
685 mode = (uint8_t) ao_cmd_lex_u32;
688 if ((mode & 2) && !radio_on) {
690 ao_monitor_disable();
693 ao_packet_slave_stop();
696 ao_radio_set_mode(AO_RADIO_MODE_TEST);
697 ao_radio_strobe(CC1120_STX);
700 for (t = 0; t < 10; t++) {
701 printf ("status: %02x\n", ao_radio_status());
702 ao_delay(AO_MS_TO_TICKS(100));
709 printf ("Hit a character to stop..."); flush();
713 if ((mode & 1) && radio_on) {
724 ao_radio_wait_isr(uint16_t timeout)
728 ao_arch_block_interrupts();
729 while (!ao_radio_wake && !ao_radio_mcu_wake && !ao_radio_abort)
730 if (ao_sleep(&ao_radio_wake))
732 ao_arch_release_interrupts();
735 if (ao_radio_mcu_wake)
736 ao_radio_check_marc_status();
740 ao_radio_wait_tx(uint8_t wait_fifo)
742 uint8_t fifo_space = 0;
745 ao_radio_wait_isr(0);
748 fifo_space = ao_radio_tx_fifo_space();
749 } while (!fifo_space && !ao_radio_abort);
753 static uint8_t tx_data[(AO_RADIO_MAX_SEND + 4) * 2];
756 ao_radio_send(const void *d, uint8_t size)
758 uint8_t *e = tx_data;
764 encode_len = ao_fec_encode(d, size, tx_data);
766 ao_radio_get(encode_len);
770 /* Flush any pending TX bytes */
771 ao_radio_strobe(CC1120_SFTX);
774 fifo_space = CC1120_FIFO_SIZE;
776 this_len = encode_len;
779 if (this_len > fifo_space) {
780 this_len = fifo_space;
781 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_BUF);
783 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_FINISH);
786 ao_radio_fifo_write(e, this_len);
788 encode_len -= this_len;
794 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
797 fifo_space = ao_radio_wait_tx(encode_len != 0);
798 if (ao_radio_abort) {
803 while (started && !ao_radio_abort && !ao_radio_tx_finished)
804 ao_radio_wait_isr(0);
808 #define AO_RADIO_LOTS 64
811 ao_radio_send_aprs(ao_radio_fill_func fill)
813 uint8_t buf[AO_RADIO_LOTS], *b;
821 fifo_space = CC1120_FIFO_SIZE;
823 cnt = (*fill)(buf, sizeof(buf));
830 /* At the last buffer, set the total length */
832 ao_radio_set_len(total & 0xff);
836 uint8_t this_len = cnt;
838 /* Wait for some space in the fifo */
839 while (!ao_radio_abort && (fifo_space = ao_radio_tx_fifo_space()) == 0) {
841 ao_radio_wait_isr(0);
845 if (this_len > fifo_space)
846 this_len = fifo_space;
852 ao_radio_set_mode(AO_RADIO_MODE_APRS_LAST_BUF);
854 ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
856 ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
858 ao_radio_fifo_write(b, this_len);
865 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
867 if (ao_radio_abort) {
871 /* Wait for the transmitter to go idle */
873 ao_radio_wait_isr(0);
878 static uint8_t rx_data[(AO_RADIO_MAX_RECV + 4) * 2 * 8];
879 static uint16_t rx_data_count;
880 static uint16_t rx_data_consumed;
881 static uint16_t rx_data_cur;
882 static uint8_t rx_ignore;
883 static uint8_t rx_waiting;
886 static uint32_t rx_start_tick, rx_packet_tick, rx_done_tick, rx_last_done_tick;
888 uint32_t ao_rx_start_tick, ao_rx_packet_tick, ao_rx_done_tick, ao_rx_last_done_tick;
890 #include <ao_profile.h>
894 ao_radio_rx_isr(void)
898 d = AO_CC1120_SPI.dr;
899 AO_CC1120_SPI.dr = 0;
900 if (rx_ignore == 0) {
901 if (rx_data_cur >= rx_data_count)
902 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
904 rx_data[rx_data_cur++] = d;
905 if (rx_waiting && rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) {
908 rx_packet_tick = ao_profile_tick();
909 if (rx_data_cur < rx_data_count)
913 ao_wakeup(&ao_radio_wake);
921 ao_radio_rx_wait(void)
924 if (ao_radio_mcu_wake)
925 ao_radio_check_marc_status();
926 ao_alarm(AO_MS_TO_TICKS(100));
927 ao_arch_block_interrupts();
929 while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&
933 if (ao_sleep(&ao_radio_wake))
937 ao_arch_release_interrupts();
939 } while (ao_radio_mcu_wake);
942 rx_data_consumed += AO_FEC_DECODE_BLOCK;
944 return rx_data_cur - rx_data_consumed;
946 return AO_FEC_DECODE_BLOCK;
950 ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout)
953 uint8_t radio_rssi = 0;
957 size -= 2; /* status bytes */
958 if (size > AO_RADIO_MAX_RECV) {
959 ao_delay(AO_SEC_TO_TICKS(1));
963 rx_start_tick = ao_profile_tick();
966 len = size + 2; /* CRC bytes */
967 len += 1 + ~(len & 1); /* 1 or two pad bytes */
968 len *= 2; /* 1/2 rate convolution */
969 rx_data_count = len * 8; /* bytes to bits */
971 rx_data_consumed = 0;
974 /* Must be set before changing the frequency; any abort
975 * after the frequency is set needs to terminate the read
976 * so that the registers can be reprogrammed
980 /* configure interrupt pin */
982 ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
985 ao_radio_mcu_wake = 0;
987 AO_CC1120_SPI.cr2 = 0;
990 (void) AO_CC1120_SPI.dr;
992 /* Have the radio signal when the preamble quality goes high */
993 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_PQT_REACHED);
994 ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
995 AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_HIGH);
996 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr);
997 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
998 ao_exti_enable(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN);
1000 ao_radio_strobe(CC1120_SRX);
1002 /* Wait for the preamble to appear */
1003 ao_radio_wait_isr(timeout);
1004 if (ao_radio_abort) {
1009 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT);
1010 ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1011 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
1013 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
1014 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
1016 ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
1018 ret = ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait);
1020 ao_radio_burst_read_stop();
1023 /* Convert from 'real' rssi to cc1111-style values */
1025 rssi0 = ao_radio_reg_read(CC1120_RSSI0);
1027 int8_t rssi = ao_radio_reg_read(CC1120_RSSI1);
1028 ao_radio_rssi = rssi;
1030 /* Bound it to the representable range */
1033 radio_rssi = AO_RADIO_FROM_RSSI (rssi);
1036 ao_radio_strobe(CC1120_SIDLE);
1040 /* Store the received RSSI value; the crc-OK byte is already done */
1042 ((uint8_t *) d)[size] = radio_rssi;
1045 rx_last_done_tick = rx_done_tick;
1046 rx_done_tick = ao_profile_tick();
1048 ao_rx_start_tick = rx_start_tick;
1049 ao_rx_packet_tick = rx_packet_tick;
1050 ao_rx_done_tick = rx_done_tick;
1051 ao_rx_last_done_tick = rx_last_done_tick;
1059 static char *cc1120_state_name[] = {
1060 [CC1120_STATUS_STATE_IDLE] = "IDLE",
1061 [CC1120_STATUS_STATE_RX] = "RX",
1062 [CC1120_STATUS_STATE_TX] = "TX",
1063 [CC1120_STATUS_STATE_FSTXON] = "FSTXON",
1064 [CC1120_STATUS_STATE_CALIBRATE] = "CALIBRATE",
1065 [CC1120_STATUS_STATE_SETTLING] = "SETTLING",
1066 [CC1120_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
1067 [CC1120_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
1070 struct ao_cc1120_reg {
1075 const static struct ao_cc1120_reg ao_cc1120_reg[] = {
1076 { .addr = CC1120_IOCFG3, .name = "IOCFG3" },
1077 { .addr = CC1120_IOCFG2, .name = "IOCFG2" },
1078 { .addr = CC1120_IOCFG1, .name = "IOCFG1" },
1079 { .addr = CC1120_IOCFG0, .name = "IOCFG0" },
1080 { .addr = CC1120_SYNC3, .name = "SYNC3" },
1081 { .addr = CC1120_SYNC2, .name = "SYNC2" },
1082 { .addr = CC1120_SYNC1, .name = "SYNC1" },
1083 { .addr = CC1120_SYNC0, .name = "SYNC0" },
1084 { .addr = CC1120_SYNC_CFG1, .name = "SYNC_CFG1" },
1085 { .addr = CC1120_SYNC_CFG0, .name = "SYNC_CFG0" },
1086 { .addr = CC1120_DEVIATION_M, .name = "DEVIATION_M" },
1087 { .addr = CC1120_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
1088 { .addr = CC1120_DCFILT_CFG, .name = "DCFILT_CFG" },
1089 { .addr = CC1120_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
1090 { .addr = CC1120_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
1091 { .addr = CC1120_FREQ_IF_CFG, .name = "FREQ_IF_CFG" },
1092 { .addr = CC1120_IQIC, .name = "IQIC" },
1093 { .addr = CC1120_CHAN_BW, .name = "CHAN_BW" },
1094 { .addr = CC1120_MDMCFG1, .name = "MDMCFG1" },
1095 { .addr = CC1120_MDMCFG0, .name = "MDMCFG0" },
1096 { .addr = CC1120_DRATE2, .name = "DRATE2" },
1097 { .addr = CC1120_DRATE1, .name = "DRATE1" },
1098 { .addr = CC1120_DRATE0, .name = "DRATE0" },
1099 { .addr = CC1120_AGC_REF, .name = "AGC_REF" },
1100 { .addr = CC1120_AGC_CS_THR, .name = "AGC_CS_THR" },
1101 { .addr = CC1120_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
1102 { .addr = CC1120_AGC_CFG3, .name = "AGC_CFG3" },
1103 { .addr = CC1120_AGC_CFG2, .name = "AGC_CFG2" },
1104 { .addr = CC1120_AGC_CFG1, .name = "AGC_CFG1" },
1105 { .addr = CC1120_AGC_CFG0, .name = "AGC_CFG0" },
1106 { .addr = CC1120_FIFO_CFG, .name = "FIFO_CFG" },
1107 { .addr = CC1120_DEV_ADDR, .name = "DEV_ADDR" },
1108 { .addr = CC1120_SETTLING_CFG, .name = "SETTLING_CFG" },
1109 { .addr = CC1120_FS_CFG, .name = "FS_CFG" },
1110 { .addr = CC1120_WOR_CFG1, .name = "WOR_CFG1" },
1111 { .addr = CC1120_WOR_CFG0, .name = "WOR_CFG0" },
1112 { .addr = CC1120_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
1113 { .addr = CC1120_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
1114 { .addr = CC1120_PKT_CFG2, .name = "PKT_CFG2" },
1115 { .addr = CC1120_PKT_CFG1, .name = "PKT_CFG1" },
1116 { .addr = CC1120_PKT_CFG0, .name = "PKT_CFG0" },
1117 { .addr = CC1120_RFEND_CFG1, .name = "RFEND_CFG1" },
1118 { .addr = CC1120_RFEND_CFG0, .name = "RFEND_CFG0" },
1119 { .addr = CC1120_PA_CFG2, .name = "PA_CFG2" },
1120 { .addr = CC1120_PA_CFG1, .name = "PA_CFG1" },
1121 { .addr = CC1120_PA_CFG0, .name = "PA_CFG0" },
1122 { .addr = CC1120_PKT_LEN, .name = "PKT_LEN" },
1123 { .addr = CC1120_IF_MIX_CFG, .name = "IF_MIX_CFG" },
1124 { .addr = CC1120_FREQOFF_CFG, .name = "FREQOFF_CFG" },
1125 { .addr = CC1120_TOC_CFG, .name = "TOC_CFG" },
1126 { .addr = CC1120_MARC_SPARE, .name = "MARC_SPARE" },
1127 { .addr = CC1120_ECG_CFG, .name = "ECG_CFG" },
1128 { .addr = CC1120_SOFT_TX_DATA_CFG, .name = "SOFT_TX_DATA_CFG" },
1129 { .addr = CC1120_EXT_CTRL, .name = "EXT_CTRL" },
1130 { .addr = CC1120_RCCAL_FINE, .name = "RCCAL_FINE" },
1131 { .addr = CC1120_RCCAL_COARSE, .name = "RCCAL_COARSE" },
1132 { .addr = CC1120_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
1133 { .addr = CC1120_FREQOFF1, .name = "FREQOFF1" },
1134 { .addr = CC1120_FREQOFF0, .name = "FREQOFF0" },
1135 { .addr = CC1120_FREQ2, .name = "FREQ2" },
1136 { .addr = CC1120_FREQ1, .name = "FREQ1" },
1137 { .addr = CC1120_FREQ0, .name = "FREQ0" },
1138 { .addr = CC1120_IF_ADC2, .name = "IF_ADC2" },
1139 { .addr = CC1120_IF_ADC1, .name = "IF_ADC1" },
1140 { .addr = CC1120_IF_ADC0, .name = "IF_ADC0" },
1141 { .addr = CC1120_FS_DIG1, .name = "FS_DIG1" },
1142 { .addr = CC1120_FS_DIG0, .name = "FS_DIG0" },
1143 { .addr = CC1120_FS_CAL3, .name = "FS_CAL3" },
1144 { .addr = CC1120_FS_CAL2, .name = "FS_CAL2" },
1145 { .addr = CC1120_FS_CAL1, .name = "FS_CAL1" },
1146 { .addr = CC1120_FS_CAL0, .name = "FS_CAL0" },
1147 { .addr = CC1120_FS_CHP, .name = "FS_CHP" },
1148 { .addr = CC1120_FS_DIVTWO, .name = "FS_DIVTWO" },
1149 { .addr = CC1120_FS_DSM1, .name = "FS_DSM1" },
1150 { .addr = CC1120_FS_DSM0, .name = "FS_DSM0" },
1151 { .addr = CC1120_FS_DVC1, .name = "FS_DVC1" },
1152 { .addr = CC1120_FS_DVC0, .name = "FS_DVC0" },
1153 { .addr = CC1120_FS_LBI, .name = "FS_LBI" },
1154 { .addr = CC1120_FS_PFD, .name = "FS_PFD" },
1155 { .addr = CC1120_FS_PRE, .name = "FS_PRE" },
1156 { .addr = CC1120_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
1157 { .addr = CC1120_FS_SPARE, .name = "FS_SPARE" },
1158 { .addr = CC1120_FS_VCO4, .name = "FS_VCO4" },
1159 { .addr = CC1120_FS_VCO3, .name = "FS_VCO3" },
1160 { .addr = CC1120_FS_VCO2, .name = "FS_VCO2" },
1161 { .addr = CC1120_FS_VCO1, .name = "FS_VCO1" },
1162 { .addr = CC1120_FS_VCO0, .name = "FS_VCO0" },
1163 { .addr = CC1120_GBIAS6, .name = "GBIAS6" },
1164 { .addr = CC1120_GBIAS5, .name = "GBIAS5" },
1165 { .addr = CC1120_GBIAS4, .name = "GBIAS4" },
1166 { .addr = CC1120_GBIAS3, .name = "GBIAS3" },
1167 { .addr = CC1120_GBIAS2, .name = "GBIAS2" },
1168 { .addr = CC1120_GBIAS1, .name = "GBIAS1" },
1169 { .addr = CC1120_GBIAS0, .name = "GBIAS0" },
1170 { .addr = CC1120_IFAMP, .name = "IFAMP" },
1171 { .addr = CC1120_LNA, .name = "LNA" },
1172 { .addr = CC1120_RXMIX, .name = "RXMIX" },
1173 { .addr = CC1120_XOSC5, .name = "XOSC5" },
1174 { .addr = CC1120_XOSC4, .name = "XOSC4" },
1175 { .addr = CC1120_XOSC3, .name = "XOSC3" },
1176 { .addr = CC1120_XOSC2, .name = "XOSC2" },
1177 { .addr = CC1120_XOSC1, .name = "XOSC1" },
1178 { .addr = CC1120_XOSC0, .name = "XOSC0" },
1179 { .addr = CC1120_ANALOG_SPARE, .name = "ANALOG_SPARE" },
1180 { .addr = CC1120_PA_CFG3, .name = "PA_CFG3" },
1181 { .addr = CC1120_WOR_TIME1, .name = "WOR_TIME1" },
1182 { .addr = CC1120_WOR_TIME0, .name = "WOR_TIME0" },
1183 { .addr = CC1120_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
1184 { .addr = CC1120_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
1185 { .addr = CC1120_BIST, .name = "BIST" },
1186 { .addr = CC1120_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
1187 { .addr = CC1120_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
1188 { .addr = CC1120_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
1189 { .addr = CC1120_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
1190 { .addr = CC1120_IQIE_I1, .name = "IQIE_I1" },
1191 { .addr = CC1120_IQIE_I0, .name = "IQIE_I0" },
1192 { .addr = CC1120_IQIE_Q1, .name = "IQIE_Q1" },
1193 { .addr = CC1120_IQIE_Q0, .name = "IQIE_Q0" },
1194 { .addr = CC1120_RSSI1, .name = "RSSI1" },
1195 { .addr = CC1120_RSSI0, .name = "RSSI0" },
1196 { .addr = CC1120_MARCSTATE, .name = "MARCSTATE" },
1197 { .addr = CC1120_LQI_VAL, .name = "LQI_VAL" },
1198 { .addr = CC1120_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
1199 { .addr = CC1120_DEM_STATUS, .name = "DEM_STATUS" },
1200 { .addr = CC1120_FREQOFF_EST1, .name = "FREQOFF_EST1" },
1201 { .addr = CC1120_FREQOFF_EST0, .name = "FREQOFF_EST0" },
1202 { .addr = CC1120_AGC_GAIN3, .name = "AGC_GAIN3" },
1203 { .addr = CC1120_AGC_GAIN2, .name = "AGC_GAIN2" },
1204 { .addr = CC1120_AGC_GAIN1, .name = "AGC_GAIN1" },
1205 { .addr = CC1120_AGC_GAIN0, .name = "AGC_GAIN0" },
1206 { .addr = CC1120_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
1207 { .addr = CC1120_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
1208 { .addr = CC1120_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
1209 { .addr = CC1120_RNDGEN, .name = "RNDGEN" },
1210 { .addr = CC1120_MAGN2, .name = "MAGN2" },
1211 { .addr = CC1120_MAGN1, .name = "MAGN1" },
1212 { .addr = CC1120_MAGN0, .name = "MAGN0" },
1213 { .addr = CC1120_ANG1, .name = "ANG1" },
1214 { .addr = CC1120_ANG0, .name = "ANG0" },
1215 { .addr = CC1120_CHFILT_I2, .name = "CHFILT_I2" },
1216 { .addr = CC1120_CHFILT_I1, .name = "CHFILT_I1" },
1217 { .addr = CC1120_CHFILT_I0, .name = "CHFILT_I0" },
1218 { .addr = CC1120_CHFILT_Q2, .name = "CHFILT_Q2" },
1219 { .addr = CC1120_CHFILT_Q1, .name = "CHFILT_Q1" },
1220 { .addr = CC1120_CHFILT_Q0, .name = "CHFILT_Q0" },
1221 { .addr = CC1120_GPIO_STATUS, .name = "GPIO_STATUS" },
1222 { .addr = CC1120_FSCAL_CTRL, .name = "FSCAL_CTRL" },
1223 { .addr = CC1120_PHASE_ADJUST, .name = "PHASE_ADJUST" },
1224 { .addr = CC1120_PARTNUMBER, .name = "PARTNUMBER" },
1225 { .addr = CC1120_PARTVERSION, .name = "PARTVERSION" },
1226 { .addr = CC1120_SERIAL_STATUS, .name = "SERIAL_STATUS" },
1227 { .addr = CC1120_RX_STATUS, .name = "RX_STATUS" },
1228 { .addr = CC1120_TX_STATUS, .name = "TX_STATUS" },
1229 { .addr = CC1120_MARC_STATUS1, .name = "MARC_STATUS1" },
1230 { .addr = CC1120_MARC_STATUS0, .name = "MARC_STATUS0" },
1231 { .addr = CC1120_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
1232 { .addr = CC1120_FSRF_TEST, .name = "FSRF_TEST" },
1233 { .addr = CC1120_PRE_TEST, .name = "PRE_TEST" },
1234 { .addr = CC1120_PRE_OVR, .name = "PRE_OVR" },
1235 { .addr = CC1120_ADC_TEST, .name = "ADC_TEST" },
1236 { .addr = CC1120_DVC_TEST, .name = "DVC_TEST" },
1237 { .addr = CC1120_ATEST, .name = "ATEST" },
1238 { .addr = CC1120_ATEST_LVDS, .name = "ATEST_LVDS" },
1239 { .addr = CC1120_ATEST_MODE, .name = "ATEST_MODE" },
1240 { .addr = CC1120_XOSC_TEST1, .name = "XOSC_TEST1" },
1241 { .addr = CC1120_XOSC_TEST0, .name = "XOSC_TEST0" },
1242 { .addr = CC1120_RXFIRST, .name = "RXFIRST" },
1243 { .addr = CC1120_TXFIRST, .name = "TXFIRST" },
1244 { .addr = CC1120_RXLAST, .name = "RXLAST" },
1245 { .addr = CC1120_TXLAST, .name = "TXLAST" },
1246 { .addr = CC1120_NUM_TXBYTES, .name = "NUM_TXBYTES" },
1247 { .addr = CC1120_NUM_RXBYTES, .name = "NUM_RXBYTES" },
1248 { .addr = CC1120_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
1249 { .addr = CC1120_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
1252 #define AO_NUM_CC1120_REG (sizeof ao_cc1120_reg / sizeof ao_cc1120_reg[0])
1254 static void ao_radio_show(void) {
1255 uint8_t status = ao_radio_status();
1259 status = ao_radio_status();
1260 printf ("Status: %02x\n", status);
1261 printf ("CHIP_RDY: %d\n", (status >> CC1120_STATUS_CHIP_RDY) & 1);
1262 printf ("STATE: %s\n", cc1120_state_name[(status >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK]);
1263 printf ("MARC: %02x\n", ao_radio_get_marc_status());
1265 for (i = 0; i < AO_NUM_CC1120_REG; i++)
1266 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name);
1270 static void ao_radio_beep(void) {
1274 static void ao_radio_packet(void) {
1275 static const uint8_t packet[] = {
1277 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1278 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1279 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1280 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1286 ao_radio_send(packet, sizeof (packet));
1290 ao_radio_test_recv()
1295 if (ao_radio_recv(bytes, 34)) {
1296 if (bytes[33] & 0x80)
1300 printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32]));
1301 for (b = 0; b < 32; b++)
1302 printf (" %02x", bytes[b]);
1308 #include <ao_aprs.h>
1313 ao_packet_slave_stop();
1320 static const struct ao_cmds ao_radio_cmds[] = {
1321 { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
1324 { ao_radio_aprs, "G\0Send APRS packet" },
1326 { ao_radio_show, "R\0Show CC1120 status" },
1327 { ao_radio_beep, "b\0Emit an RDF beacon" },
1328 { ao_radio_packet, "p\0Send a test packet" },
1329 { ao_radio_test_recv, "q\0Recv a test packet" },
1337 ao_radio_configured = 0;
1338 ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN));
1341 AO_CC1120_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN));
1342 for (i = 0; i < 10000; i++) {
1343 if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0)
1346 AO_CC1120_SPI_CS_PORT->bsrr = (1 << AO_CC1120_SPI_CS_PIN);
1348 ao_panic(AO_PANIC_SELF_TEST_CC1120);
1351 /* Enable the EXTI interrupt for the appropriate pin */
1352 ao_enable_port(AO_CC1120_INT_PORT);
1353 ao_exti_setup(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1354 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
1357 /* Enable the hacked up GPIO3 pin */
1358 ao_enable_port(AO_CC1120_MCU_WAKEUP_PORT);
1359 ao_exti_setup(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN,
1360 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED,
1361 ao_radio_mcu_wakeup_isr);
1363 ao_cmd_register(&ao_radio_cmds[0]);