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 CC1120_SOFT_TX_DATA_CFG,((0 << CC1120_SOFT_TX_DATA_CFG_SOFT_TX_DATA_EN)),
332 AO_CC1120_MARC_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP,
335 static const uint16_t packet_tx_setup[] = {
336 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
337 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
338 AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG,
341 static const uint16_t packet_rx_setup[] = {
342 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
343 (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT)),
344 AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT,
348 * RDF deviation is 5kHz
350 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
352 * 32e6Hz / (2 ** 24) * (256 + 71) * (2 ** 3) = 4989
357 #define RDF_PACKET_LEN 50
360 * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
362 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
363 * Rdata = -------------------------------------- * fosc
369 * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
371 #define RDF_DRATE_E 5
372 #define RDF_DRATE_M 25166
373 #define RDF_PACKET_LEN 50
375 static const uint16_t rdf_setup[] = {
376 CC1120_DEVIATION_M, RDF_DEV_M,
377 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
378 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
379 (RDF_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
380 CC1120_DRATE2, ((RDF_DRATE_E << CC1120_DRATE2_DATARATE_E) |
381 (((RDF_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
382 CC1120_DRATE1, ((RDF_DRATE_M >> 8) & 0xff),
383 CC1120_DRATE0, ((RDF_DRATE_M >> 0) & 0xff),
384 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
385 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
386 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
387 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
388 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
389 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
390 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
391 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
392 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
393 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
394 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
395 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
396 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
397 CC1120_SOFT_TX_DATA_CFG,((0 << CC1120_SOFT_TX_DATA_CFG_SOFT_TX_DATA_EN)),
401 * APRS deviation is 3kHz
403 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
405 * 32e6Hz / (2 ** 24) * (256 + 137) * (2 ** 2) = 2998Hz
409 #define APRS_DEV_M 137
412 * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate)
414 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
415 * Rdata = -------------------------------------- * fosc
418 * DATARATE_M = 239914
421 * Rdata = 9599.998593330383301
424 #define APRS_DRATE_E 7
425 #define APRS_DRATE_M 239914
427 static const uint16_t aprs_setup[] = {
428 CC1120_DEVIATION_M, APRS_DEV_M,
429 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
430 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
431 (APRS_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
432 CC1120_DRATE2, ((APRS_DRATE_E << CC1120_DRATE2_DATARATE_E) |
433 (((APRS_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
434 CC1120_DRATE1, ((APRS_DRATE_M >> 8) & 0xff),
435 CC1120_DRATE0, ((APRS_DRATE_M >> 0) & 0xff),
436 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
437 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
438 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
439 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
440 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
441 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
442 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
443 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
444 CC1120_SOFT_TX_DATA_CFG,((0 << CC1120_SOFT_TX_DATA_CFG_SOFT_TX_DATA_EN)),
448 * For Test mode, we want an unmodulated carrier. To do that,
449 * we enable soft TX mode and set the deviation to zero
452 static const uint16_t test_setup[] = {
453 CC1120_DEVIATION_M, APRS_DEV_M,
454 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
455 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
456 (APRS_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
457 CC1120_DRATE2, ((APRS_DRATE_E << CC1120_DRATE2_DATARATE_E) |
458 (((APRS_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
459 CC1120_DRATE1, ((APRS_DRATE_M >> 8) & 0xff),
460 CC1120_DRATE0, ((APRS_DRATE_M >> 0) & 0xff),
461 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
462 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
463 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
464 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
465 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
466 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
467 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
468 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
469 CC1120_SOFT_TX_DATA_CFG,((1 << CC1120_SOFT_TX_DATA_CFG_SOFT_TX_DATA_EN)),
470 CC1120_SOFT_TX_DATA_IN, 0,
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)
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_INFINITE)
545 ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_INFINITE);
547 if (changes & AO_RADIO_MODE_BITS_FIXED)
548 ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_FIXED);
550 ao_radio_mode = new_mode;
553 static const uint16_t radio_setup[] = {
554 #include "ao_cc1120_CC1120.h"
557 static uint8_t ao_radio_configured = 0;
564 ao_radio_strobe(CC1120_SRES);
566 for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2)
567 ao_radio_reg_write(radio_setup[i], radio_setup[i+1]);
573 ao_radio_configured = 1;
577 ao_radio_set_len(uint8_t len)
579 static uint8_t last_len;
581 if (len != last_len) {
582 ao_radio_reg_write(CC1120_PKT_LEN, len);
588 ao_radio_get(uint8_t len)
590 static uint32_t last_radio_setting;
592 ao_mutex_get(&ao_radio_mutex);
594 if (!ao_radio_configured)
596 if (ao_config.radio_setting != last_radio_setting) {
597 ao_radio_reg_write(CC1120_FREQ2, ao_config.radio_setting >> 16);
598 ao_radio_reg_write(CC1120_FREQ1, ao_config.radio_setting >> 8);
599 ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting);
600 last_radio_setting = ao_config.radio_setting;
602 ao_radio_set_len(len);
605 #define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
608 ao_rdf_start(uint8_t len)
613 ao_radio_set_mode(AO_RADIO_MODE_RDF);
623 ao_arch_block_interrupts();
624 while (!ao_radio_wake && !ao_radio_abort && !ao_radio_mcu_wake)
625 ao_sleep(&ao_radio_wake);
626 ao_arch_release_interrupts();
627 if (ao_radio_mcu_wake)
628 ao_radio_check_marc_status();
637 ao_rdf_start(AO_RADIO_RDF_LEN);
639 ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN);
645 ao_radio_continuity(uint8_t c)
650 ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN);
652 status = ao_radio_fifo_write_start();
653 for (i = 0; i < 3; i++) {
654 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
656 ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN);
658 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN);
660 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
661 status = ao_radio_fifo_write_stop(status);
667 ao_radio_rdf_abort(void)
670 ao_wakeup(&ao_radio_wake);
674 ao_radio_test_cmd(void)
677 static uint8_t radio_on;
679 if (ao_cmd_lex_c != '\n') {
681 mode = (uint8_t) ao_cmd_lex_u32;
684 if ((mode & 2) && !radio_on) {
686 ao_monitor_disable();
689 ao_packet_slave_stop();
692 ao_radio_set_mode(AO_RADIO_MODE_TEST);
693 ao_radio_strobe(CC1120_STX);
695 for (i = 0; i < 10; i++) {
696 ao_delay(AO_MS_TO_TICKS(100));
697 ao_radio_reg_write(CC1120_SOFT_TX_DATA_IN, 0);
702 for (t = 0; t < 10; t++) {
703 printf ("status: %02x\n", ao_radio_status());
704 ao_delay(AO_MS_TO_TICKS(100));
711 printf ("Hit a character to stop..."); flush();
715 if ((mode & 1) && radio_on) {
726 ao_radio_wait_isr(uint16_t timeout)
730 ao_arch_block_interrupts();
731 while (!ao_radio_wake && !ao_radio_mcu_wake && !ao_radio_abort)
732 if (ao_sleep(&ao_radio_wake))
734 ao_arch_release_interrupts();
737 if (ao_radio_mcu_wake)
738 ao_radio_check_marc_status();
742 ao_radio_wait_tx(uint8_t wait_fifo)
744 uint8_t fifo_space = 0;
747 ao_radio_wait_isr(0);
750 fifo_space = ao_radio_tx_fifo_space();
751 } while (!fifo_space && !ao_radio_abort);
755 static uint8_t tx_data[(AO_RADIO_MAX_SEND + 4) * 2];
758 ao_radio_send(const void *d, uint8_t size)
761 uint8_t *e = tx_data;
768 encode_len = ao_fec_encode(d, size, tx_data);
770 ao_radio_get(encode_len);
774 /* Flush any pending TX bytes */
775 ao_radio_strobe(CC1120_SFTX);
778 fifo_space = CC1120_FIFO_SIZE;
780 this_len = encode_len;
783 if (this_len > fifo_space) {
784 this_len = fifo_space;
785 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_BUF);
787 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_FINISH);
790 ao_radio_fifo_write(e, this_len);
792 encode_len -= this_len;
798 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
801 fifo_space = ao_radio_wait_tx(encode_len != 0);
802 if (ao_radio_abort) {
807 while (started && !ao_radio_abort && !ao_radio_tx_finished)
808 ao_radio_wait_isr(0);
812 #define AO_RADIO_LOTS 64
815 ao_radio_send_aprs(ao_radio_fill_func fill)
817 uint8_t buf[AO_RADIO_LOTS], *b;
825 fifo_space = CC1120_FIFO_SIZE;
827 cnt = (*fill)(buf, sizeof(buf));
834 /* At the last buffer, set the total length */
836 ao_radio_set_len(total & 0xff);
840 uint8_t this_len = cnt;
842 /* Wait for some space in the fifo */
843 while (!ao_radio_abort && (fifo_space = ao_radio_tx_fifo_space()) == 0) {
845 ao_radio_wait_isr(0);
849 if (this_len > fifo_space)
850 this_len = fifo_space;
856 ao_radio_set_mode(AO_RADIO_MODE_APRS_LAST_BUF);
858 ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
860 ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
862 ao_radio_fifo_write(b, this_len);
869 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
871 if (ao_radio_abort) {
875 /* Wait for the transmitter to go idle */
877 ao_radio_wait_isr(0);
882 static uint8_t rx_data[(AO_RADIO_MAX_RECV + 4) * 2 * 8];
883 static uint16_t rx_data_count;
884 static uint16_t rx_data_consumed;
885 static uint16_t rx_data_cur;
886 static uint8_t rx_ignore;
887 static uint8_t rx_waiting;
890 static uint32_t rx_start_tick, rx_packet_tick, rx_done_tick, rx_last_done_tick;
892 uint32_t ao_rx_start_tick, ao_rx_packet_tick, ao_rx_done_tick, ao_rx_last_done_tick;
894 #include <ao_profile.h>
898 ao_radio_rx_isr(void)
902 d = AO_CC1120_SPI.dr;
903 AO_CC1120_SPI.dr = 0;
904 if (rx_ignore == 0) {
905 if (rx_data_cur >= rx_data_count)
906 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
908 rx_data[rx_data_cur++] = d;
909 if (rx_waiting && rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) {
912 rx_packet_tick = ao_profile_tick();
913 if (rx_data_cur < rx_data_count)
917 ao_wakeup(&ao_radio_wake);
925 ao_radio_rx_wait(void)
928 if (ao_radio_mcu_wake)
929 ao_radio_check_marc_status();
930 ao_alarm(AO_MS_TO_TICKS(100));
931 ao_arch_block_interrupts();
933 while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&
937 if (ao_sleep(&ao_radio_wake))
941 ao_arch_release_interrupts();
943 } while (ao_radio_mcu_wake);
946 rx_data_consumed += AO_FEC_DECODE_BLOCK;
948 return rx_data_cur - rx_data_consumed;
950 return AO_FEC_DECODE_BLOCK;
954 ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout)
958 uint8_t radio_rssi = 0;
961 static int been_here = 0;
963 size -= 2; /* status bytes */
964 if (size > AO_RADIO_MAX_RECV) {
965 ao_delay(AO_SEC_TO_TICKS(1));
969 rx_start_tick = ao_profile_tick();
972 len = size + 2; /* CRC bytes */
973 len += 1 + ~(len & 1); /* 1 or two pad bytes */
974 len *= 2; /* 1/2 rate convolution */
975 rx_data_count = len * 8; /* bytes to bits */
977 rx_data_consumed = 0;
980 /* Must be set before changing the frequency; any abort
981 * after the frequency is set needs to terminate the read
982 * so that the registers can be reprogrammed
986 /* configure interrupt pin */
988 ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
991 ao_radio_mcu_wake = 0;
993 AO_CC1120_SPI.cr2 = 0;
996 (void) AO_CC1120_SPI.dr;
998 /* Have the radio signal when the preamble quality goes high */
999 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_PQT_REACHED);
1000 ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1001 AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_HIGH);
1002 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr);
1003 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
1004 ao_exti_enable(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN);
1006 ao_radio_strobe(CC1120_SRX);
1008 /* Wait for the preamble to appear */
1009 ao_radio_wait_isr(timeout);
1010 if (ao_radio_abort) {
1015 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT);
1016 ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1017 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
1019 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
1020 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
1022 ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
1024 ret = ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait);
1026 ao_radio_burst_read_stop();
1029 /* Convert from 'real' rssi to cc1111-style values */
1031 rssi0 = ao_radio_reg_read(CC1120_RSSI0);
1033 int8_t rssi = ao_radio_reg_read(CC1120_RSSI1);
1034 ao_radio_rssi = rssi;
1036 /* Bound it to the representable range */
1039 radio_rssi = AO_RADIO_FROM_RSSI (rssi);
1042 ao_radio_strobe(CC1120_SIDLE);
1046 /* Store the received RSSI value; the crc-OK byte is already done */
1048 ((uint8_t *) d)[size] = radio_rssi;
1051 rx_last_done_tick = rx_done_tick;
1052 rx_done_tick = ao_profile_tick();
1054 ao_rx_start_tick = rx_start_tick;
1055 ao_rx_packet_tick = rx_packet_tick;
1056 ao_rx_done_tick = rx_done_tick;
1057 ao_rx_last_done_tick = rx_last_done_tick;
1065 static char *cc1120_state_name[] = {
1066 [CC1120_STATUS_STATE_IDLE] = "IDLE",
1067 [CC1120_STATUS_STATE_RX] = "RX",
1068 [CC1120_STATUS_STATE_TX] = "TX",
1069 [CC1120_STATUS_STATE_FSTXON] = "FSTXON",
1070 [CC1120_STATUS_STATE_CALIBRATE] = "CALIBRATE",
1071 [CC1120_STATUS_STATE_SETTLING] = "SETTLING",
1072 [CC1120_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
1073 [CC1120_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
1076 struct ao_cc1120_reg {
1081 const static struct ao_cc1120_reg ao_cc1120_reg[] = {
1082 { .addr = CC1120_IOCFG3, .name = "IOCFG3" },
1083 { .addr = CC1120_IOCFG2, .name = "IOCFG2" },
1084 { .addr = CC1120_IOCFG1, .name = "IOCFG1" },
1085 { .addr = CC1120_IOCFG0, .name = "IOCFG0" },
1086 { .addr = CC1120_SYNC3, .name = "SYNC3" },
1087 { .addr = CC1120_SYNC2, .name = "SYNC2" },
1088 { .addr = CC1120_SYNC1, .name = "SYNC1" },
1089 { .addr = CC1120_SYNC0, .name = "SYNC0" },
1090 { .addr = CC1120_SYNC_CFG1, .name = "SYNC_CFG1" },
1091 { .addr = CC1120_SYNC_CFG0, .name = "SYNC_CFG0" },
1092 { .addr = CC1120_DEVIATION_M, .name = "DEVIATION_M" },
1093 { .addr = CC1120_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
1094 { .addr = CC1120_DCFILT_CFG, .name = "DCFILT_CFG" },
1095 { .addr = CC1120_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
1096 { .addr = CC1120_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
1097 { .addr = CC1120_FREQ_IF_CFG, .name = "FREQ_IF_CFG" },
1098 { .addr = CC1120_IQIC, .name = "IQIC" },
1099 { .addr = CC1120_CHAN_BW, .name = "CHAN_BW" },
1100 { .addr = CC1120_MDMCFG1, .name = "MDMCFG1" },
1101 { .addr = CC1120_MDMCFG0, .name = "MDMCFG0" },
1102 { .addr = CC1120_DRATE2, .name = "DRATE2" },
1103 { .addr = CC1120_DRATE1, .name = "DRATE1" },
1104 { .addr = CC1120_DRATE0, .name = "DRATE0" },
1105 { .addr = CC1120_AGC_REF, .name = "AGC_REF" },
1106 { .addr = CC1120_AGC_CS_THR, .name = "AGC_CS_THR" },
1107 { .addr = CC1120_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
1108 { .addr = CC1120_AGC_CFG3, .name = "AGC_CFG3" },
1109 { .addr = CC1120_AGC_CFG2, .name = "AGC_CFG2" },
1110 { .addr = CC1120_AGC_CFG1, .name = "AGC_CFG1" },
1111 { .addr = CC1120_AGC_CFG0, .name = "AGC_CFG0" },
1112 { .addr = CC1120_FIFO_CFG, .name = "FIFO_CFG" },
1113 { .addr = CC1120_DEV_ADDR, .name = "DEV_ADDR" },
1114 { .addr = CC1120_SETTLING_CFG, .name = "SETTLING_CFG" },
1115 { .addr = CC1120_FS_CFG, .name = "FS_CFG" },
1116 { .addr = CC1120_WOR_CFG1, .name = "WOR_CFG1" },
1117 { .addr = CC1120_WOR_CFG0, .name = "WOR_CFG0" },
1118 { .addr = CC1120_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
1119 { .addr = CC1120_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
1120 { .addr = CC1120_PKT_CFG2, .name = "PKT_CFG2" },
1121 { .addr = CC1120_PKT_CFG1, .name = "PKT_CFG1" },
1122 { .addr = CC1120_PKT_CFG0, .name = "PKT_CFG0" },
1123 { .addr = CC1120_RFEND_CFG1, .name = "RFEND_CFG1" },
1124 { .addr = CC1120_RFEND_CFG0, .name = "RFEND_CFG0" },
1125 { .addr = CC1120_PA_CFG2, .name = "PA_CFG2" },
1126 { .addr = CC1120_PA_CFG1, .name = "PA_CFG1" },
1127 { .addr = CC1120_PA_CFG0, .name = "PA_CFG0" },
1128 { .addr = CC1120_PKT_LEN, .name = "PKT_LEN" },
1129 { .addr = CC1120_IF_MIX_CFG, .name = "IF_MIX_CFG" },
1130 { .addr = CC1120_FREQOFF_CFG, .name = "FREQOFF_CFG" },
1131 { .addr = CC1120_TOC_CFG, .name = "TOC_CFG" },
1132 { .addr = CC1120_MARC_SPARE, .name = "MARC_SPARE" },
1133 { .addr = CC1120_ECG_CFG, .name = "ECG_CFG" },
1134 { .addr = CC1120_SOFT_TX_DATA_CFG, .name = "SOFT_TX_DATA_CFG" },
1135 { .addr = CC1120_EXT_CTRL, .name = "EXT_CTRL" },
1136 { .addr = CC1120_RCCAL_FINE, .name = "RCCAL_FINE" },
1137 { .addr = CC1120_RCCAL_COARSE, .name = "RCCAL_COARSE" },
1138 { .addr = CC1120_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
1139 { .addr = CC1120_FREQOFF1, .name = "FREQOFF1" },
1140 { .addr = CC1120_FREQOFF0, .name = "FREQOFF0" },
1141 { .addr = CC1120_FREQ2, .name = "FREQ2" },
1142 { .addr = CC1120_FREQ1, .name = "FREQ1" },
1143 { .addr = CC1120_FREQ0, .name = "FREQ0" },
1144 { .addr = CC1120_IF_ADC2, .name = "IF_ADC2" },
1145 { .addr = CC1120_IF_ADC1, .name = "IF_ADC1" },
1146 { .addr = CC1120_IF_ADC0, .name = "IF_ADC0" },
1147 { .addr = CC1120_FS_DIG1, .name = "FS_DIG1" },
1148 { .addr = CC1120_FS_DIG0, .name = "FS_DIG0" },
1149 { .addr = CC1120_FS_CAL3, .name = "FS_CAL3" },
1150 { .addr = CC1120_FS_CAL2, .name = "FS_CAL2" },
1151 { .addr = CC1120_FS_CAL1, .name = "FS_CAL1" },
1152 { .addr = CC1120_FS_CAL0, .name = "FS_CAL0" },
1153 { .addr = CC1120_FS_CHP, .name = "FS_CHP" },
1154 { .addr = CC1120_FS_DIVTWO, .name = "FS_DIVTWO" },
1155 { .addr = CC1120_FS_DSM1, .name = "FS_DSM1" },
1156 { .addr = CC1120_FS_DSM0, .name = "FS_DSM0" },
1157 { .addr = CC1120_FS_DVC1, .name = "FS_DVC1" },
1158 { .addr = CC1120_FS_DVC0, .name = "FS_DVC0" },
1159 { .addr = CC1120_FS_LBI, .name = "FS_LBI" },
1160 { .addr = CC1120_FS_PFD, .name = "FS_PFD" },
1161 { .addr = CC1120_FS_PRE, .name = "FS_PRE" },
1162 { .addr = CC1120_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
1163 { .addr = CC1120_FS_SPARE, .name = "FS_SPARE" },
1164 { .addr = CC1120_FS_VCO4, .name = "FS_VCO4" },
1165 { .addr = CC1120_FS_VCO3, .name = "FS_VCO3" },
1166 { .addr = CC1120_FS_VCO2, .name = "FS_VCO2" },
1167 { .addr = CC1120_FS_VCO1, .name = "FS_VCO1" },
1168 { .addr = CC1120_FS_VCO0, .name = "FS_VCO0" },
1169 { .addr = CC1120_GBIAS6, .name = "GBIAS6" },
1170 { .addr = CC1120_GBIAS5, .name = "GBIAS5" },
1171 { .addr = CC1120_GBIAS4, .name = "GBIAS4" },
1172 { .addr = CC1120_GBIAS3, .name = "GBIAS3" },
1173 { .addr = CC1120_GBIAS2, .name = "GBIAS2" },
1174 { .addr = CC1120_GBIAS1, .name = "GBIAS1" },
1175 { .addr = CC1120_GBIAS0, .name = "GBIAS0" },
1176 { .addr = CC1120_IFAMP, .name = "IFAMP" },
1177 { .addr = CC1120_LNA, .name = "LNA" },
1178 { .addr = CC1120_RXMIX, .name = "RXMIX" },
1179 { .addr = CC1120_XOSC5, .name = "XOSC5" },
1180 { .addr = CC1120_XOSC4, .name = "XOSC4" },
1181 { .addr = CC1120_XOSC3, .name = "XOSC3" },
1182 { .addr = CC1120_XOSC2, .name = "XOSC2" },
1183 { .addr = CC1120_XOSC1, .name = "XOSC1" },
1184 { .addr = CC1120_XOSC0, .name = "XOSC0" },
1185 { .addr = CC1120_ANALOG_SPARE, .name = "ANALOG_SPARE" },
1186 { .addr = CC1120_PA_CFG3, .name = "PA_CFG3" },
1187 { .addr = CC1120_WOR_TIME1, .name = "WOR_TIME1" },
1188 { .addr = CC1120_WOR_TIME0, .name = "WOR_TIME0" },
1189 { .addr = CC1120_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
1190 { .addr = CC1120_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
1191 { .addr = CC1120_BIST, .name = "BIST" },
1192 { .addr = CC1120_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
1193 { .addr = CC1120_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
1194 { .addr = CC1120_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
1195 { .addr = CC1120_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
1196 { .addr = CC1120_IQIE_I1, .name = "IQIE_I1" },
1197 { .addr = CC1120_IQIE_I0, .name = "IQIE_I0" },
1198 { .addr = CC1120_IQIE_Q1, .name = "IQIE_Q1" },
1199 { .addr = CC1120_IQIE_Q0, .name = "IQIE_Q0" },
1200 { .addr = CC1120_RSSI1, .name = "RSSI1" },
1201 { .addr = CC1120_RSSI0, .name = "RSSI0" },
1202 { .addr = CC1120_MARCSTATE, .name = "MARCSTATE" },
1203 { .addr = CC1120_LQI_VAL, .name = "LQI_VAL" },
1204 { .addr = CC1120_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
1205 { .addr = CC1120_DEM_STATUS, .name = "DEM_STATUS" },
1206 { .addr = CC1120_FREQOFF_EST1, .name = "FREQOFF_EST1" },
1207 { .addr = CC1120_FREQOFF_EST0, .name = "FREQOFF_EST0" },
1208 { .addr = CC1120_AGC_GAIN3, .name = "AGC_GAIN3" },
1209 { .addr = CC1120_AGC_GAIN2, .name = "AGC_GAIN2" },
1210 { .addr = CC1120_AGC_GAIN1, .name = "AGC_GAIN1" },
1211 { .addr = CC1120_AGC_GAIN0, .name = "AGC_GAIN0" },
1212 { .addr = CC1120_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
1213 { .addr = CC1120_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
1214 { .addr = CC1120_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
1215 { .addr = CC1120_RNDGEN, .name = "RNDGEN" },
1216 { .addr = CC1120_MAGN2, .name = "MAGN2" },
1217 { .addr = CC1120_MAGN1, .name = "MAGN1" },
1218 { .addr = CC1120_MAGN0, .name = "MAGN0" },
1219 { .addr = CC1120_ANG1, .name = "ANG1" },
1220 { .addr = CC1120_ANG0, .name = "ANG0" },
1221 { .addr = CC1120_CHFILT_I2, .name = "CHFILT_I2" },
1222 { .addr = CC1120_CHFILT_I1, .name = "CHFILT_I1" },
1223 { .addr = CC1120_CHFILT_I0, .name = "CHFILT_I0" },
1224 { .addr = CC1120_CHFILT_Q2, .name = "CHFILT_Q2" },
1225 { .addr = CC1120_CHFILT_Q1, .name = "CHFILT_Q1" },
1226 { .addr = CC1120_CHFILT_Q0, .name = "CHFILT_Q0" },
1227 { .addr = CC1120_GPIO_STATUS, .name = "GPIO_STATUS" },
1228 { .addr = CC1120_FSCAL_CTRL, .name = "FSCAL_CTRL" },
1229 { .addr = CC1120_PHASE_ADJUST, .name = "PHASE_ADJUST" },
1230 { .addr = CC1120_PARTNUMBER, .name = "PARTNUMBER" },
1231 { .addr = CC1120_PARTVERSION, .name = "PARTVERSION" },
1232 { .addr = CC1120_SERIAL_STATUS, .name = "SERIAL_STATUS" },
1233 { .addr = CC1120_RX_STATUS, .name = "RX_STATUS" },
1234 { .addr = CC1120_TX_STATUS, .name = "TX_STATUS" },
1235 { .addr = CC1120_MARC_STATUS1, .name = "MARC_STATUS1" },
1236 { .addr = CC1120_MARC_STATUS0, .name = "MARC_STATUS0" },
1237 { .addr = CC1120_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
1238 { .addr = CC1120_FSRF_TEST, .name = "FSRF_TEST" },
1239 { .addr = CC1120_PRE_TEST, .name = "PRE_TEST" },
1240 { .addr = CC1120_PRE_OVR, .name = "PRE_OVR" },
1241 { .addr = CC1120_ADC_TEST, .name = "ADC_TEST" },
1242 { .addr = CC1120_DVC_TEST, .name = "DVC_TEST" },
1243 { .addr = CC1120_ATEST, .name = "ATEST" },
1244 { .addr = CC1120_ATEST_LVDS, .name = "ATEST_LVDS" },
1245 { .addr = CC1120_ATEST_MODE, .name = "ATEST_MODE" },
1246 { .addr = CC1120_XOSC_TEST1, .name = "XOSC_TEST1" },
1247 { .addr = CC1120_XOSC_TEST0, .name = "XOSC_TEST0" },
1248 { .addr = CC1120_RXFIRST, .name = "RXFIRST" },
1249 { .addr = CC1120_TXFIRST, .name = "TXFIRST" },
1250 { .addr = CC1120_RXLAST, .name = "RXLAST" },
1251 { .addr = CC1120_TXLAST, .name = "TXLAST" },
1252 { .addr = CC1120_NUM_TXBYTES, .name = "NUM_TXBYTES" },
1253 { .addr = CC1120_NUM_RXBYTES, .name = "NUM_RXBYTES" },
1254 { .addr = CC1120_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
1255 { .addr = CC1120_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
1258 #define AO_NUM_CC1120_REG (sizeof ao_cc1120_reg / sizeof ao_cc1120_reg[0])
1260 static void ao_radio_show(void) {
1261 uint8_t status = ao_radio_status();
1265 status = ao_radio_status();
1266 printf ("Status: %02x\n", status);
1267 printf ("CHIP_RDY: %d\n", (status >> CC1120_STATUS_CHIP_RDY) & 1);
1268 printf ("STATE: %s\n", cc1120_state_name[(status >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK]);
1269 printf ("MARC: %02x\n", ao_radio_get_marc_status());
1271 for (i = 0; i < AO_NUM_CC1120_REG; i++)
1272 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name);
1276 static void ao_radio_beep(void) {
1280 static void ao_radio_packet(void) {
1281 static const uint8_t packet[] = {
1283 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1284 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1285 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1286 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1292 ao_radio_send(packet, sizeof (packet));
1296 ao_radio_test_recv()
1301 if (ao_radio_recv(bytes, 34)) {
1302 if (bytes[33] & 0x80)
1306 printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32]));
1307 for (b = 0; b < 32; b++)
1308 printf (" %02x", bytes[b]);
1314 #include <ao_aprs.h>
1319 ao_packet_slave_stop();
1326 static const struct ao_cmds ao_radio_cmds[] = {
1327 { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
1330 { ao_radio_aprs, "G\0Send APRS packet" },
1332 { ao_radio_show, "R\0Show CC1120 status" },
1333 { ao_radio_beep, "b\0Emit an RDF beacon" },
1334 { ao_radio_packet, "p\0Send a test packet" },
1335 { ao_radio_test_recv, "q\0Recv a test packet" },
1345 ao_radio_configured = 0;
1346 ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN));
1349 AO_CC1120_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN));
1350 for (i = 0; i < 10000; i++) {
1351 if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0)
1354 AO_CC1120_SPI_CS_PORT->bsrr = (1 << AO_CC1120_SPI_CS_PIN);
1356 ao_panic(AO_PANIC_SELF_TEST_CC1120);
1359 /* Enable the EXTI interrupt for the appropriate pin */
1360 ao_enable_port(AO_CC1120_INT_PORT);
1361 ao_exti_setup(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1362 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
1365 /* Enable the hacked up GPIO3 pin */
1366 ao_enable_port(AO_CC1120_MCU_WAKEUP_PORT);
1367 ao_exti_setup(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN,
1368 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED,
1369 ao_radio_mcu_wakeup_isr);
1371 ao_cmd_register(&ao_radio_cmds[0]);