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_try_select(task_id) ao_spi_try_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS,AO_SPI_SPEED_4MHz, task_id)
45 #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)
46 #define ao_radio_deselect() ao_spi_put_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS)
47 #define ao_radio_spi_start_bytes() ao_spi_start_bytes(AO_CC1120_SPI_BUS)
48 #define ao_radio_spi_stop_bytes() ao_spi_stop_bytes(AO_CC1120_SPI_BUS)
49 #define ao_radio_spi_send_byte(b) ao_spi_send_byte(b, AO_CC1120_SPI_BUS)
50 #define ao_radio_spi_recv_byte() ao_spi_recv_byte(AO_CC1120_SPI_BUS)
51 #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1120_SPI_BUS)
52 #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1120_SPI_BUS)
53 #define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1120_SPI_BUS)
54 #define ao_radio_duplex(o,i,l) ao_spi_duplex((o), (i), (l), AO_CC1120_SPI_BUS)
57 ao_radio_reg_read(uint16_t addr)
63 printf("\t\tao_radio_reg_read (%04x): ", addr); flush();
65 if (CC1120_IS_EXTENDED(addr)) {
66 data[0] = ((1 << CC1120_READ) |
72 data[0] = ((1 << CC1120_READ) |
78 ao_radio_spi_send(data, d);
79 ao_radio_spi_recv(data, 1);
82 printf (" %02x\n", data[0]);
88 ao_radio_reg_write(uint16_t addr, uint8_t value)
94 printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value);
96 if (CC1120_IS_EXTENDED(addr)) {
97 data[0] = ((0 << CC1120_READ) |
103 data[0] = ((0 << CC1120_READ) |
104 (0 << CC1120_BURST) |
110 ao_radio_spi_send(data, d+1);
115 _ao_radio_burst_read_start (uint16_t addr)
117 ao_radio_spi_start_bytes();
119 if (CC1120_IS_EXTENDED(addr)) {
120 ao_radio_spi_send_byte((1 << CC1120_READ) |
121 (1 << CC1120_BURST) |
124 addr |= ((1 << CC1120_READ) |
125 (1 << CC1120_BURST));
127 ao_radio_spi_send_byte(addr);
131 ao_radio_burst_read_stop (void)
133 ao_radio_spi_stop_bytes();
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_int_pin(void)
209 return ao_gpio_get(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_CC1120_INT);
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_enable_isr(void)
267 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
268 ao_exti_enable(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN);
272 ao_radio_start_tx(void)
274 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr);
275 ao_radio_tx_finished = 0;
276 ao_radio_strobe(CC1120_STX);
283 uint8_t state = (ao_radio_strobe(CC1120_SIDLE) >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK;
284 if (state == CC1120_STATUS_STATE_IDLE)
286 if (state == CC1120_STATUS_STATE_TX_FIFO_ERROR)
287 ao_radio_strobe(CC1120_SFTX);
288 if (state == CC1120_STATUS_STATE_RX_FIFO_ERROR)
289 ao_radio_strobe(CC1120_SFRX);
291 /* Flush any pending TX bytes */
292 ao_radio_strobe(CC1120_SFTX);
298 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
300 * Deviation for 38400 baud should be 20.5kHz:
302 * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz
304 * Deviation for 9600 baud should be 5.125kHz:
306 * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 3) = 5127Hz
308 * Deviation for 2400 baud should be 1.28125kHz, but cc1111 and
309 * cc115l can't do that, so we'll use 1.5kHz instead:
311 * 32e6Hz / (2 ** 24) * (256 + 137) * (2 ** 1) = 1499Hz
314 #define PACKET_DEV_M_384 80
315 #define PACKET_DEV_E_384 5
317 #define PACKET_DEV_M_96 80
318 #define PACKET_DEV_E_96 3
320 #define PACKET_DEV_M_24 137
321 #define PACKET_DEV_E_24 1
324 * For our packet data
326 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
327 * Rdata = -------------------------------------- * fosc
330 * Given the bit period of the baseband, T, the bandwidth of the
331 * baseband signal is B = 1/(2T). The overall bandwidth of the
332 * modulated signal is then Channel bandwidth = 2Δf + 2B.
334 * 38400 -- 2 * 20500 + 38400 = 79.4 kHz
335 * 9600 -- 2 * 5.125 + 9600 = 19.9 kHz
336 * 2400 -- 2 * 1.5 + 2400 = 5.4 khz
338 * Symbol rate 38400 Baud:
340 * DATARATE_M = 239914
342 * CHANBW = 79.4 (round to 100)
344 * Symbol rate 9600 Baud:
346 * DATARATE_M = 239914
348 * CHANBW = 19.9 (round to 20)
350 * Symbol rate 2400 Baud:
352 * DATARATE_M = 239914
354 * CHANBW = 5.0 (round to 8.0)
357 #define PACKET_DRATE_M 239914
359 #define PACKET_DRATE_E_384 9
362 #define PACKET_CHAN_BW_384 ((0 << CC1120_CHAN_BW_CHFILT_BYPASS) | \
363 (CC1120_CHAN_BW_ADC_CIC_DECFACT_20 << CC1120_CHAN_BW_ADC_CIC_DECFACT) | \
364 (2 << CC1120_CHAN_BW_BB_CIC_DECFACT))
366 #define PACKET_DRATE_E_96 7
368 #define PACKET_CHAN_BW_96 ((0 << CC1120_CHAN_BW_CHFILT_BYPASS) | \
369 (CC1120_CHAN_BW_ADC_CIC_DECFACT_20 << CC1120_CHAN_BW_ADC_CIC_DECFACT) | \
370 (10 << CC1120_CHAN_BW_BB_CIC_DECFACT))
372 #define PACKET_DRATE_E_24 5
374 #define PACKET_CHAN_BW_24 ((0 << CC1120_CHAN_BW_CHFILT_BYPASS) | \
375 (CC1120_CHAN_BW_ADC_CIC_DECFACT_20 << CC1120_CHAN_BW_ADC_CIC_DECFACT) | \
376 (25 << CC1120_CHAN_BW_BB_CIC_DECFACT))
378 static const uint16_t packet_setup[] = {
379 CC1120_DRATE1, ((PACKET_DRATE_M >> 8) & 0xff),
380 CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff),
381 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
382 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
383 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
384 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
385 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
386 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
387 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
388 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
389 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
390 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
391 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
392 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
393 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
394 AO_CC1120_MARC_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP,
397 static const uint16_t packet_setup_384[] = {
398 CC1120_DEVIATION_M, PACKET_DEV_M_384,
399 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
400 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
401 (PACKET_DEV_E_384 << CC1120_MODCFG_DEV_E_DEV_E)),
402 CC1120_DRATE2, ((PACKET_DRATE_E_384 << CC1120_DRATE2_DATARATE_E) |
403 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
404 CC1120_CHAN_BW, PACKET_CHAN_BW_384,
405 CC1120_PA_CFG0, 0x7b,
408 static const uint16_t packet_setup_96[] = {
409 CC1120_DEVIATION_M, PACKET_DEV_M_96,
410 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
411 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
412 (PACKET_DEV_E_96 << CC1120_MODCFG_DEV_E_DEV_E)),
413 CC1120_DRATE2, ((PACKET_DRATE_E_96 << CC1120_DRATE2_DATARATE_E) |
414 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
415 CC1120_CHAN_BW, PACKET_CHAN_BW_96,
416 CC1120_PA_CFG0, 0x7d,
419 static const uint16_t packet_setup_24[] = {
420 CC1120_DEVIATION_M, PACKET_DEV_M_24,
421 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
422 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
423 (PACKET_DEV_E_24 << CC1120_MODCFG_DEV_E_DEV_E)),
424 CC1120_DRATE2, ((PACKET_DRATE_E_24 << CC1120_DRATE2_DATARATE_E) |
425 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
426 CC1120_CHAN_BW, PACKET_CHAN_BW_24,
427 CC1120_PA_CFG0, 0x7e,
430 #define AO_CC1120_TX_BUFFER 64
432 static const uint16_t packet_tx_setup[] = {
433 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
434 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
435 CC1120_FIFO_CFG, ((0 << CC1120_FIFO_CFG_CRC_AUTOFLUSH) |
436 (AO_CC1120_TX_BUFFER << CC1120_FIFO_CFG_FIFO_THR)),
439 static const uint16_t packet_rx_setup[] = {
440 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
441 (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT)),
442 AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT,
446 * RDF deviation is 5kHz
448 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
450 * 32e6Hz / (2 ** 24) * (256 + 71) * (2 ** 3) = 4989
455 #define RDF_PACKET_LEN 50
458 * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
460 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
461 * Rdata = -------------------------------------- * fosc
467 * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
469 #define RDF_DRATE_E 5
470 #define RDF_DRATE_M 25166
471 #define RDF_PACKET_LEN 50
473 static const uint16_t rdf_setup[] = {
474 CC1120_DEVIATION_M, RDF_DEV_M,
475 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
476 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
477 (RDF_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
478 CC1120_DRATE2, ((RDF_DRATE_E << CC1120_DRATE2_DATARATE_E) |
479 (((RDF_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
480 CC1120_DRATE1, ((RDF_DRATE_M >> 8) & 0xff),
481 CC1120_DRATE0, ((RDF_DRATE_M >> 0) & 0xff),
482 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
483 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
484 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
485 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
486 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
487 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
488 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
489 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
490 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
491 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
492 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
493 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
494 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
495 CC1120_PA_CFG0, 0x7e,
499 * APRS deviation is 3kHz
501 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
503 * 32e6Hz / (2 ** 24) * (256 + 137) * (2 ** 2) = 2998Hz
507 #define APRS_DEV_M 137
510 * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate)
512 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
513 * Rdata = -------------------------------------- * fosc
516 * DATARATE_M = 239914
519 * Rdata = 9599.998593330383301
522 #define APRS_DRATE_E 7
523 #define APRS_DRATE_M 239914
525 static const uint16_t aprs_setup[] = {
526 CC1120_DEVIATION_M, APRS_DEV_M,
527 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
528 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
529 (APRS_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
530 CC1120_DRATE2, ((APRS_DRATE_E << CC1120_DRATE2_DATARATE_E) |
531 (((APRS_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
532 CC1120_DRATE1, ((APRS_DRATE_M >> 8) & 0xff),
533 CC1120_DRATE0, ((APRS_DRATE_M >> 0) & 0xff),
534 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
535 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
536 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
537 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
538 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
539 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
540 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
541 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
542 CC1120_PA_CFG0, 0x7d,
543 CC1120_FIFO_CFG, ((0 << CC1120_FIFO_CFG_CRC_AUTOFLUSH) |
544 (AO_CC1120_TX_BUFFER << CC1120_FIFO_CFG_FIFO_THR)),
548 * For Test mode, we want an unmodulated carrier. To do that, we
549 * set the deviation to zero and enable a preamble so that the radio
550 * turns on before we send any data
553 static const uint16_t test_setup[] = {
554 CC1120_DEVIATION_M, 0,
555 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
556 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
557 (0 << CC1120_MODCFG_DEV_E_DEV_E)),
558 CC1120_DRATE2, ((APRS_DRATE_E << CC1120_DRATE2_DATARATE_E) |
559 (((APRS_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
560 CC1120_DRATE1, ((APRS_DRATE_M >> 8) & 0xff),
561 CC1120_DRATE0, ((APRS_DRATE_M >> 0) & 0xff),
562 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
563 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
564 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
565 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
566 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
567 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
568 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
569 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
572 #define AO_PKT_CFG0_INFINITE ((0 << CC1120_PKT_CFG0_RESERVED7) | \
573 (CC1120_PKT_CFG0_LENGTH_CONFIG_INFINITE << CC1120_PKT_CFG0_LENGTH_CONFIG) | \
574 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | \
575 (0 << CC1120_PKT_CFG0_UART_MODE_EN) | \
576 (0 << CC1120_PKT_CFG0_UART_SWAP_EN))
578 #define AO_PKT_CFG0_FIXED ((0 << CC1120_PKT_CFG0_RESERVED7) | \
579 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) | \
580 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | \
581 (0 << CC1120_PKT_CFG0_UART_MODE_EN) | \
582 (0 << CC1120_PKT_CFG0_UART_SWAP_EN))
584 static uint16_t ao_radio_mode;
586 #define AO_RADIO_MODE_BITS_PACKET 1
587 #define AO_RADIO_MODE_BITS_PACKET_TX 2
588 #define AO_RADIO_MODE_BITS_TX_BUF 4
589 #define AO_RADIO_MODE_BITS_TX_FINISH 8
590 #define AO_RADIO_MODE_BITS_PACKET_RX 16
591 #define AO_RADIO_MODE_BITS_RDF 32
592 #define AO_RADIO_MODE_BITS_APRS 64
593 #define AO_RADIO_MODE_BITS_TEST 128
594 #define AO_RADIO_MODE_BITS_INFINITE 256
595 #define AO_RADIO_MODE_BITS_FIXED 512
597 #define AO_RADIO_MODE_NONE 0
598 #define AO_RADIO_MODE_PACKET_TX_BUF (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_BUF)
599 #define AO_RADIO_MODE_PACKET_TX_FINISH (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_FINISH)
600 #define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_RX)
601 #define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_TX_FINISH)
602 #define AO_RADIO_MODE_APRS_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
603 #define AO_RADIO_MODE_APRS_LAST_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_BUF)
604 #define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
605 #define AO_RADIO_MODE_TEST (AO_RADIO_MODE_BITS_TEST | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
608 _ao_radio_set_regs(const uint16_t *regs, int nreg)
612 for (i = 0; i < nreg; i++) {
613 ao_radio_reg_write(regs[0], regs[1]);
618 #define ao_radio_set_regs(setup) _ao_radio_set_regs(setup, (sizeof (setup) / sizeof(setup[0])) >> 1)
621 ao_radio_set_mode(uint16_t new_mode)
625 if (new_mode == ao_radio_mode)
628 changes = new_mode & (~ao_radio_mode);
630 if (changes & AO_RADIO_MODE_BITS_PACKET) {
631 ao_radio_set_regs(packet_setup);
633 switch (ao_config.radio_rate) {
635 case AO_RADIO_RATE_38400:
636 ao_radio_set_regs(packet_setup_384);
638 case AO_RADIO_RATE_9600:
639 ao_radio_set_regs(packet_setup_96);
641 case AO_RADIO_RATE_2400:
642 ao_radio_set_regs(packet_setup_24);
647 if (changes & AO_RADIO_MODE_BITS_PACKET_TX)
648 ao_radio_set_regs(packet_tx_setup);
650 if (changes & AO_RADIO_MODE_BITS_TX_BUF)
651 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_TXFIFO_THR);
653 if (changes & AO_RADIO_MODE_BITS_TX_FINISH)
654 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG);
656 if (changes & AO_RADIO_MODE_BITS_PACKET_RX)
657 ao_radio_set_regs(packet_rx_setup);
659 if (changes & AO_RADIO_MODE_BITS_RDF)
660 ao_radio_set_regs(rdf_setup);
662 if (changes & AO_RADIO_MODE_BITS_APRS)
663 ao_radio_set_regs(aprs_setup);
665 if (changes & AO_RADIO_MODE_BITS_TEST)
666 ao_radio_set_regs(test_setup);
668 if (changes & AO_RADIO_MODE_BITS_INFINITE)
669 ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_INFINITE);
671 if (changes & AO_RADIO_MODE_BITS_FIXED)
672 ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_FIXED);
674 ao_radio_mode = new_mode;
677 static const uint16_t radio_setup[] = {
678 #include "ao_cc1120_CC1120.h"
681 static uint8_t ao_radio_configured = 0;
686 ao_radio_strobe(CC1120_SRES);
688 ao_radio_set_regs(radio_setup);
694 ao_radio_configured = 1;
698 ao_radio_set_len(uint8_t len)
700 static uint8_t last_len;
702 if (len != last_len) {
703 ao_radio_reg_write(CC1120_PKT_LEN, len);
709 ao_radio_get(uint8_t len)
711 static uint32_t last_radio_setting;
712 static uint8_t last_radio_rate;
714 ao_mutex_get(&ao_radio_mutex);
716 if (!ao_radio_configured)
718 if (ao_config.radio_setting != last_radio_setting) {
719 ao_radio_reg_write(CC1120_FREQ2, ao_config.radio_setting >> 16);
720 ao_radio_reg_write(CC1120_FREQ1, ao_config.radio_setting >> 8);
721 ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting);
722 last_radio_setting = ao_config.radio_setting;
724 if (ao_config.radio_rate != last_radio_rate) {
725 ao_radio_mode &= ~AO_RADIO_MODE_BITS_PACKET;
726 last_radio_rate = ao_config.radio_rate;
728 ao_radio_set_len(len);
731 #define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
734 ao_rdf_start(uint8_t len)
739 ao_radio_set_mode(AO_RADIO_MODE_RDF);
749 ao_arch_block_interrupts();
750 while (!ao_radio_wake && !ao_radio_abort && !ao_radio_mcu_wake) {
751 ao_radio_enable_isr();
752 ao_sleep(&ao_radio_wake);
754 ao_arch_release_interrupts();
755 if (ao_radio_mcu_wake)
756 ao_radio_check_marc_status();
765 ao_rdf_start(AO_RADIO_RDF_LEN);
767 ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN);
773 ao_radio_continuity(uint8_t c)
778 ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN);
780 status = ao_radio_fifo_write_start();
781 for (i = 0; i < 3; i++) {
782 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
784 ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN);
786 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN);
788 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
789 status = ao_radio_fifo_write_stop(status);
795 ao_radio_rdf_abort(void)
798 ao_wakeup(&ao_radio_wake);
802 ao_radio_test_cmd(void)
805 static uint8_t radio_on;
807 if (ao_cmd_lex_c != '\n') {
809 mode = (uint8_t) ao_cmd_lex_u32;
812 if ((mode & 2) && !radio_on) {
814 ao_monitor_disable();
817 ao_packet_slave_stop();
820 ao_radio_set_mode(AO_RADIO_MODE_TEST);
821 ao_radio_strobe(CC1120_STX);
824 for (t = 0; t < 10; t++) {
825 printf ("status: %02x\n", ao_radio_status());
826 ao_delay(AO_MS_TO_TICKS(100));
833 printf ("Hit a character to stop..."); flush();
837 if ((mode & 1) && radio_on) {
848 ao_radio_wait_isr(uint16_t timeout)
850 ao_arch_block_interrupts();
851 while (!ao_radio_wake && !ao_radio_mcu_wake && !ao_radio_abort)
852 if (ao_sleep_for(&ao_radio_wake, timeout))
854 ao_arch_release_interrupts();
855 if (ao_radio_mcu_wake)
856 ao_radio_check_marc_status();
860 ao_radio_wait_fifo(void)
862 while (ao_radio_int_pin() != 0 && !ao_radio_abort) {
864 ao_radio_enable_isr();
865 ao_radio_wait_isr(0);
869 static uint8_t tx_data[(AO_RADIO_MAX_SEND + 4) * 2];
872 ao_radio_send(const void *d, uint8_t size)
874 uint8_t *e = tx_data;
879 encode_len = ao_fec_encode(d, size, tx_data);
881 ao_radio_get(encode_len);
885 /* Flush any pending TX bytes */
886 ao_radio_strobe(CC1120_SFTX);
889 this_len = encode_len;
892 ao_radio_wait_fifo();
897 if (this_len > AO_CC1120_TX_BUFFER) {
898 this_len = AO_CC1120_TX_BUFFER;
899 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_BUF);
901 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_FINISH);
904 ao_radio_fifo_write(e, this_len);
906 encode_len -= this_len;
913 while (started && !ao_radio_abort && !ao_radio_tx_finished) {
915 ao_radio_enable_isr();
916 ao_radio_wait_isr(0);
924 ao_radio_send_aprs(ao_radio_fill_func fill)
926 uint8_t buf[AO_CC1120_TX_BUFFER];
936 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr);
938 cnt = (*fill)(buf, sizeof(buf));
945 /* Wait for some space in the fifo */
947 ao_radio_wait_fifo();
953 ao_radio_set_len(total & 0xff);
954 ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
956 ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
958 ao_radio_fifo_write(buf, cnt);
965 /* Wait for the transmitter to go idle */
966 while (started && ao_radio_int_pin() != 0 && !ao_radio_abort) {
968 ao_radio_enable_isr();
969 ao_radio_wait_isr(0);
976 static uint8_t rx_data[(AO_RADIO_MAX_RECV + 4) * 2 * 8];
977 static uint16_t rx_data_count;
978 static uint16_t rx_data_consumed;
979 static uint16_t rx_data_cur;
980 static uint8_t rx_ignore;
981 static uint8_t rx_waiting;
982 static uint8_t rx_starting;
983 static uint8_t rx_task_id;
984 static uint32_t rx_fast_start;
985 static uint32_t rx_slow_start;
986 static uint32_t rx_missed;
989 static uint32_t rx_start_tick, rx_packet_tick, rx_done_tick, rx_last_done_tick;
991 uint32_t ao_rx_start_tick, ao_rx_packet_tick, ao_rx_done_tick, ao_rx_last_done_tick;
993 #include <ao_profile.h>
997 ao_radio_rx_isr(void)
1002 if (ao_radio_try_select(rx_task_id)) {
1005 _ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
1018 ao_wakeup(&ao_radio_wake);
1020 d = ao_radio_spi_recv_byte();
1021 if (rx_ignore == 0) {
1022 if (rx_data_cur < rx_data_count)
1023 rx_data[rx_data_cur++] = d;
1024 if (rx_data_cur >= rx_data_count) {
1025 ao_spi_clr_cs(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN));
1026 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
1028 if (rx_waiting && rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) {
1030 if (!rx_packet_tick)
1031 rx_packet_tick = ao_profile_tick();
1032 if (rx_data_cur < rx_data_count)
1036 ao_wakeup(&ao_radio_wake);
1044 ao_radio_rx_wait(void)
1046 ao_arch_block_interrupts();
1048 while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&
1052 if (ao_sleep_for(&ao_radio_wake, AO_MS_TO_TICKS(100)))
1056 ao_arch_release_interrupts();
1057 if (ao_radio_abort || ao_radio_mcu_wake)
1059 rx_data_consumed += AO_FEC_DECODE_BLOCK;
1061 return rx_data_cur - rx_data_consumed;
1063 return AO_FEC_DECODE_BLOCK;
1067 ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout)
1070 uint8_t radio_rssi = 0;
1074 size -= 2; /* status bytes */
1075 if (size > AO_RADIO_MAX_RECV) {
1076 ao_delay(AO_SEC_TO_TICKS(1));
1080 rx_start_tick = ao_profile_tick();
1083 len = size + 2; /* CRC bytes */
1084 len += 1 + ~(len & 1); /* 1 or two pad bytes */
1085 len *= 2; /* 1/2 rate convolution */
1086 rx_data_count = len * 8; /* bytes to bits */
1088 rx_data_consumed = 0;
1091 /* Must be set before changing the frequency; any abort
1092 * after the frequency is set needs to terminate the read
1093 * so that the registers can be reprogrammed
1100 ao_radio_mcu_wake = 0;
1102 ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
1104 /* configure interrupt pin */
1105 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT);
1106 ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1107 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
1110 rx_task_id = ao_cur_task->task_id;
1112 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
1113 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
1115 ao_radio_strobe(CC1120_SRX);
1117 ao_arch_block_interrupts();
1118 while (rx_starting && !ao_radio_abort) {
1119 if (ao_sleep_for(&ao_radio_wake, timeout))
1122 uint8_t rx_task_id_save = rx_task_id;
1125 ao_arch_release_interrupts();
1127 if (ao_radio_abort) {
1128 if (rx_task_id_save == 0)
1129 ao_radio_burst_read_stop();
1134 if (rx_task_id_save) {
1137 _ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
1139 (void) ao_radio_spi_recv_byte();
1144 ret = ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait);
1146 ao_radio_burst_read_stop();
1148 if (ao_radio_mcu_wake)
1149 ao_radio_check_marc_status();
1154 /* Convert from 'real' rssi to cc1111-style values */
1156 rssi0 = ao_radio_reg_read(CC1120_RSSI0);
1158 int8_t rssi = ao_radio_reg_read(CC1120_RSSI1);
1159 ao_radio_rssi = rssi;
1161 /* Bound it to the representable range */
1164 radio_rssi = AO_RADIO_FROM_RSSI (rssi);
1171 /* Store the received RSSI value; the crc-OK byte is already done */
1173 ((uint8_t *) d)[size] = radio_rssi;
1176 rx_last_done_tick = rx_done_tick;
1177 rx_done_tick = ao_profile_tick();
1179 ao_rx_start_tick = rx_start_tick;
1180 ao_rx_packet_tick = rx_packet_tick;
1181 ao_rx_done_tick = rx_done_tick;
1182 ao_rx_last_done_tick = rx_last_done_tick;
1190 static char *cc1120_state_name[] = {
1191 [CC1120_STATUS_STATE_IDLE] = "IDLE",
1192 [CC1120_STATUS_STATE_RX] = "RX",
1193 [CC1120_STATUS_STATE_TX] = "TX",
1194 [CC1120_STATUS_STATE_FSTXON] = "FSTXON",
1195 [CC1120_STATUS_STATE_CALIBRATE] = "CALIBRATE",
1196 [CC1120_STATUS_STATE_SETTLING] = "SETTLING",
1197 [CC1120_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
1198 [CC1120_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
1201 struct ao_cc1120_reg {
1206 static const struct ao_cc1120_reg ao_cc1120_reg[] = {
1207 { .addr = CC1120_IOCFG3, .name = "IOCFG3" },
1208 { .addr = CC1120_IOCFG2, .name = "IOCFG2" },
1209 { .addr = CC1120_IOCFG1, .name = "IOCFG1" },
1210 { .addr = CC1120_IOCFG0, .name = "IOCFG0" },
1211 { .addr = CC1120_SYNC3, .name = "SYNC3" },
1212 { .addr = CC1120_SYNC2, .name = "SYNC2" },
1213 { .addr = CC1120_SYNC1, .name = "SYNC1" },
1214 { .addr = CC1120_SYNC0, .name = "SYNC0" },
1215 { .addr = CC1120_SYNC_CFG1, .name = "SYNC_CFG1" },
1216 { .addr = CC1120_SYNC_CFG0, .name = "SYNC_CFG0" },
1217 { .addr = CC1120_DEVIATION_M, .name = "DEVIATION_M" },
1218 { .addr = CC1120_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
1219 { .addr = CC1120_DCFILT_CFG, .name = "DCFILT_CFG" },
1220 { .addr = CC1120_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
1221 { .addr = CC1120_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
1222 { .addr = CC1120_FREQ_IF_CFG, .name = "FREQ_IF_CFG" },
1223 { .addr = CC1120_IQIC, .name = "IQIC" },
1224 { .addr = CC1120_CHAN_BW, .name = "CHAN_BW" },
1225 { .addr = CC1120_MDMCFG1, .name = "MDMCFG1" },
1226 { .addr = CC1120_MDMCFG0, .name = "MDMCFG0" },
1227 { .addr = CC1120_DRATE2, .name = "DRATE2" },
1228 { .addr = CC1120_DRATE1, .name = "DRATE1" },
1229 { .addr = CC1120_DRATE0, .name = "DRATE0" },
1230 { .addr = CC1120_AGC_REF, .name = "AGC_REF" },
1231 { .addr = CC1120_AGC_CS_THR, .name = "AGC_CS_THR" },
1232 { .addr = CC1120_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
1233 { .addr = CC1120_AGC_CFG3, .name = "AGC_CFG3" },
1234 { .addr = CC1120_AGC_CFG2, .name = "AGC_CFG2" },
1235 { .addr = CC1120_AGC_CFG1, .name = "AGC_CFG1" },
1236 { .addr = CC1120_AGC_CFG0, .name = "AGC_CFG0" },
1237 { .addr = CC1120_FIFO_CFG, .name = "FIFO_CFG" },
1238 { .addr = CC1120_DEV_ADDR, .name = "DEV_ADDR" },
1239 { .addr = CC1120_SETTLING_CFG, .name = "SETTLING_CFG" },
1240 { .addr = CC1120_FS_CFG, .name = "FS_CFG" },
1241 { .addr = CC1120_WOR_CFG1, .name = "WOR_CFG1" },
1242 { .addr = CC1120_WOR_CFG0, .name = "WOR_CFG0" },
1243 { .addr = CC1120_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
1244 { .addr = CC1120_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
1245 { .addr = CC1120_PKT_CFG2, .name = "PKT_CFG2" },
1246 { .addr = CC1120_PKT_CFG1, .name = "PKT_CFG1" },
1247 { .addr = CC1120_PKT_CFG0, .name = "PKT_CFG0" },
1248 { .addr = CC1120_RFEND_CFG1, .name = "RFEND_CFG1" },
1249 { .addr = CC1120_RFEND_CFG0, .name = "RFEND_CFG0" },
1250 { .addr = CC1120_PA_CFG2, .name = "PA_CFG2" },
1251 { .addr = CC1120_PA_CFG1, .name = "PA_CFG1" },
1252 { .addr = CC1120_PA_CFG0, .name = "PA_CFG0" },
1253 { .addr = CC1120_PKT_LEN, .name = "PKT_LEN" },
1254 { .addr = CC1120_IF_MIX_CFG, .name = "IF_MIX_CFG" },
1255 { .addr = CC1120_FREQOFF_CFG, .name = "FREQOFF_CFG" },
1256 { .addr = CC1120_TOC_CFG, .name = "TOC_CFG" },
1257 { .addr = CC1120_MARC_SPARE, .name = "MARC_SPARE" },
1258 { .addr = CC1120_ECG_CFG, .name = "ECG_CFG" },
1259 { .addr = CC1120_SOFT_TX_DATA_CFG, .name = "SOFT_TX_DATA_CFG" },
1260 { .addr = CC1120_EXT_CTRL, .name = "EXT_CTRL" },
1261 { .addr = CC1120_RCCAL_FINE, .name = "RCCAL_FINE" },
1262 { .addr = CC1120_RCCAL_COARSE, .name = "RCCAL_COARSE" },
1263 { .addr = CC1120_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
1264 { .addr = CC1120_FREQOFF1, .name = "FREQOFF1" },
1265 { .addr = CC1120_FREQOFF0, .name = "FREQOFF0" },
1266 { .addr = CC1120_FREQ2, .name = "FREQ2" },
1267 { .addr = CC1120_FREQ1, .name = "FREQ1" },
1268 { .addr = CC1120_FREQ0, .name = "FREQ0" },
1269 { .addr = CC1120_IF_ADC2, .name = "IF_ADC2" },
1270 { .addr = CC1120_IF_ADC1, .name = "IF_ADC1" },
1271 { .addr = CC1120_IF_ADC0, .name = "IF_ADC0" },
1272 { .addr = CC1120_FS_DIG1, .name = "FS_DIG1" },
1273 { .addr = CC1120_FS_DIG0, .name = "FS_DIG0" },
1274 { .addr = CC1120_FS_CAL3, .name = "FS_CAL3" },
1275 { .addr = CC1120_FS_CAL2, .name = "FS_CAL2" },
1276 { .addr = CC1120_FS_CAL1, .name = "FS_CAL1" },
1277 { .addr = CC1120_FS_CAL0, .name = "FS_CAL0" },
1278 { .addr = CC1120_FS_CHP, .name = "FS_CHP" },
1279 { .addr = CC1120_FS_DIVTWO, .name = "FS_DIVTWO" },
1280 { .addr = CC1120_FS_DSM1, .name = "FS_DSM1" },
1281 { .addr = CC1120_FS_DSM0, .name = "FS_DSM0" },
1282 { .addr = CC1120_FS_DVC1, .name = "FS_DVC1" },
1283 { .addr = CC1120_FS_DVC0, .name = "FS_DVC0" },
1284 { .addr = CC1120_FS_LBI, .name = "FS_LBI" },
1285 { .addr = CC1120_FS_PFD, .name = "FS_PFD" },
1286 { .addr = CC1120_FS_PRE, .name = "FS_PRE" },
1287 { .addr = CC1120_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
1288 { .addr = CC1120_FS_SPARE, .name = "FS_SPARE" },
1289 { .addr = CC1120_FS_VCO4, .name = "FS_VCO4" },
1290 { .addr = CC1120_FS_VCO3, .name = "FS_VCO3" },
1291 { .addr = CC1120_FS_VCO2, .name = "FS_VCO2" },
1292 { .addr = CC1120_FS_VCO1, .name = "FS_VCO1" },
1293 { .addr = CC1120_FS_VCO0, .name = "FS_VCO0" },
1294 { .addr = CC1120_GBIAS6, .name = "GBIAS6" },
1295 { .addr = CC1120_GBIAS5, .name = "GBIAS5" },
1296 { .addr = CC1120_GBIAS4, .name = "GBIAS4" },
1297 { .addr = CC1120_GBIAS3, .name = "GBIAS3" },
1298 { .addr = CC1120_GBIAS2, .name = "GBIAS2" },
1299 { .addr = CC1120_GBIAS1, .name = "GBIAS1" },
1300 { .addr = CC1120_GBIAS0, .name = "GBIAS0" },
1301 { .addr = CC1120_IFAMP, .name = "IFAMP" },
1302 { .addr = CC1120_LNA, .name = "LNA" },
1303 { .addr = CC1120_RXMIX, .name = "RXMIX" },
1304 { .addr = CC1120_XOSC5, .name = "XOSC5" },
1305 { .addr = CC1120_XOSC4, .name = "XOSC4" },
1306 { .addr = CC1120_XOSC3, .name = "XOSC3" },
1307 { .addr = CC1120_XOSC2, .name = "XOSC2" },
1308 { .addr = CC1120_XOSC1, .name = "XOSC1" },
1309 { .addr = CC1120_XOSC0, .name = "XOSC0" },
1310 { .addr = CC1120_ANALOG_SPARE, .name = "ANALOG_SPARE" },
1311 { .addr = CC1120_PA_CFG3, .name = "PA_CFG3" },
1312 { .addr = CC1120_WOR_TIME1, .name = "WOR_TIME1" },
1313 { .addr = CC1120_WOR_TIME0, .name = "WOR_TIME0" },
1314 { .addr = CC1120_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
1315 { .addr = CC1120_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
1316 { .addr = CC1120_BIST, .name = "BIST" },
1317 { .addr = CC1120_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
1318 { .addr = CC1120_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
1319 { .addr = CC1120_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
1320 { .addr = CC1120_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
1321 { .addr = CC1120_IQIE_I1, .name = "IQIE_I1" },
1322 { .addr = CC1120_IQIE_I0, .name = "IQIE_I0" },
1323 { .addr = CC1120_IQIE_Q1, .name = "IQIE_Q1" },
1324 { .addr = CC1120_IQIE_Q0, .name = "IQIE_Q0" },
1325 { .addr = CC1120_RSSI1, .name = "RSSI1" },
1326 { .addr = CC1120_RSSI0, .name = "RSSI0" },
1327 { .addr = CC1120_MARCSTATE, .name = "MARCSTATE" },
1328 { .addr = CC1120_LQI_VAL, .name = "LQI_VAL" },
1329 { .addr = CC1120_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
1330 { .addr = CC1120_DEM_STATUS, .name = "DEM_STATUS" },
1331 { .addr = CC1120_FREQOFF_EST1, .name = "FREQOFF_EST1" },
1332 { .addr = CC1120_FREQOFF_EST0, .name = "FREQOFF_EST0" },
1333 { .addr = CC1120_AGC_GAIN3, .name = "AGC_GAIN3" },
1334 { .addr = CC1120_AGC_GAIN2, .name = "AGC_GAIN2" },
1335 { .addr = CC1120_AGC_GAIN1, .name = "AGC_GAIN1" },
1336 { .addr = CC1120_AGC_GAIN0, .name = "AGC_GAIN0" },
1337 { .addr = CC1120_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
1338 { .addr = CC1120_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
1339 { .addr = CC1120_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
1340 { .addr = CC1120_RNDGEN, .name = "RNDGEN" },
1341 { .addr = CC1120_MAGN2, .name = "MAGN2" },
1342 { .addr = CC1120_MAGN1, .name = "MAGN1" },
1343 { .addr = CC1120_MAGN0, .name = "MAGN0" },
1344 { .addr = CC1120_ANG1, .name = "ANG1" },
1345 { .addr = CC1120_ANG0, .name = "ANG0" },
1346 { .addr = CC1120_CHFILT_I2, .name = "CHFILT_I2" },
1347 { .addr = CC1120_CHFILT_I1, .name = "CHFILT_I1" },
1348 { .addr = CC1120_CHFILT_I0, .name = "CHFILT_I0" },
1349 { .addr = CC1120_CHFILT_Q2, .name = "CHFILT_Q2" },
1350 { .addr = CC1120_CHFILT_Q1, .name = "CHFILT_Q1" },
1351 { .addr = CC1120_CHFILT_Q0, .name = "CHFILT_Q0" },
1352 { .addr = CC1120_GPIO_STATUS, .name = "GPIO_STATUS" },
1353 { .addr = CC1120_FSCAL_CTRL, .name = "FSCAL_CTRL" },
1354 { .addr = CC1120_PHASE_ADJUST, .name = "PHASE_ADJUST" },
1355 { .addr = CC1120_PARTNUMBER, .name = "PARTNUMBER" },
1356 { .addr = CC1120_PARTVERSION, .name = "PARTVERSION" },
1357 { .addr = CC1120_SERIAL_STATUS, .name = "SERIAL_STATUS" },
1358 { .addr = CC1120_RX_STATUS, .name = "RX_STATUS" },
1359 { .addr = CC1120_TX_STATUS, .name = "TX_STATUS" },
1360 { .addr = CC1120_MARC_STATUS1, .name = "MARC_STATUS1" },
1361 { .addr = CC1120_MARC_STATUS0, .name = "MARC_STATUS0" },
1362 { .addr = CC1120_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
1363 { .addr = CC1120_FSRF_TEST, .name = "FSRF_TEST" },
1364 { .addr = CC1120_PRE_TEST, .name = "PRE_TEST" },
1365 { .addr = CC1120_PRE_OVR, .name = "PRE_OVR" },
1366 { .addr = CC1120_ADC_TEST, .name = "ADC_TEST" },
1367 { .addr = CC1120_DVC_TEST, .name = "DVC_TEST" },
1368 { .addr = CC1120_ATEST, .name = "ATEST" },
1369 { .addr = CC1120_ATEST_LVDS, .name = "ATEST_LVDS" },
1370 { .addr = CC1120_ATEST_MODE, .name = "ATEST_MODE" },
1371 { .addr = CC1120_XOSC_TEST1, .name = "XOSC_TEST1" },
1372 { .addr = CC1120_XOSC_TEST0, .name = "XOSC_TEST0" },
1373 { .addr = CC1120_RXFIRST, .name = "RXFIRST" },
1374 { .addr = CC1120_TXFIRST, .name = "TXFIRST" },
1375 { .addr = CC1120_RXLAST, .name = "RXLAST" },
1376 { .addr = CC1120_TXLAST, .name = "TXLAST" },
1377 { .addr = CC1120_NUM_TXBYTES, .name = "NUM_TXBYTES" },
1378 { .addr = CC1120_NUM_RXBYTES, .name = "NUM_RXBYTES" },
1379 { .addr = CC1120_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
1380 { .addr = CC1120_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
1383 #define AO_NUM_CC1120_REG (sizeof ao_cc1120_reg / sizeof ao_cc1120_reg[0])
1385 static void ao_radio_show(void) {
1386 uint8_t status = ao_radio_status();
1390 status = ao_radio_status();
1391 printf ("Status: %02x\n", status);
1392 printf ("CHIP_RDY: %d\n", (status >> CC1120_STATUS_CHIP_RDY) & 1);
1393 printf ("STATE: %s\n", cc1120_state_name[(status >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK]);
1394 printf ("MARC: %02x\n", ao_radio_get_marc_status());
1396 for (i = 0; i < AO_NUM_CC1120_REG; i++)
1397 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name);
1399 printf("RX fast start: %u\n", rx_fast_start);
1400 printf("RX slow start: %u\n", rx_slow_start);
1401 printf("RX missed: %u\n", rx_missed);
1405 static void ao_radio_beep(void) {
1409 static void ao_radio_packet(void) {
1410 static const uint8_t packet[] = {
1412 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1413 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1414 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1415 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1421 ao_radio_send(packet, sizeof (packet));
1425 ao_radio_test_recv(void)
1430 if (ao_radio_recv(bytes, 34, 0)) {
1431 if (bytes[33] & 0x80)
1435 printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32]));
1436 for (b = 0; b < 32; b++)
1437 printf (" %02x", bytes[b]);
1443 #include <ao_aprs.h>
1448 ao_packet_slave_stop();
1454 static const struct ao_cmds ao_radio_cmds[] = {
1455 { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
1458 { ao_radio_aprs, "G\0Send APRS packet" },
1460 { ao_radio_show, "R\0Show CC1120 status" },
1461 { ao_radio_beep, "b\0Emit an RDF beacon" },
1462 { ao_radio_packet, "p\0Send a test packet" },
1463 { ao_radio_test_recv, "q\0Recv a test packet" },
1471 ao_radio_configured = 0;
1472 ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN));
1475 AO_CC1120_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN));
1476 for (i = 0; i < 10000; i++) {
1477 if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0)
1480 AO_CC1120_SPI_CS_PORT->bsrr = (1 << AO_CC1120_SPI_CS_PIN);
1482 ao_panic(AO_PANIC_SELF_TEST_CC1120);
1485 /* Enable the EXTI interrupt for the appropriate pin */
1486 ao_enable_port(AO_CC1120_INT_PORT);
1487 ao_exti_setup(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1488 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
1491 /* Enable the hacked up GPIO3 pin */
1492 ao_enable_port(AO_CC1120_MCU_WAKEUP_PORT);
1493 ao_exti_setup(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN,
1494 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED,
1495 ao_radio_mcu_wakeup_isr);
1497 ao_cmd_register(&ao_radio_cmds[0]);