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
302 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
303 * Rdata = -------------------------------------- * fosc
306 * Symbol rate 38400 Baud:
308 * DATARATE_M = 239914
310 * CHANBW = 74.42 (round to 100)
312 * Symbol rate 9600 Baud:
314 * DATARATE_M = 239914
316 * CHANBW = 58.58 (round to 62.5)
318 * Symbol rate 2400 Baud:
320 * DATARATE_M = 239914
322 * CHANBW = 47.61 (round to 50)
325 #define PACKET_DRATE_M 239914
327 #define PACKET_DRATE_E_384 9
328 #define PACKET_CHAN_BW_384 0x02 /* 200 / 2 = 100 */
330 #define PACKET_DRATE_E_96 7
331 #define PACKET_CHAN_BW_96 0x42 /* 125 / 2 = 62.5 */
333 #define PACKET_DRATE_E_24 5
334 #define PACKET_CHAN_BW_24 0x04 /* 200 / 4 = 50 */
336 static const uint16_t packet_setup[] = {
337 CC1120_DEVIATION_M, PACKET_DEV_M,
338 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
339 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
340 (PACKET_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
341 CC1120_DRATE1, ((PACKET_DRATE_M >> 8) & 0xff),
342 CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff),
343 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
344 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
345 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
346 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
347 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
348 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
349 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
350 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
351 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
352 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
353 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
354 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
355 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
356 AO_CC1120_MARC_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP,
359 static const uint16_t packet_setup_384[] = {
360 CC1120_DRATE2, ((PACKET_DRATE_E_384 << CC1120_DRATE2_DATARATE_E) |
361 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
362 CC1120_CHAN_BW, PACKET_CHAN_BW_384,
363 CC1120_PA_CFG0, 0x7b,
366 static const uint16_t packet_setup_96[] = {
367 CC1120_DRATE2, ((PACKET_DRATE_E_96 << CC1120_DRATE2_DATARATE_E) |
368 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
369 CC1120_CHAN_BW, PACKET_CHAN_BW_96,
370 CC1120_PA_CFG0, 0x7d,
373 static const uint16_t packet_setup_24[] = {
374 CC1120_DRATE2, ((PACKET_DRATE_E_24 << CC1120_DRATE2_DATARATE_E) |
375 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
376 CC1120_CHAN_BW, PACKET_CHAN_BW_24,
377 CC1120_PA_CFG0, 0x7e,
380 static const uint16_t packet_tx_setup[] = {
381 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
382 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
383 AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG,
386 static const uint16_t packet_rx_setup[] = {
387 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
388 (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT)),
389 AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT,
393 * RDF deviation is 5kHz
395 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
397 * 32e6Hz / (2 ** 24) * (256 + 71) * (2 ** 3) = 4989
402 #define RDF_PACKET_LEN 50
405 * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
407 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
408 * Rdata = -------------------------------------- * fosc
414 * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
416 #define RDF_DRATE_E 5
417 #define RDF_DRATE_M 25166
418 #define RDF_PACKET_LEN 50
420 static const uint16_t rdf_setup[] = {
421 CC1120_DEVIATION_M, RDF_DEV_M,
422 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
423 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
424 (RDF_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
425 CC1120_DRATE2, ((RDF_DRATE_E << CC1120_DRATE2_DATARATE_E) |
426 (((RDF_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
427 CC1120_DRATE1, ((RDF_DRATE_M >> 8) & 0xff),
428 CC1120_DRATE0, ((RDF_DRATE_M >> 0) & 0xff),
429 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
430 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
431 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
432 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
433 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
434 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
435 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
436 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
437 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
438 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
439 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
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)),
442 CC1120_PA_CFG0, 0x7e,
446 * APRS deviation is 3kHz
448 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
450 * 32e6Hz / (2 ** 24) * (256 + 137) * (2 ** 2) = 2998Hz
454 #define APRS_DEV_M 137
457 * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate)
459 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
460 * Rdata = -------------------------------------- * fosc
463 * DATARATE_M = 239914
466 * Rdata = 9599.998593330383301
469 #define APRS_DRATE_E 7
470 #define APRS_DRATE_M 239914
472 static const uint16_t aprs_setup[] = {
473 CC1120_DEVIATION_M, APRS_DEV_M,
474 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
475 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
476 (APRS_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
477 CC1120_DRATE2, ((APRS_DRATE_E << CC1120_DRATE2_DATARATE_E) |
478 (((APRS_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
479 CC1120_DRATE1, ((APRS_DRATE_M >> 8) & 0xff),
480 CC1120_DRATE0, ((APRS_DRATE_M >> 0) & 0xff),
481 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
482 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
483 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
484 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
485 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
486 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
487 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
488 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
489 CC1120_PA_CFG0, 0x7d,
493 * For Test mode, we want an unmodulated carrier. To do that, we
494 * set the deviation to zero and enable a preamble so that the radio
495 * turns on before we send any data
498 static const uint16_t test_setup[] = {
499 CC1120_DEVIATION_M, 0,
500 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
501 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
502 (0 << CC1120_MODCFG_DEV_E_DEV_E)),
503 CC1120_DRATE2, ((APRS_DRATE_E << CC1120_DRATE2_DATARATE_E) |
504 (((APRS_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
505 CC1120_DRATE1, ((APRS_DRATE_M >> 8) & 0xff),
506 CC1120_DRATE0, ((APRS_DRATE_M >> 0) & 0xff),
507 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
508 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
509 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
510 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
511 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
512 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
513 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
514 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
517 #define AO_PKT_CFG0_INFINITE ((0 << CC1120_PKT_CFG0_RESERVED7) | \
518 (CC1120_PKT_CFG0_LENGTH_CONFIG_INFINITE << CC1120_PKT_CFG0_LENGTH_CONFIG) | \
519 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | \
520 (0 << CC1120_PKT_CFG0_UART_MODE_EN) | \
521 (0 << CC1120_PKT_CFG0_UART_SWAP_EN))
523 #define AO_PKT_CFG0_FIXED ((0 << CC1120_PKT_CFG0_RESERVED7) | \
524 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) | \
525 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | \
526 (0 << CC1120_PKT_CFG0_UART_MODE_EN) | \
527 (0 << CC1120_PKT_CFG0_UART_SWAP_EN))
529 static uint16_t ao_radio_mode;
531 #define AO_RADIO_MODE_BITS_PACKET 1
532 #define AO_RADIO_MODE_BITS_PACKET_TX 2
533 #define AO_RADIO_MODE_BITS_TX_BUF 4
534 #define AO_RADIO_MODE_BITS_TX_FINISH 8
535 #define AO_RADIO_MODE_BITS_PACKET_RX 16
536 #define AO_RADIO_MODE_BITS_RDF 32
537 #define AO_RADIO_MODE_BITS_APRS 64
538 #define AO_RADIO_MODE_BITS_TEST 128
539 #define AO_RADIO_MODE_BITS_INFINITE 256
540 #define AO_RADIO_MODE_BITS_FIXED 512
542 #define AO_RADIO_MODE_NONE 0
543 #define AO_RADIO_MODE_PACKET_TX_BUF (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_BUF)
544 #define AO_RADIO_MODE_PACKET_TX_FINISH (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_FINISH)
545 #define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_RX)
546 #define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_TX_FINISH)
547 #define AO_RADIO_MODE_APRS_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
548 #define AO_RADIO_MODE_APRS_LAST_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_BUF)
549 #define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
550 #define AO_RADIO_MODE_TEST (AO_RADIO_MODE_BITS_TEST | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
553 _ao_radio_set_regs(const uint16_t *regs, int nreg)
557 for (i = 0; i < nreg; i++) {
558 ao_radio_reg_write(regs[0], regs[1]);
563 #define ao_radio_set_regs(setup) _ao_radio_set_regs(setup, (sizeof (setup) / sizeof(setup[0])) >> 1)
566 ao_radio_set_mode(uint16_t new_mode)
570 if (new_mode == ao_radio_mode)
573 changes = new_mode & (~ao_radio_mode);
575 if (changes & AO_RADIO_MODE_BITS_PACKET) {
576 ao_radio_set_regs(packet_setup);
578 switch (ao_config.radio_rate) {
580 case AO_RADIO_RATE_38400:
581 ao_radio_set_regs(packet_setup_384);
583 case AO_RADIO_RATE_9600:
584 ao_radio_set_regs(packet_setup_96);
586 case AO_RADIO_RATE_2400:
587 ao_radio_set_regs(packet_setup_24);
592 if (changes & AO_RADIO_MODE_BITS_PACKET_TX)
593 ao_radio_set_regs(packet_tx_setup);
595 if (changes & AO_RADIO_MODE_BITS_TX_BUF)
596 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_TXFIFO_THR);
598 if (changes & AO_RADIO_MODE_BITS_TX_FINISH)
599 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG);
601 if (changes & AO_RADIO_MODE_BITS_PACKET_RX)
602 ao_radio_set_regs(packet_rx_setup);
604 if (changes & AO_RADIO_MODE_BITS_RDF)
605 ao_radio_set_regs(rdf_setup);
607 if (changes & AO_RADIO_MODE_BITS_APRS)
608 ao_radio_set_regs(aprs_setup);
610 if (changes & AO_RADIO_MODE_BITS_TEST)
611 ao_radio_set_regs(test_setup);
613 if (changes & AO_RADIO_MODE_BITS_INFINITE)
614 ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_INFINITE);
616 if (changes & AO_RADIO_MODE_BITS_FIXED)
617 ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_FIXED);
619 ao_radio_mode = new_mode;
622 static const uint16_t radio_setup[] = {
623 #include "ao_cc1120_CC1120.h"
626 static uint8_t ao_radio_configured = 0;
631 ao_radio_strobe(CC1120_SRES);
633 ao_radio_set_regs(radio_setup);
639 ao_radio_configured = 1;
643 ao_radio_set_len(uint8_t len)
645 static uint8_t last_len;
647 if (len != last_len) {
648 ao_radio_reg_write(CC1120_PKT_LEN, len);
654 ao_radio_get(uint8_t len)
656 static uint32_t last_radio_setting;
657 static uint8_t last_radio_rate;
659 ao_mutex_get(&ao_radio_mutex);
661 if (!ao_radio_configured)
663 if (ao_config.radio_setting != last_radio_setting) {
664 ao_radio_reg_write(CC1120_FREQ2, ao_config.radio_setting >> 16);
665 ao_radio_reg_write(CC1120_FREQ1, ao_config.radio_setting >> 8);
666 ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting);
667 last_radio_setting = ao_config.radio_setting;
669 if (ao_config.radio_rate != last_radio_rate) {
670 ao_radio_mode &= ~AO_RADIO_MODE_BITS_PACKET;
671 last_radio_rate = ao_config.radio_rate;
673 ao_radio_set_len(len);
676 #define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
679 ao_rdf_start(uint8_t len)
684 ao_radio_set_mode(AO_RADIO_MODE_RDF);
694 ao_arch_block_interrupts();
695 while (!ao_radio_wake && !ao_radio_abort && !ao_radio_mcu_wake)
696 ao_sleep(&ao_radio_wake);
697 ao_arch_release_interrupts();
698 if (ao_radio_mcu_wake)
699 ao_radio_check_marc_status();
708 ao_rdf_start(AO_RADIO_RDF_LEN);
710 ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN);
716 ao_radio_continuity(uint8_t c)
721 ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN);
723 status = ao_radio_fifo_write_start();
724 for (i = 0; i < 3; i++) {
725 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
727 ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN);
729 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN);
731 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
732 status = ao_radio_fifo_write_stop(status);
738 ao_radio_rdf_abort(void)
741 ao_wakeup(&ao_radio_wake);
745 ao_radio_test_cmd(void)
748 static uint8_t radio_on;
750 if (ao_cmd_lex_c != '\n') {
752 mode = (uint8_t) ao_cmd_lex_u32;
755 if ((mode & 2) && !radio_on) {
757 ao_monitor_disable();
760 ao_packet_slave_stop();
763 ao_radio_set_mode(AO_RADIO_MODE_TEST);
764 ao_radio_strobe(CC1120_STX);
767 for (t = 0; t < 10; t++) {
768 printf ("status: %02x\n", ao_radio_status());
769 ao_delay(AO_MS_TO_TICKS(100));
776 printf ("Hit a character to stop..."); flush();
780 if ((mode & 1) && radio_on) {
791 ao_radio_wait_isr(uint16_t timeout)
795 ao_arch_block_interrupts();
796 while (!ao_radio_wake && !ao_radio_mcu_wake && !ao_radio_abort)
797 if (ao_sleep(&ao_radio_wake))
799 ao_arch_release_interrupts();
802 if (ao_radio_mcu_wake)
803 ao_radio_check_marc_status();
807 ao_radio_wait_tx(uint8_t wait_fifo)
809 uint8_t fifo_space = 0;
812 ao_radio_wait_isr(0);
815 fifo_space = ao_radio_tx_fifo_space();
816 } while (!fifo_space && !ao_radio_abort);
820 static uint8_t tx_data[(AO_RADIO_MAX_SEND + 4) * 2];
823 ao_radio_send(const void *d, uint8_t size)
825 uint8_t *e = tx_data;
831 encode_len = ao_fec_encode(d, size, tx_data);
833 ao_radio_get(encode_len);
837 /* Flush any pending TX bytes */
838 ao_radio_strobe(CC1120_SFTX);
841 fifo_space = CC1120_FIFO_SIZE;
843 this_len = encode_len;
846 if (this_len > fifo_space) {
847 this_len = fifo_space;
848 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_BUF);
850 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_FINISH);
853 ao_radio_fifo_write(e, this_len);
855 encode_len -= this_len;
861 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
864 fifo_space = ao_radio_wait_tx(encode_len != 0);
865 if (ao_radio_abort) {
870 while (started && !ao_radio_abort && !ao_radio_tx_finished)
871 ao_radio_wait_isr(0);
875 #define AO_RADIO_LOTS 64
878 ao_radio_send_aprs(ao_radio_fill_func fill)
880 uint8_t buf[AO_RADIO_LOTS], *b;
888 fifo_space = CC1120_FIFO_SIZE;
890 cnt = (*fill)(buf, sizeof(buf));
897 /* At the last buffer, set the total length */
899 ao_radio_set_len(total & 0xff);
903 uint8_t this_len = cnt;
905 /* Wait for some space in the fifo */
906 while (!ao_radio_abort && (fifo_space = ao_radio_tx_fifo_space()) == 0) {
908 ao_radio_wait_isr(0);
912 if (this_len > fifo_space)
913 this_len = fifo_space;
919 ao_radio_set_mode(AO_RADIO_MODE_APRS_LAST_BUF);
921 ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
923 ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
925 ao_radio_fifo_write(b, this_len);
932 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
934 if (ao_radio_abort) {
938 /* Wait for the transmitter to go idle */
940 ao_radio_wait_isr(0);
945 static uint8_t rx_data[(AO_RADIO_MAX_RECV + 4) * 2 * 8];
946 static uint16_t rx_data_count;
947 static uint16_t rx_data_consumed;
948 static uint16_t rx_data_cur;
949 static uint8_t rx_ignore;
950 static uint8_t rx_waiting;
953 static uint32_t rx_start_tick, rx_packet_tick, rx_done_tick, rx_last_done_tick;
955 uint32_t ao_rx_start_tick, ao_rx_packet_tick, ao_rx_done_tick, ao_rx_last_done_tick;
957 #include <ao_profile.h>
961 ao_radio_rx_isr(void)
965 d = AO_CC1120_SPI.dr;
966 AO_CC1120_SPI.dr = 0;
967 if (rx_ignore == 0) {
968 if (rx_data_cur >= rx_data_count)
969 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
971 rx_data[rx_data_cur++] = d;
972 if (rx_waiting && rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) {
975 rx_packet_tick = ao_profile_tick();
976 if (rx_data_cur < rx_data_count)
980 ao_wakeup(&ao_radio_wake);
988 ao_radio_rx_wait(void)
991 if (ao_radio_mcu_wake)
992 ao_radio_check_marc_status();
993 ao_alarm(AO_MS_TO_TICKS(100));
994 ao_arch_block_interrupts();
996 while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&
1000 if (ao_sleep(&ao_radio_wake))
1004 ao_arch_release_interrupts();
1006 } while (ao_radio_mcu_wake);
1009 rx_data_consumed += AO_FEC_DECODE_BLOCK;
1011 return rx_data_cur - rx_data_consumed;
1013 return AO_FEC_DECODE_BLOCK;
1017 ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout)
1020 uint8_t radio_rssi = 0;
1024 size -= 2; /* status bytes */
1025 if (size > AO_RADIO_MAX_RECV) {
1026 ao_delay(AO_SEC_TO_TICKS(1));
1030 rx_start_tick = ao_profile_tick();
1033 len = size + 2; /* CRC bytes */
1034 len += 1 + ~(len & 1); /* 1 or two pad bytes */
1035 len *= 2; /* 1/2 rate convolution */
1036 rx_data_count = len * 8; /* bytes to bits */
1038 rx_data_consumed = 0;
1041 /* Must be set before changing the frequency; any abort
1042 * after the frequency is set needs to terminate the read
1043 * so that the registers can be reprogrammed
1047 /* configure interrupt pin */
1049 ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
1052 ao_radio_mcu_wake = 0;
1054 AO_CC1120_SPI.cr2 = 0;
1056 /* clear any RXNE */
1057 (void) AO_CC1120_SPI.dr;
1059 /* Have the radio signal when the preamble quality goes high */
1060 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_PQT_REACHED);
1061 ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1062 AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_HIGH);
1063 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr);
1064 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
1065 ao_exti_enable(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN);
1067 ao_radio_strobe(CC1120_SRX);
1069 /* Wait for the preamble to appear */
1070 ao_radio_wait_isr(timeout);
1071 if (ao_radio_abort) {
1076 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT);
1077 ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1078 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
1080 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
1081 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
1083 ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
1085 ret = ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait);
1087 ao_radio_burst_read_stop();
1090 /* Convert from 'real' rssi to cc1111-style values */
1092 rssi0 = ao_radio_reg_read(CC1120_RSSI0);
1094 int8_t rssi = ao_radio_reg_read(CC1120_RSSI1);
1095 ao_radio_rssi = rssi;
1097 /* Bound it to the representable range */
1100 radio_rssi = AO_RADIO_FROM_RSSI (rssi);
1103 ao_radio_strobe(CC1120_SIDLE);
1107 /* Store the received RSSI value; the crc-OK byte is already done */
1109 ((uint8_t *) d)[size] = radio_rssi;
1112 rx_last_done_tick = rx_done_tick;
1113 rx_done_tick = ao_profile_tick();
1115 ao_rx_start_tick = rx_start_tick;
1116 ao_rx_packet_tick = rx_packet_tick;
1117 ao_rx_done_tick = rx_done_tick;
1118 ao_rx_last_done_tick = rx_last_done_tick;
1126 static char *cc1120_state_name[] = {
1127 [CC1120_STATUS_STATE_IDLE] = "IDLE",
1128 [CC1120_STATUS_STATE_RX] = "RX",
1129 [CC1120_STATUS_STATE_TX] = "TX",
1130 [CC1120_STATUS_STATE_FSTXON] = "FSTXON",
1131 [CC1120_STATUS_STATE_CALIBRATE] = "CALIBRATE",
1132 [CC1120_STATUS_STATE_SETTLING] = "SETTLING",
1133 [CC1120_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
1134 [CC1120_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
1137 struct ao_cc1120_reg {
1142 const static struct ao_cc1120_reg ao_cc1120_reg[] = {
1143 { .addr = CC1120_IOCFG3, .name = "IOCFG3" },
1144 { .addr = CC1120_IOCFG2, .name = "IOCFG2" },
1145 { .addr = CC1120_IOCFG1, .name = "IOCFG1" },
1146 { .addr = CC1120_IOCFG0, .name = "IOCFG0" },
1147 { .addr = CC1120_SYNC3, .name = "SYNC3" },
1148 { .addr = CC1120_SYNC2, .name = "SYNC2" },
1149 { .addr = CC1120_SYNC1, .name = "SYNC1" },
1150 { .addr = CC1120_SYNC0, .name = "SYNC0" },
1151 { .addr = CC1120_SYNC_CFG1, .name = "SYNC_CFG1" },
1152 { .addr = CC1120_SYNC_CFG0, .name = "SYNC_CFG0" },
1153 { .addr = CC1120_DEVIATION_M, .name = "DEVIATION_M" },
1154 { .addr = CC1120_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
1155 { .addr = CC1120_DCFILT_CFG, .name = "DCFILT_CFG" },
1156 { .addr = CC1120_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
1157 { .addr = CC1120_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
1158 { .addr = CC1120_FREQ_IF_CFG, .name = "FREQ_IF_CFG" },
1159 { .addr = CC1120_IQIC, .name = "IQIC" },
1160 { .addr = CC1120_CHAN_BW, .name = "CHAN_BW" },
1161 { .addr = CC1120_MDMCFG1, .name = "MDMCFG1" },
1162 { .addr = CC1120_MDMCFG0, .name = "MDMCFG0" },
1163 { .addr = CC1120_DRATE2, .name = "DRATE2" },
1164 { .addr = CC1120_DRATE1, .name = "DRATE1" },
1165 { .addr = CC1120_DRATE0, .name = "DRATE0" },
1166 { .addr = CC1120_AGC_REF, .name = "AGC_REF" },
1167 { .addr = CC1120_AGC_CS_THR, .name = "AGC_CS_THR" },
1168 { .addr = CC1120_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
1169 { .addr = CC1120_AGC_CFG3, .name = "AGC_CFG3" },
1170 { .addr = CC1120_AGC_CFG2, .name = "AGC_CFG2" },
1171 { .addr = CC1120_AGC_CFG1, .name = "AGC_CFG1" },
1172 { .addr = CC1120_AGC_CFG0, .name = "AGC_CFG0" },
1173 { .addr = CC1120_FIFO_CFG, .name = "FIFO_CFG" },
1174 { .addr = CC1120_DEV_ADDR, .name = "DEV_ADDR" },
1175 { .addr = CC1120_SETTLING_CFG, .name = "SETTLING_CFG" },
1176 { .addr = CC1120_FS_CFG, .name = "FS_CFG" },
1177 { .addr = CC1120_WOR_CFG1, .name = "WOR_CFG1" },
1178 { .addr = CC1120_WOR_CFG0, .name = "WOR_CFG0" },
1179 { .addr = CC1120_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
1180 { .addr = CC1120_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
1181 { .addr = CC1120_PKT_CFG2, .name = "PKT_CFG2" },
1182 { .addr = CC1120_PKT_CFG1, .name = "PKT_CFG1" },
1183 { .addr = CC1120_PKT_CFG0, .name = "PKT_CFG0" },
1184 { .addr = CC1120_RFEND_CFG1, .name = "RFEND_CFG1" },
1185 { .addr = CC1120_RFEND_CFG0, .name = "RFEND_CFG0" },
1186 { .addr = CC1120_PA_CFG2, .name = "PA_CFG2" },
1187 { .addr = CC1120_PA_CFG1, .name = "PA_CFG1" },
1188 { .addr = CC1120_PA_CFG0, .name = "PA_CFG0" },
1189 { .addr = CC1120_PKT_LEN, .name = "PKT_LEN" },
1190 { .addr = CC1120_IF_MIX_CFG, .name = "IF_MIX_CFG" },
1191 { .addr = CC1120_FREQOFF_CFG, .name = "FREQOFF_CFG" },
1192 { .addr = CC1120_TOC_CFG, .name = "TOC_CFG" },
1193 { .addr = CC1120_MARC_SPARE, .name = "MARC_SPARE" },
1194 { .addr = CC1120_ECG_CFG, .name = "ECG_CFG" },
1195 { .addr = CC1120_SOFT_TX_DATA_CFG, .name = "SOFT_TX_DATA_CFG" },
1196 { .addr = CC1120_EXT_CTRL, .name = "EXT_CTRL" },
1197 { .addr = CC1120_RCCAL_FINE, .name = "RCCAL_FINE" },
1198 { .addr = CC1120_RCCAL_COARSE, .name = "RCCAL_COARSE" },
1199 { .addr = CC1120_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
1200 { .addr = CC1120_FREQOFF1, .name = "FREQOFF1" },
1201 { .addr = CC1120_FREQOFF0, .name = "FREQOFF0" },
1202 { .addr = CC1120_FREQ2, .name = "FREQ2" },
1203 { .addr = CC1120_FREQ1, .name = "FREQ1" },
1204 { .addr = CC1120_FREQ0, .name = "FREQ0" },
1205 { .addr = CC1120_IF_ADC2, .name = "IF_ADC2" },
1206 { .addr = CC1120_IF_ADC1, .name = "IF_ADC1" },
1207 { .addr = CC1120_IF_ADC0, .name = "IF_ADC0" },
1208 { .addr = CC1120_FS_DIG1, .name = "FS_DIG1" },
1209 { .addr = CC1120_FS_DIG0, .name = "FS_DIG0" },
1210 { .addr = CC1120_FS_CAL3, .name = "FS_CAL3" },
1211 { .addr = CC1120_FS_CAL2, .name = "FS_CAL2" },
1212 { .addr = CC1120_FS_CAL1, .name = "FS_CAL1" },
1213 { .addr = CC1120_FS_CAL0, .name = "FS_CAL0" },
1214 { .addr = CC1120_FS_CHP, .name = "FS_CHP" },
1215 { .addr = CC1120_FS_DIVTWO, .name = "FS_DIVTWO" },
1216 { .addr = CC1120_FS_DSM1, .name = "FS_DSM1" },
1217 { .addr = CC1120_FS_DSM0, .name = "FS_DSM0" },
1218 { .addr = CC1120_FS_DVC1, .name = "FS_DVC1" },
1219 { .addr = CC1120_FS_DVC0, .name = "FS_DVC0" },
1220 { .addr = CC1120_FS_LBI, .name = "FS_LBI" },
1221 { .addr = CC1120_FS_PFD, .name = "FS_PFD" },
1222 { .addr = CC1120_FS_PRE, .name = "FS_PRE" },
1223 { .addr = CC1120_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
1224 { .addr = CC1120_FS_SPARE, .name = "FS_SPARE" },
1225 { .addr = CC1120_FS_VCO4, .name = "FS_VCO4" },
1226 { .addr = CC1120_FS_VCO3, .name = "FS_VCO3" },
1227 { .addr = CC1120_FS_VCO2, .name = "FS_VCO2" },
1228 { .addr = CC1120_FS_VCO1, .name = "FS_VCO1" },
1229 { .addr = CC1120_FS_VCO0, .name = "FS_VCO0" },
1230 { .addr = CC1120_GBIAS6, .name = "GBIAS6" },
1231 { .addr = CC1120_GBIAS5, .name = "GBIAS5" },
1232 { .addr = CC1120_GBIAS4, .name = "GBIAS4" },
1233 { .addr = CC1120_GBIAS3, .name = "GBIAS3" },
1234 { .addr = CC1120_GBIAS2, .name = "GBIAS2" },
1235 { .addr = CC1120_GBIAS1, .name = "GBIAS1" },
1236 { .addr = CC1120_GBIAS0, .name = "GBIAS0" },
1237 { .addr = CC1120_IFAMP, .name = "IFAMP" },
1238 { .addr = CC1120_LNA, .name = "LNA" },
1239 { .addr = CC1120_RXMIX, .name = "RXMIX" },
1240 { .addr = CC1120_XOSC5, .name = "XOSC5" },
1241 { .addr = CC1120_XOSC4, .name = "XOSC4" },
1242 { .addr = CC1120_XOSC3, .name = "XOSC3" },
1243 { .addr = CC1120_XOSC2, .name = "XOSC2" },
1244 { .addr = CC1120_XOSC1, .name = "XOSC1" },
1245 { .addr = CC1120_XOSC0, .name = "XOSC0" },
1246 { .addr = CC1120_ANALOG_SPARE, .name = "ANALOG_SPARE" },
1247 { .addr = CC1120_PA_CFG3, .name = "PA_CFG3" },
1248 { .addr = CC1120_WOR_TIME1, .name = "WOR_TIME1" },
1249 { .addr = CC1120_WOR_TIME0, .name = "WOR_TIME0" },
1250 { .addr = CC1120_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
1251 { .addr = CC1120_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
1252 { .addr = CC1120_BIST, .name = "BIST" },
1253 { .addr = CC1120_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
1254 { .addr = CC1120_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
1255 { .addr = CC1120_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
1256 { .addr = CC1120_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
1257 { .addr = CC1120_IQIE_I1, .name = "IQIE_I1" },
1258 { .addr = CC1120_IQIE_I0, .name = "IQIE_I0" },
1259 { .addr = CC1120_IQIE_Q1, .name = "IQIE_Q1" },
1260 { .addr = CC1120_IQIE_Q0, .name = "IQIE_Q0" },
1261 { .addr = CC1120_RSSI1, .name = "RSSI1" },
1262 { .addr = CC1120_RSSI0, .name = "RSSI0" },
1263 { .addr = CC1120_MARCSTATE, .name = "MARCSTATE" },
1264 { .addr = CC1120_LQI_VAL, .name = "LQI_VAL" },
1265 { .addr = CC1120_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
1266 { .addr = CC1120_DEM_STATUS, .name = "DEM_STATUS" },
1267 { .addr = CC1120_FREQOFF_EST1, .name = "FREQOFF_EST1" },
1268 { .addr = CC1120_FREQOFF_EST0, .name = "FREQOFF_EST0" },
1269 { .addr = CC1120_AGC_GAIN3, .name = "AGC_GAIN3" },
1270 { .addr = CC1120_AGC_GAIN2, .name = "AGC_GAIN2" },
1271 { .addr = CC1120_AGC_GAIN1, .name = "AGC_GAIN1" },
1272 { .addr = CC1120_AGC_GAIN0, .name = "AGC_GAIN0" },
1273 { .addr = CC1120_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
1274 { .addr = CC1120_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
1275 { .addr = CC1120_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
1276 { .addr = CC1120_RNDGEN, .name = "RNDGEN" },
1277 { .addr = CC1120_MAGN2, .name = "MAGN2" },
1278 { .addr = CC1120_MAGN1, .name = "MAGN1" },
1279 { .addr = CC1120_MAGN0, .name = "MAGN0" },
1280 { .addr = CC1120_ANG1, .name = "ANG1" },
1281 { .addr = CC1120_ANG0, .name = "ANG0" },
1282 { .addr = CC1120_CHFILT_I2, .name = "CHFILT_I2" },
1283 { .addr = CC1120_CHFILT_I1, .name = "CHFILT_I1" },
1284 { .addr = CC1120_CHFILT_I0, .name = "CHFILT_I0" },
1285 { .addr = CC1120_CHFILT_Q2, .name = "CHFILT_Q2" },
1286 { .addr = CC1120_CHFILT_Q1, .name = "CHFILT_Q1" },
1287 { .addr = CC1120_CHFILT_Q0, .name = "CHFILT_Q0" },
1288 { .addr = CC1120_GPIO_STATUS, .name = "GPIO_STATUS" },
1289 { .addr = CC1120_FSCAL_CTRL, .name = "FSCAL_CTRL" },
1290 { .addr = CC1120_PHASE_ADJUST, .name = "PHASE_ADJUST" },
1291 { .addr = CC1120_PARTNUMBER, .name = "PARTNUMBER" },
1292 { .addr = CC1120_PARTVERSION, .name = "PARTVERSION" },
1293 { .addr = CC1120_SERIAL_STATUS, .name = "SERIAL_STATUS" },
1294 { .addr = CC1120_RX_STATUS, .name = "RX_STATUS" },
1295 { .addr = CC1120_TX_STATUS, .name = "TX_STATUS" },
1296 { .addr = CC1120_MARC_STATUS1, .name = "MARC_STATUS1" },
1297 { .addr = CC1120_MARC_STATUS0, .name = "MARC_STATUS0" },
1298 { .addr = CC1120_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
1299 { .addr = CC1120_FSRF_TEST, .name = "FSRF_TEST" },
1300 { .addr = CC1120_PRE_TEST, .name = "PRE_TEST" },
1301 { .addr = CC1120_PRE_OVR, .name = "PRE_OVR" },
1302 { .addr = CC1120_ADC_TEST, .name = "ADC_TEST" },
1303 { .addr = CC1120_DVC_TEST, .name = "DVC_TEST" },
1304 { .addr = CC1120_ATEST, .name = "ATEST" },
1305 { .addr = CC1120_ATEST_LVDS, .name = "ATEST_LVDS" },
1306 { .addr = CC1120_ATEST_MODE, .name = "ATEST_MODE" },
1307 { .addr = CC1120_XOSC_TEST1, .name = "XOSC_TEST1" },
1308 { .addr = CC1120_XOSC_TEST0, .name = "XOSC_TEST0" },
1309 { .addr = CC1120_RXFIRST, .name = "RXFIRST" },
1310 { .addr = CC1120_TXFIRST, .name = "TXFIRST" },
1311 { .addr = CC1120_RXLAST, .name = "RXLAST" },
1312 { .addr = CC1120_TXLAST, .name = "TXLAST" },
1313 { .addr = CC1120_NUM_TXBYTES, .name = "NUM_TXBYTES" },
1314 { .addr = CC1120_NUM_RXBYTES, .name = "NUM_RXBYTES" },
1315 { .addr = CC1120_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
1316 { .addr = CC1120_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
1319 #define AO_NUM_CC1120_REG (sizeof ao_cc1120_reg / sizeof ao_cc1120_reg[0])
1321 static void ao_radio_show(void) {
1322 uint8_t status = ao_radio_status();
1326 status = ao_radio_status();
1327 printf ("Status: %02x\n", status);
1328 printf ("CHIP_RDY: %d\n", (status >> CC1120_STATUS_CHIP_RDY) & 1);
1329 printf ("STATE: %s\n", cc1120_state_name[(status >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK]);
1330 printf ("MARC: %02x\n", ao_radio_get_marc_status());
1332 for (i = 0; i < AO_NUM_CC1120_REG; i++)
1333 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name);
1337 static void ao_radio_beep(void) {
1341 static void ao_radio_packet(void) {
1342 static const uint8_t packet[] = {
1344 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1345 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1346 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1347 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1353 ao_radio_send(packet, sizeof (packet));
1357 ao_radio_test_recv()
1362 if (ao_radio_recv(bytes, 34)) {
1363 if (bytes[33] & 0x80)
1367 printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32]));
1368 for (b = 0; b < 32; b++)
1369 printf (" %02x", bytes[b]);
1375 #include <ao_aprs.h>
1380 ao_packet_slave_stop();
1387 static const struct ao_cmds ao_radio_cmds[] = {
1388 { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
1391 { ao_radio_aprs, "G\0Send APRS packet" },
1393 { ao_radio_show, "R\0Show CC1120 status" },
1394 { ao_radio_beep, "b\0Emit an RDF beacon" },
1395 { ao_radio_packet, "p\0Send a test packet" },
1396 { ao_radio_test_recv, "q\0Recv a test packet" },
1404 ao_radio_configured = 0;
1405 ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN));
1408 AO_CC1120_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN));
1409 for (i = 0; i < 10000; i++) {
1410 if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0)
1413 AO_CC1120_SPI_CS_PORT->bsrr = (1 << AO_CC1120_SPI_CS_PIN);
1415 ao_panic(AO_PANIC_SELF_TEST_CC1120);
1418 /* Enable the EXTI interrupt for the appropriate pin */
1419 ao_enable_port(AO_CC1120_INT_PORT);
1420 ao_exti_setup(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1421 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
1424 /* Enable the hacked up GPIO3 pin */
1425 ao_enable_port(AO_CC1120_MCU_WAKEUP_PORT);
1426 ao_exti_setup(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN,
1427 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED,
1428 ao_radio_mcu_wakeup_isr);
1430 ao_cmd_register(&ao_radio_cmds[0]);