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; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20 #include <ao_cc1120.h>
23 #include <ao_packet.h>
25 #define AO_RADIO_MAX_RECV sizeof(struct ao_packet)
26 #define AO_RADIO_MAX_SEND sizeof(struct ao_packet)
28 static uint8_t ao_radio_mutex;
30 static uint8_t ao_radio_wake; /* radio ready. Also used as sleep address */
31 static uint8_t ao_radio_abort; /* radio operation should abort */
32 static uint8_t ao_radio_mcu_wake; /* MARC status change */
33 static uint8_t ao_radio_marc_status; /* Last read MARC status value */
34 static uint8_t ao_radio_tx_finished; /* MARC status indicates TX finished */
36 int8_t ao_radio_rssi; /* Last received RSSI value */
38 #define CC1120_DEBUG AO_FEC_DEBUG
39 #define CC1120_TRACE 0
41 extern const uint32_t ao_radio_cal;
45 #define AO_CC1120_SPI_SPEED ao_spi_speed(AO_CC1120_SPI_BUS, 6100000) /* 6.1MHz max with 32MHz osc */
47 #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_CC1120_SPI_SPEED, task_id)
48 #define ao_radio_select() ao_spi_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS,AO_CC1120_SPI_SPEED)
49 #define ao_radio_deselect() ao_spi_put_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS)
50 #define ao_radio_spi_start_bytes() ao_spi_start_bytes(AO_CC1120_SPI_BUS)
51 #define ao_radio_spi_stop_bytes() ao_spi_stop_bytes(AO_CC1120_SPI_BUS)
52 #define ao_radio_spi_send_byte(b) ao_spi_send_byte(b, AO_CC1120_SPI_BUS)
53 #define ao_radio_spi_recv_byte() ao_spi_recv_byte(AO_CC1120_SPI_BUS)
54 #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1120_SPI_BUS)
55 #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1120_SPI_BUS)
56 #define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1120_SPI_BUS)
57 #define ao_radio_duplex(o,i,l) ao_spi_duplex((o), (i), (l), AO_CC1120_SPI_BUS)
60 ao_radio_reg_read(uint16_t addr)
66 printf("\t\tao_radio_reg_read (%04x): ", addr); flush();
68 if (CC1120_IS_EXTENDED(addr)) {
69 data[0] = ((1 << CC1120_READ) |
72 data[1] = (uint8_t) addr;
75 data[0] = ((1 << CC1120_READ) |
81 ao_radio_spi_send(data, d);
82 ao_radio_spi_recv(data, 1);
85 printf (" %02x\n", data[0]);
91 ao_radio_reg_write(uint16_t addr, uint8_t value)
97 printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value);
99 if (CC1120_IS_EXTENDED(addr)) {
100 data[0] = ((0 << CC1120_READ) |
101 (0 << CC1120_BURST) |
103 data[1] = (uint8_t) addr;
106 data[0] = ((0 << CC1120_READ) |
107 (0 << CC1120_BURST) |
113 ao_radio_spi_send(data, d+1);
118 _ao_radio_burst_read_start (uint16_t addr)
120 ao_radio_spi_start_bytes();
122 if (CC1120_IS_EXTENDED(addr)) {
123 ao_radio_spi_send_byte((1 << CC1120_READ) |
124 (1 << CC1120_BURST) |
127 addr |= ((1 << CC1120_READ) |
128 (1 << CC1120_BURST));
130 ao_radio_spi_send_byte((uint8_t) addr);
134 ao_radio_burst_read_stop (void)
136 ao_radio_spi_stop_bytes();
142 ao_radio_strobe(uint8_t addr)
147 printf("\t\tao_radio_strobe (%02x): ", addr); flush();
150 ao_radio_duplex(&addr, &in, 1);
153 printf("%02x\n", in); flush();
160 ao_radio_fifo_read(uint8_t *data, uint8_t len)
162 uint8_t addr = ((1 << CC1120_READ) |
163 (1 << CC1120_BURST) |
168 ao_radio_duplex(&addr, &status, 1);
169 ao_radio_spi_recv(data, len);
176 ao_radio_fifo_write_start(void)
178 uint8_t addr = ((0 << CC1120_READ) |
179 (1 << CC1120_BURST) |
184 ao_radio_duplex(&addr, &status, 1);
188 static inline void ao_radio_fifo_write_stop(void) {
193 ao_radio_fifo_write(uint8_t *data, uint8_t len)
195 uint8_t status = ao_radio_fifo_write_start();
196 ao_radio_spi_send(data, len);
197 ao_radio_fifo_write_stop();
202 ao_radio_fifo_write_fixed(uint8_t data, uint8_t len)
204 uint8_t status = ao_radio_fifo_write_start();
205 ao_radio_spi_send_fixed(data, len);
206 ao_radio_fifo_write_stop();
211 ao_radio_int_pin(void)
213 return ao_gpio_get(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
218 ao_radio_status(void)
220 return ao_radio_strobe (CC1120_SNOP);
225 ao_radio_recv_abort(void)
228 ao_wakeup(&ao_radio_wake);
231 #define ao_radio_rdf_value 0x55
234 ao_radio_get_marc_status(void)
236 return ao_radio_reg_read(CC1120_MARC_STATUS1);
240 ao_radio_mcu_wakeup_isr(void)
242 ao_radio_mcu_wake = 1;
243 ao_wakeup(&ao_radio_wake);
248 ao_radio_check_marc_status(void)
250 ao_radio_mcu_wake = 0;
251 ao_radio_marc_status = ao_radio_get_marc_status();
253 /* Anyt other than 'tx/rx finished' means an error occurred */
254 if (ao_radio_marc_status & ~(CC1120_MARC_STATUS1_TX_FINISHED|CC1120_MARC_STATUS1_RX_FINISHED))
256 if (ao_radio_marc_status & (CC1120_MARC_STATUS1_TX_FINISHED))
257 ao_radio_tx_finished = 1;
263 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
265 ao_wakeup(&ao_radio_wake);
269 ao_radio_enable_isr(void)
271 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
272 ao_exti_enable(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN);
276 ao_radio_start_tx(void)
278 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr);
279 ao_radio_tx_finished = 0;
280 ao_radio_strobe(CC1120_STX);
287 uint8_t state = (ao_radio_strobe(CC1120_SIDLE) >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK;
288 if (state == CC1120_STATUS_STATE_IDLE)
290 if (state == CC1120_STATUS_STATE_TX_FIFO_ERROR)
291 ao_radio_strobe(CC1120_SFTX);
292 if (state == CC1120_STATUS_STATE_RX_FIFO_ERROR)
293 ao_radio_strobe(CC1120_SFRX);
295 /* Flush any pending TX bytes */
296 ao_radio_strobe(CC1120_SFTX);
302 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
304 * Deviation for 38400 baud should be 20.5kHz:
306 * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz
308 * Deviation for 9600 baud should be 5.125kHz:
310 * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 3) = 5127Hz
312 * Deviation for 2400 baud should be 1.28125kHz, but cc1111 and
313 * cc115l can't do that, so we'll use 1.5kHz instead:
315 * 32e6Hz / (2 ** 24) * (256 + 137) * (2 ** 1) = 1499Hz
318 #define PACKET_DEV_M_384 80
319 #define PACKET_DEV_E_384 5
321 #define PACKET_DEV_M_96 80
322 #define PACKET_DEV_E_96 3
324 #define PACKET_DEV_M_24 137
325 #define PACKET_DEV_E_24 1
328 * For our packet data
330 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
331 * Rdata = -------------------------------------- * fosc
334 * Given the bit period of the baseband, T, the bandwidth of the
335 * baseband signal is B = 1/(2T). The overall bandwidth of the
336 * modulated signal is then Channel bandwidth = 2Δf + 2B.
338 * 38400 -- 2 * 20500 + 38400 = 79.4 kHz
339 * 9600 -- 2 * 5.125 + 9600 = 19.9 kHz
340 * 2400 -- 2 * 1.5 + 2400 = 5.4 khz
342 * Symbol rate 38400 Baud:
344 * DATARATE_M = 239914
346 * CHANBW = 79.4 (round to 100)
348 * Symbol rate 9600 Baud:
350 * DATARATE_M = 239914
352 * CHANBW = 19.9 (round to 20)
354 * Symbol rate 2400 Baud:
356 * DATARATE_M = 239914
358 * CHANBW = 5.0 (round to 8.0)
361 #define PACKET_DRATE_M 239914
363 #define PACKET_DRATE_E_384 9
366 #define PACKET_CHAN_BW_384 ((0 << CC1120_CHAN_BW_CHFILT_BYPASS) | \
367 (CC1120_CHAN_BW_ADC_CIC_DECFACT_20 << CC1120_CHAN_BW_ADC_CIC_DECFACT) | \
368 (2 << CC1120_CHAN_BW_BB_CIC_DECFACT))
370 #define PACKET_DRATE_E_96 7
372 #define PACKET_CHAN_BW_96 ((0 << CC1120_CHAN_BW_CHFILT_BYPASS) | \
373 (CC1120_CHAN_BW_ADC_CIC_DECFACT_20 << CC1120_CHAN_BW_ADC_CIC_DECFACT) | \
374 (10 << CC1120_CHAN_BW_BB_CIC_DECFACT))
376 #define PACKET_DRATE_E_24 5
378 #define PACKET_CHAN_BW_24 ((0 << CC1120_CHAN_BW_CHFILT_BYPASS) | \
379 (CC1120_CHAN_BW_ADC_CIC_DECFACT_20 << CC1120_CHAN_BW_ADC_CIC_DECFACT) | \
380 (25 << CC1120_CHAN_BW_BB_CIC_DECFACT))
382 static const uint16_t packet_setup[] = {
383 CC1120_DRATE1, ((PACKET_DRATE_M >> 8) & 0xff),
384 CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff),
385 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
386 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
387 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
388 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
389 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
390 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
391 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
392 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
393 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
394 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
395 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
396 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
397 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
398 AO_CC1120_MARC_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP,
401 static const uint16_t packet_setup_384[] = {
402 CC1120_DEVIATION_M, PACKET_DEV_M_384,
403 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
404 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
405 (PACKET_DEV_E_384 << CC1120_MODCFG_DEV_E_DEV_E)),
406 CC1120_DRATE2, ((PACKET_DRATE_E_384 << CC1120_DRATE2_DATARATE_E) |
407 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
408 CC1120_CHAN_BW, PACKET_CHAN_BW_384,
409 CC1120_PA_CFG0, 0x7b,
412 static const uint16_t packet_setup_96[] = {
413 CC1120_DEVIATION_M, PACKET_DEV_M_96,
414 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
415 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
416 (PACKET_DEV_E_96 << CC1120_MODCFG_DEV_E_DEV_E)),
417 CC1120_DRATE2, ((PACKET_DRATE_E_96 << CC1120_DRATE2_DATARATE_E) |
418 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
419 CC1120_CHAN_BW, PACKET_CHAN_BW_96,
420 CC1120_PA_CFG0, 0x7d,
423 static const uint16_t packet_setup_24[] = {
424 CC1120_DEVIATION_M, PACKET_DEV_M_24,
425 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
426 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
427 (PACKET_DEV_E_24 << CC1120_MODCFG_DEV_E_DEV_E)),
428 CC1120_DRATE2, ((PACKET_DRATE_E_24 << CC1120_DRATE2_DATARATE_E) |
429 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
430 CC1120_CHAN_BW, PACKET_CHAN_BW_24,
431 CC1120_PA_CFG0, 0x7e,
434 #define AO_CC1120_TX_BUFFER 64
436 static const uint16_t packet_tx_setup[] = {
437 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
438 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
439 CC1120_FIFO_CFG, ((0 << CC1120_FIFO_CFG_CRC_AUTOFLUSH) |
440 (AO_CC1120_TX_BUFFER << CC1120_FIFO_CFG_FIFO_THR)),
443 static const uint16_t packet_rx_setup[] = {
444 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
445 (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT)),
446 AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT,
450 * RDF deviation is 5kHz
452 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
454 * 32e6Hz / (2 ** 24) * (256 + 71) * (2 ** 3) = 4989
459 #define RDF_PACKET_LEN 50
462 * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
464 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
465 * Rdata = -------------------------------------- * fosc
471 * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
473 #define RDF_DRATE_E 5
474 #define RDF_DRATE_M 25166
475 #define RDF_PACKET_LEN 50
477 static const uint16_t rdf_setup[] = {
478 CC1120_DEVIATION_M, RDF_DEV_M,
479 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
480 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
481 (RDF_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
482 CC1120_DRATE2, ((RDF_DRATE_E << CC1120_DRATE2_DATARATE_E) |
483 (((RDF_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
484 CC1120_DRATE1, ((RDF_DRATE_M >> 8) & 0xff),
485 CC1120_DRATE0, ((RDF_DRATE_M >> 0) & 0xff),
486 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
487 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
488 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
489 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
490 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
491 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
492 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
493 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
494 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
495 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
496 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
497 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
498 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
499 CC1120_PA_CFG0, 0x7e,
503 * APRS deviation is 3kHz
505 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
507 * 32e6Hz / (2 ** 24) * (256 + 137) * (2 ** 2) = 2998Hz
511 #define APRS_DEV_M 137
514 * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate)
516 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
517 * Rdata = -------------------------------------- * fosc
520 * DATARATE_M = 239914
523 * Rdata = 9599.998593330383301
526 #define APRS_DRATE_E 7
527 #define APRS_DRATE_M 239914
529 static const uint16_t aprs_setup[] = {
530 CC1120_DEVIATION_M, APRS_DEV_M,
531 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
532 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
533 (APRS_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
534 CC1120_DRATE2, ((APRS_DRATE_E << CC1120_DRATE2_DATARATE_E) |
535 (((APRS_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
536 CC1120_DRATE1, ((APRS_DRATE_M >> 8) & 0xff),
537 CC1120_DRATE0, ((APRS_DRATE_M >> 0) & 0xff),
538 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
539 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
540 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
541 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
542 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
543 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
544 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
545 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
546 CC1120_PA_CFG0, 0x7d,
547 CC1120_FIFO_CFG, ((0 << CC1120_FIFO_CFG_CRC_AUTOFLUSH) |
548 (AO_CC1120_TX_BUFFER << CC1120_FIFO_CFG_FIFO_THR)),
552 * For Test mode, we want an unmodulated carrier. To do that, we
553 * set the deviation to zero and enable a preamble so that the radio
554 * turns on before we send any data
557 static const uint16_t test_setup[] = {
558 CC1120_DEVIATION_M, 0,
559 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
560 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
561 (0 << CC1120_MODCFG_DEV_E_DEV_E)),
562 CC1120_DRATE2, ((APRS_DRATE_E << CC1120_DRATE2_DATARATE_E) |
563 (((APRS_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
564 CC1120_DRATE1, ((APRS_DRATE_M >> 8) & 0xff),
565 CC1120_DRATE0, ((APRS_DRATE_M >> 0) & 0xff),
566 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
567 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
568 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
569 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
570 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
571 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
572 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
573 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
576 #define AO_PKT_CFG0_INFINITE ((0 << CC1120_PKT_CFG0_RESERVED7) | \
577 (CC1120_PKT_CFG0_LENGTH_CONFIG_INFINITE << CC1120_PKT_CFG0_LENGTH_CONFIG) | \
578 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | \
579 (0 << CC1120_PKT_CFG0_UART_MODE_EN) | \
580 (0 << CC1120_PKT_CFG0_UART_SWAP_EN))
582 #define AO_PKT_CFG0_FIXED ((0 << CC1120_PKT_CFG0_RESERVED7) | \
583 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) | \
584 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | \
585 (0 << CC1120_PKT_CFG0_UART_MODE_EN) | \
586 (0 << CC1120_PKT_CFG0_UART_SWAP_EN))
588 static uint16_t ao_radio_mode;
590 #define AO_RADIO_MODE_BITS_PACKET 1
591 #define AO_RADIO_MODE_BITS_PACKET_TX 2
592 #define AO_RADIO_MODE_BITS_TX_BUF 4
593 #define AO_RADIO_MODE_BITS_TX_FINISH 8
594 #define AO_RADIO_MODE_BITS_PACKET_RX 16
595 #define AO_RADIO_MODE_BITS_RDF 32
596 #define AO_RADIO_MODE_BITS_APRS 64
597 #define AO_RADIO_MODE_BITS_TEST 128
598 #define AO_RADIO_MODE_BITS_INFINITE 256
599 #define AO_RADIO_MODE_BITS_FIXED 512
601 #define AO_RADIO_MODE_NONE 0
602 #define AO_RADIO_MODE_PACKET_TX_BUF (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_BUF)
603 #define AO_RADIO_MODE_PACKET_TX_FINISH (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_FINISH)
604 #define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_RX)
605 #define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_TX_FINISH)
606 #define AO_RADIO_MODE_APRS_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
607 #define AO_RADIO_MODE_APRS_LAST_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_BUF)
608 #define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
609 #define AO_RADIO_MODE_TEST (AO_RADIO_MODE_BITS_TEST | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
612 _ao_radio_set_regs(const uint16_t *regs, int nreg)
616 for (i = 0; i < nreg; i++) {
617 ao_radio_reg_write(regs[0], (uint8_t) regs[1]);
622 #define ao_radio_set_regs(setup) _ao_radio_set_regs(setup, (sizeof (setup) / sizeof(setup[0])) >> 1)
625 ao_radio_set_mode(uint16_t new_mode)
629 if (new_mode == ao_radio_mode)
632 changes = (uint16_t) (new_mode & (~ao_radio_mode));
634 if (changes & AO_RADIO_MODE_BITS_PACKET) {
635 ao_radio_set_regs(packet_setup);
637 switch (ao_config.radio_rate) {
639 case AO_RADIO_RATE_38400:
640 ao_radio_set_regs(packet_setup_384);
642 case AO_RADIO_RATE_9600:
643 ao_radio_set_regs(packet_setup_96);
645 case AO_RADIO_RATE_2400:
646 ao_radio_set_regs(packet_setup_24);
651 if (changes & AO_RADIO_MODE_BITS_PACKET_TX)
652 ao_radio_set_regs(packet_tx_setup);
654 if (changes & AO_RADIO_MODE_BITS_TX_BUF)
655 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_TXFIFO_THR);
657 if (changes & AO_RADIO_MODE_BITS_TX_FINISH)
658 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG);
660 if (changes & AO_RADIO_MODE_BITS_PACKET_RX)
661 ao_radio_set_regs(packet_rx_setup);
663 if (changes & AO_RADIO_MODE_BITS_RDF)
664 ao_radio_set_regs(rdf_setup);
666 if (changes & AO_RADIO_MODE_BITS_APRS)
667 ao_radio_set_regs(aprs_setup);
669 if (changes & AO_RADIO_MODE_BITS_TEST)
670 ao_radio_set_regs(test_setup);
672 if (changes & AO_RADIO_MODE_BITS_INFINITE)
673 ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_INFINITE);
675 if (changes & AO_RADIO_MODE_BITS_FIXED)
676 ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_FIXED);
678 ao_radio_mode = new_mode;
681 static const uint16_t radio_setup[] = {
682 #include "ao_cc1120_CC1120.h"
685 static uint8_t ao_radio_configured = 0;
690 ao_radio_strobe(CC1120_SRES);
692 ao_radio_set_regs(radio_setup);
698 ao_radio_configured = 1;
702 ao_radio_set_len(uint8_t len)
704 static uint8_t last_len;
706 if (len != last_len) {
707 ao_radio_reg_write(CC1120_PKT_LEN, len);
713 ao_radio_get(uint8_t len)
715 static uint32_t last_radio_setting;
716 static uint8_t last_radio_rate;
718 ao_mutex_get(&ao_radio_mutex);
720 if (!ao_radio_configured)
722 if (ao_config.radio_setting != last_radio_setting) {
723 ao_radio_reg_write(CC1120_FREQ2, (uint8_t) (ao_config.radio_setting >> 16));
724 ao_radio_reg_write(CC1120_FREQ1, (uint8_t) (ao_config.radio_setting >> 8));
725 ao_radio_reg_write(CC1120_FREQ0, (uint8_t) (ao_config.radio_setting));
726 last_radio_setting = ao_config.radio_setting;
728 if (ao_config.radio_rate != last_radio_rate) {
729 ao_radio_mode &= (uint16_t) ~AO_RADIO_MODE_BITS_PACKET;
730 last_radio_rate = ao_config.radio_rate;
732 ao_radio_set_len(len);
735 #define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
738 ao_rdf_start(uint8_t len)
743 ao_radio_set_mode(AO_RADIO_MODE_RDF);
753 ao_arch_block_interrupts();
754 while (!ao_radio_wake && !ao_radio_abort && !ao_radio_mcu_wake) {
755 ao_radio_enable_isr();
756 ao_sleep(&ao_radio_wake);
758 ao_arch_release_interrupts();
759 if (ao_radio_mcu_wake)
760 ao_radio_check_marc_status();
769 ao_rdf_start(AO_RADIO_RDF_LEN);
771 ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN);
777 ao_radio_continuity(uint8_t c)
781 ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN);
783 (void) ao_radio_fifo_write_start();
784 for (i = 0; i < 3; i++) {
785 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
787 ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN);
789 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN);
791 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
792 ao_radio_fifo_write_stop();
797 ao_radio_rdf_abort(void)
800 ao_wakeup(&ao_radio_wake);
804 ao_radio_test_cmd(void)
807 static uint8_t radio_on;
809 if (ao_cmd_lex_c != '\n') {
810 mode = (uint8_t) ao_cmd_decimal();
813 if ((mode & 2) && !radio_on) {
815 ao_monitor_disable();
818 ao_packet_slave_stop();
821 ao_radio_set_mode(AO_RADIO_MODE_TEST);
822 ao_radio_strobe(CC1120_STX);
825 for (t = 0; t < 10; t++) {
826 printf ("status: %02x\n", ao_radio_status());
827 ao_delay(AO_MS_TO_TICKS(100));
834 printf ("Hit a character to stop..."); flush();
838 if ((mode & 1) && radio_on) {
849 ao_radio_wait_isr(AO_TICK_TYPE timeout)
851 ao_arch_block_interrupts();
852 while (!ao_radio_wake && !ao_radio_mcu_wake && !ao_radio_abort)
853 if (ao_sleep_for(&ao_radio_wake, timeout))
855 ao_arch_release_interrupts();
856 if (ao_radio_mcu_wake)
857 ao_radio_check_marc_status();
861 ao_radio_wait_fifo(void)
863 while (ao_radio_int_pin() != 0 && !ao_radio_abort) {
865 ao_radio_enable_isr();
866 ao_radio_wait_isr(0);
870 static uint8_t tx_data[(AO_RADIO_MAX_SEND + 4) * 2];
873 ao_radio_send(const void *d, uint8_t size)
875 uint8_t *e = tx_data;
880 encode_len = ao_fec_encode(d, size, tx_data);
882 ao_radio_get(encode_len);
886 /* Flush any pending TX bytes */
887 ao_radio_strobe(CC1120_SFTX);
890 this_len = encode_len;
893 ao_radio_wait_fifo();
898 if (this_len > AO_CC1120_TX_BUFFER) {
899 this_len = AO_CC1120_TX_BUFFER;
900 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_BUF);
902 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_FINISH);
905 ao_radio_fifo_write(e, this_len);
907 encode_len -= this_len;
914 while (started && !ao_radio_abort && !ao_radio_tx_finished) {
916 ao_radio_enable_isr();
917 ao_radio_wait_isr(0);
925 ao_radio_send_aprs(ao_radio_fill_func fill)
927 uint8_t buf[AO_CC1120_TX_BUFFER];
937 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr);
939 cnt = (*fill)(buf, sizeof(buf));
946 /* Wait for some space in the fifo */
948 ao_radio_wait_fifo();
954 ao_radio_set_len((uint8_t) (total & 0xff));
955 ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
957 ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
959 ao_radio_fifo_write(buf, (uint8_t) cnt);
966 /* Wait for the transmitter to go idle */
967 while (started && ao_radio_int_pin() != 0 && !ao_radio_abort) {
969 ao_radio_enable_isr();
970 ao_radio_wait_isr(0);
977 static uint8_t rx_data[(AO_RADIO_MAX_RECV + 4) * 2 * 8];
978 static uint16_t rx_data_count;
979 static uint16_t rx_data_consumed;
980 static uint16_t rx_data_cur;
981 static uint8_t rx_ignore;
982 static uint8_t rx_waiting;
983 static uint8_t rx_starting;
984 static uint8_t rx_task_id;
985 static uint32_t rx_fast_start;
986 static uint32_t rx_slow_start;
987 static uint32_t rx_missed;
990 static uint32_t rx_start_tick, rx_packet_tick, rx_done_tick, rx_last_done_tick;
992 uint32_t ao_rx_start_tick, ao_rx_packet_tick, ao_rx_done_tick, ao_rx_last_done_tick;
994 #include <ao_profile.h>
998 ao_radio_rx_isr(void)
1005 if (ao_radio_try_select(rx_task_id)) {
1008 _ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
1021 ao_wakeup(&ao_radio_wake);
1023 d = ao_radio_spi_recv_byte();
1024 if (rx_ignore == 0) {
1025 if (rx_data_cur < rx_data_count)
1026 rx_data[rx_data_cur++] = d;
1027 if (rx_data_cur >= rx_data_count) {
1028 ao_spi_clr_cs(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN));
1029 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
1031 if (rx_waiting && rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) {
1033 if (!rx_packet_tick)
1034 rx_packet_tick = ao_profile_tick();
1035 if (rx_data_cur < rx_data_count)
1039 ao_wakeup(&ao_radio_wake);
1047 ao_radio_rx_wait(void)
1049 ao_arch_block_interrupts();
1051 while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&
1055 if (ao_sleep_for(&ao_radio_wake, AO_MS_TO_TICKS(100)))
1059 ao_arch_release_interrupts();
1060 if (ao_radio_abort || ao_radio_mcu_wake)
1062 rx_data_consumed += AO_FEC_DECODE_BLOCK;
1064 return rx_data_cur - rx_data_consumed;
1066 return AO_FEC_DECODE_BLOCK;
1070 ao_radio_recv(void *d, uint8_t size, AO_TICK_TYPE timeout)
1073 uint8_t radio_rssi = 0;
1077 size -= 2; /* status bytes */
1078 if (size > AO_RADIO_MAX_RECV) {
1079 ao_delay(AO_SEC_TO_TICKS(1));
1083 rx_start_tick = ao_profile_tick();
1086 len = size + 2; /* CRC bytes */
1087 len += (uint8_t) (1 + ~(len & 1)); /* 1 or two pad bytes */
1088 len *= 2; /* 1/2 rate convolution */
1089 rx_data_count = len * 8; /* bytes to bits */
1091 rx_data_consumed = 0;
1094 /* Must be set before changing the frequency; any abort
1095 * after the frequency is set needs to terminate the read
1096 * so that the registers can be reprogrammed
1103 ao_radio_mcu_wake = 0;
1105 ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
1107 /* configure interrupt pin */
1108 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT);
1109 ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1110 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
1113 rx_task_id = ao_cur_task->task_id;
1115 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
1116 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
1118 ao_radio_strobe(CC1120_SRX);
1120 ao_arch_block_interrupts();
1121 while (rx_starting && !ao_radio_abort) {
1122 if (ao_sleep_for(&ao_radio_wake, timeout))
1125 uint8_t rx_task_id_save = rx_task_id;
1128 ao_arch_release_interrupts();
1130 if (ao_radio_abort) {
1131 if (rx_task_id_save == 0)
1132 ao_radio_burst_read_stop();
1137 if (rx_task_id_save) {
1140 _ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
1142 (void) ao_radio_spi_recv_byte();
1147 ret = ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait);
1149 ao_radio_burst_read_stop();
1151 if (ao_radio_mcu_wake)
1152 ao_radio_check_marc_status();
1157 /* Convert from 'real' rssi to cc1111-style values */
1159 rssi0 = ao_radio_reg_read(CC1120_RSSI0);
1161 int8_t rssi = (int8_t) ao_radio_reg_read(CC1120_RSSI1);
1162 ao_radio_rssi = rssi;
1164 /* Bound it to the representable range */
1167 radio_rssi = AO_RADIO_FROM_RSSI (rssi);
1174 /* Store the received RSSI value; the crc-OK byte is already done */
1176 ((uint8_t *) d)[size] = radio_rssi;
1179 rx_last_done_tick = rx_done_tick;
1180 rx_done_tick = ao_profile_tick();
1182 ao_rx_start_tick = rx_start_tick;
1183 ao_rx_packet_tick = rx_packet_tick;
1184 ao_rx_done_tick = rx_done_tick;
1185 ao_rx_last_done_tick = rx_last_done_tick;
1193 static char *cc1120_state_name[] = {
1194 [CC1120_STATUS_STATE_IDLE] = "IDLE",
1195 [CC1120_STATUS_STATE_RX] = "RX",
1196 [CC1120_STATUS_STATE_TX] = "TX",
1197 [CC1120_STATUS_STATE_FSTXON] = "FSTXON",
1198 [CC1120_STATUS_STATE_CALIBRATE] = "CALIBRATE",
1199 [CC1120_STATUS_STATE_SETTLING] = "SETTLING",
1200 [CC1120_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
1201 [CC1120_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
1204 struct ao_cc1120_reg {
1209 static const struct ao_cc1120_reg ao_cc1120_reg[] = {
1210 { .addr = CC1120_IOCFG3, .name = "IOCFG3" },
1211 { .addr = CC1120_IOCFG2, .name = "IOCFG2" },
1212 { .addr = CC1120_IOCFG1, .name = "IOCFG1" },
1213 { .addr = CC1120_IOCFG0, .name = "IOCFG0" },
1214 { .addr = CC1120_SYNC3, .name = "SYNC3" },
1215 { .addr = CC1120_SYNC2, .name = "SYNC2" },
1216 { .addr = CC1120_SYNC1, .name = "SYNC1" },
1217 { .addr = CC1120_SYNC0, .name = "SYNC0" },
1218 { .addr = CC1120_SYNC_CFG1, .name = "SYNC_CFG1" },
1219 { .addr = CC1120_SYNC_CFG0, .name = "SYNC_CFG0" },
1220 { .addr = CC1120_DEVIATION_M, .name = "DEVIATION_M" },
1221 { .addr = CC1120_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
1222 { .addr = CC1120_DCFILT_CFG, .name = "DCFILT_CFG" },
1223 { .addr = CC1120_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
1224 { .addr = CC1120_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
1225 { .addr = CC1120_FREQ_IF_CFG, .name = "FREQ_IF_CFG" },
1226 { .addr = CC1120_IQIC, .name = "IQIC" },
1227 { .addr = CC1120_CHAN_BW, .name = "CHAN_BW" },
1228 { .addr = CC1120_MDMCFG1, .name = "MDMCFG1" },
1229 { .addr = CC1120_MDMCFG0, .name = "MDMCFG0" },
1230 { .addr = CC1120_DRATE2, .name = "DRATE2" },
1231 { .addr = CC1120_DRATE1, .name = "DRATE1" },
1232 { .addr = CC1120_DRATE0, .name = "DRATE0" },
1233 { .addr = CC1120_AGC_REF, .name = "AGC_REF" },
1234 { .addr = CC1120_AGC_CS_THR, .name = "AGC_CS_THR" },
1235 { .addr = CC1120_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
1236 { .addr = CC1120_AGC_CFG3, .name = "AGC_CFG3" },
1237 { .addr = CC1120_AGC_CFG2, .name = "AGC_CFG2" },
1238 { .addr = CC1120_AGC_CFG1, .name = "AGC_CFG1" },
1239 { .addr = CC1120_AGC_CFG0, .name = "AGC_CFG0" },
1240 { .addr = CC1120_FIFO_CFG, .name = "FIFO_CFG" },
1241 { .addr = CC1120_DEV_ADDR, .name = "DEV_ADDR" },
1242 { .addr = CC1120_SETTLING_CFG, .name = "SETTLING_CFG" },
1243 { .addr = CC1120_FS_CFG, .name = "FS_CFG" },
1244 { .addr = CC1120_WOR_CFG1, .name = "WOR_CFG1" },
1245 { .addr = CC1120_WOR_CFG0, .name = "WOR_CFG0" },
1246 { .addr = CC1120_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
1247 { .addr = CC1120_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
1248 { .addr = CC1120_PKT_CFG2, .name = "PKT_CFG2" },
1249 { .addr = CC1120_PKT_CFG1, .name = "PKT_CFG1" },
1250 { .addr = CC1120_PKT_CFG0, .name = "PKT_CFG0" },
1251 { .addr = CC1120_RFEND_CFG1, .name = "RFEND_CFG1" },
1252 { .addr = CC1120_RFEND_CFG0, .name = "RFEND_CFG0" },
1253 { .addr = CC1120_PA_CFG2, .name = "PA_CFG2" },
1254 { .addr = CC1120_PA_CFG1, .name = "PA_CFG1" },
1255 { .addr = CC1120_PA_CFG0, .name = "PA_CFG0" },
1256 { .addr = CC1120_PKT_LEN, .name = "PKT_LEN" },
1257 { .addr = CC1120_IF_MIX_CFG, .name = "IF_MIX_CFG" },
1258 { .addr = CC1120_FREQOFF_CFG, .name = "FREQOFF_CFG" },
1259 { .addr = CC1120_TOC_CFG, .name = "TOC_CFG" },
1260 { .addr = CC1120_MARC_SPARE, .name = "MARC_SPARE" },
1261 { .addr = CC1120_ECG_CFG, .name = "ECG_CFG" },
1262 { .addr = CC1120_SOFT_TX_DATA_CFG, .name = "SOFT_TX_DATA_CFG" },
1263 { .addr = CC1120_EXT_CTRL, .name = "EXT_CTRL" },
1264 { .addr = CC1120_RCCAL_FINE, .name = "RCCAL_FINE" },
1265 { .addr = CC1120_RCCAL_COARSE, .name = "RCCAL_COARSE" },
1266 { .addr = CC1120_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
1267 { .addr = CC1120_FREQOFF1, .name = "FREQOFF1" },
1268 { .addr = CC1120_FREQOFF0, .name = "FREQOFF0" },
1269 { .addr = CC1120_FREQ2, .name = "FREQ2" },
1270 { .addr = CC1120_FREQ1, .name = "FREQ1" },
1271 { .addr = CC1120_FREQ0, .name = "FREQ0" },
1272 { .addr = CC1120_IF_ADC2, .name = "IF_ADC2" },
1273 { .addr = CC1120_IF_ADC1, .name = "IF_ADC1" },
1274 { .addr = CC1120_IF_ADC0, .name = "IF_ADC0" },
1275 { .addr = CC1120_FS_DIG1, .name = "FS_DIG1" },
1276 { .addr = CC1120_FS_DIG0, .name = "FS_DIG0" },
1277 { .addr = CC1120_FS_CAL3, .name = "FS_CAL3" },
1278 { .addr = CC1120_FS_CAL2, .name = "FS_CAL2" },
1279 { .addr = CC1120_FS_CAL1, .name = "FS_CAL1" },
1280 { .addr = CC1120_FS_CAL0, .name = "FS_CAL0" },
1281 { .addr = CC1120_FS_CHP, .name = "FS_CHP" },
1282 { .addr = CC1120_FS_DIVTWO, .name = "FS_DIVTWO" },
1283 { .addr = CC1120_FS_DSM1, .name = "FS_DSM1" },
1284 { .addr = CC1120_FS_DSM0, .name = "FS_DSM0" },
1285 { .addr = CC1120_FS_DVC1, .name = "FS_DVC1" },
1286 { .addr = CC1120_FS_DVC0, .name = "FS_DVC0" },
1287 { .addr = CC1120_FS_LBI, .name = "FS_LBI" },
1288 { .addr = CC1120_FS_PFD, .name = "FS_PFD" },
1289 { .addr = CC1120_FS_PRE, .name = "FS_PRE" },
1290 { .addr = CC1120_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
1291 { .addr = CC1120_FS_SPARE, .name = "FS_SPARE" },
1292 { .addr = CC1120_FS_VCO4, .name = "FS_VCO4" },
1293 { .addr = CC1120_FS_VCO3, .name = "FS_VCO3" },
1294 { .addr = CC1120_FS_VCO2, .name = "FS_VCO2" },
1295 { .addr = CC1120_FS_VCO1, .name = "FS_VCO1" },
1296 { .addr = CC1120_FS_VCO0, .name = "FS_VCO0" },
1297 { .addr = CC1120_GBIAS6, .name = "GBIAS6" },
1298 { .addr = CC1120_GBIAS5, .name = "GBIAS5" },
1299 { .addr = CC1120_GBIAS4, .name = "GBIAS4" },
1300 { .addr = CC1120_GBIAS3, .name = "GBIAS3" },
1301 { .addr = CC1120_GBIAS2, .name = "GBIAS2" },
1302 { .addr = CC1120_GBIAS1, .name = "GBIAS1" },
1303 { .addr = CC1120_GBIAS0, .name = "GBIAS0" },
1304 { .addr = CC1120_IFAMP, .name = "IFAMP" },
1305 { .addr = CC1120_LNA, .name = "LNA" },
1306 { .addr = CC1120_RXMIX, .name = "RXMIX" },
1307 { .addr = CC1120_XOSC5, .name = "XOSC5" },
1308 { .addr = CC1120_XOSC4, .name = "XOSC4" },
1309 { .addr = CC1120_XOSC3, .name = "XOSC3" },
1310 { .addr = CC1120_XOSC2, .name = "XOSC2" },
1311 { .addr = CC1120_XOSC1, .name = "XOSC1" },
1312 { .addr = CC1120_XOSC0, .name = "XOSC0" },
1313 { .addr = CC1120_ANALOG_SPARE, .name = "ANALOG_SPARE" },
1314 { .addr = CC1120_PA_CFG3, .name = "PA_CFG3" },
1315 { .addr = CC1120_WOR_TIME1, .name = "WOR_TIME1" },
1316 { .addr = CC1120_WOR_TIME0, .name = "WOR_TIME0" },
1317 { .addr = CC1120_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
1318 { .addr = CC1120_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
1319 { .addr = CC1120_BIST, .name = "BIST" },
1320 { .addr = CC1120_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
1321 { .addr = CC1120_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
1322 { .addr = CC1120_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
1323 { .addr = CC1120_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
1324 { .addr = CC1120_IQIE_I1, .name = "IQIE_I1" },
1325 { .addr = CC1120_IQIE_I0, .name = "IQIE_I0" },
1326 { .addr = CC1120_IQIE_Q1, .name = "IQIE_Q1" },
1327 { .addr = CC1120_IQIE_Q0, .name = "IQIE_Q0" },
1328 { .addr = CC1120_RSSI1, .name = "RSSI1" },
1329 { .addr = CC1120_RSSI0, .name = "RSSI0" },
1330 { .addr = CC1120_MARCSTATE, .name = "MARCSTATE" },
1331 { .addr = CC1120_LQI_VAL, .name = "LQI_VAL" },
1332 { .addr = CC1120_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
1333 { .addr = CC1120_DEM_STATUS, .name = "DEM_STATUS" },
1334 { .addr = CC1120_FREQOFF_EST1, .name = "FREQOFF_EST1" },
1335 { .addr = CC1120_FREQOFF_EST0, .name = "FREQOFF_EST0" },
1336 { .addr = CC1120_AGC_GAIN3, .name = "AGC_GAIN3" },
1337 { .addr = CC1120_AGC_GAIN2, .name = "AGC_GAIN2" },
1338 { .addr = CC1120_AGC_GAIN1, .name = "AGC_GAIN1" },
1339 { .addr = CC1120_AGC_GAIN0, .name = "AGC_GAIN0" },
1340 { .addr = CC1120_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
1341 { .addr = CC1120_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
1342 { .addr = CC1120_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
1343 { .addr = CC1120_RNDGEN, .name = "RNDGEN" },
1344 { .addr = CC1120_MAGN2, .name = "MAGN2" },
1345 { .addr = CC1120_MAGN1, .name = "MAGN1" },
1346 { .addr = CC1120_MAGN0, .name = "MAGN0" },
1347 { .addr = CC1120_ANG1, .name = "ANG1" },
1348 { .addr = CC1120_ANG0, .name = "ANG0" },
1349 { .addr = CC1120_CHFILT_I2, .name = "CHFILT_I2" },
1350 { .addr = CC1120_CHFILT_I1, .name = "CHFILT_I1" },
1351 { .addr = CC1120_CHFILT_I0, .name = "CHFILT_I0" },
1352 { .addr = CC1120_CHFILT_Q2, .name = "CHFILT_Q2" },
1353 { .addr = CC1120_CHFILT_Q1, .name = "CHFILT_Q1" },
1354 { .addr = CC1120_CHFILT_Q0, .name = "CHFILT_Q0" },
1355 { .addr = CC1120_GPIO_STATUS, .name = "GPIO_STATUS" },
1356 { .addr = CC1120_FSCAL_CTRL, .name = "FSCAL_CTRL" },
1357 { .addr = CC1120_PHASE_ADJUST, .name = "PHASE_ADJUST" },
1358 { .addr = CC1120_PARTNUMBER, .name = "PARTNUMBER" },
1359 { .addr = CC1120_PARTVERSION, .name = "PARTVERSION" },
1360 { .addr = CC1120_SERIAL_STATUS, .name = "SERIAL_STATUS" },
1361 { .addr = CC1120_RX_STATUS, .name = "RX_STATUS" },
1362 { .addr = CC1120_TX_STATUS, .name = "TX_STATUS" },
1363 { .addr = CC1120_MARC_STATUS1, .name = "MARC_STATUS1" },
1364 { .addr = CC1120_MARC_STATUS0, .name = "MARC_STATUS0" },
1365 { .addr = CC1120_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
1366 { .addr = CC1120_FSRF_TEST, .name = "FSRF_TEST" },
1367 { .addr = CC1120_PRE_TEST, .name = "PRE_TEST" },
1368 { .addr = CC1120_PRE_OVR, .name = "PRE_OVR" },
1369 { .addr = CC1120_ADC_TEST, .name = "ADC_TEST" },
1370 { .addr = CC1120_DVC_TEST, .name = "DVC_TEST" },
1371 { .addr = CC1120_ATEST, .name = "ATEST" },
1372 { .addr = CC1120_ATEST_LVDS, .name = "ATEST_LVDS" },
1373 { .addr = CC1120_ATEST_MODE, .name = "ATEST_MODE" },
1374 { .addr = CC1120_XOSC_TEST1, .name = "XOSC_TEST1" },
1375 { .addr = CC1120_XOSC_TEST0, .name = "XOSC_TEST0" },
1376 { .addr = CC1120_RXFIRST, .name = "RXFIRST" },
1377 { .addr = CC1120_TXFIRST, .name = "TXFIRST" },
1378 { .addr = CC1120_RXLAST, .name = "RXLAST" },
1379 { .addr = CC1120_TXLAST, .name = "TXLAST" },
1380 { .addr = CC1120_NUM_TXBYTES, .name = "NUM_TXBYTES" },
1381 { .addr = CC1120_NUM_RXBYTES, .name = "NUM_RXBYTES" },
1382 { .addr = CC1120_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
1383 { .addr = CC1120_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
1386 #define AO_NUM_CC1120_REG (sizeof ao_cc1120_reg / sizeof ao_cc1120_reg[0])
1388 static void ao_radio_show(void) {
1389 uint8_t status = ao_radio_status();
1393 status = ao_radio_status();
1394 printf ("Status: %02x\n", status);
1395 printf ("CHIP_RDY: %d\n", (status >> CC1120_STATUS_CHIP_RDY) & 1);
1396 printf ("STATE: %s\n", cc1120_state_name[(status >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK]);
1397 printf ("MARC: %02x\n", ao_radio_get_marc_status());
1399 for (i = 0; i < AO_NUM_CC1120_REG; i++)
1400 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name);
1402 printf("RX fast start: %u\n", rx_fast_start);
1403 printf("RX slow start: %u\n", rx_slow_start);
1404 printf("RX missed: %u\n", rx_missed);
1408 static void ao_radio_beep(void) {
1412 static void ao_radio_packet(void) {
1413 static const uint8_t packet[] = {
1415 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1416 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1417 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1418 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1424 ao_radio_send(packet, sizeof (packet));
1428 ao_radio_test_recv(void)
1433 if (ao_radio_recv(bytes, 34, 0)) {
1434 if (bytes[33] & 0x80)
1438 printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32]));
1439 for (b = 0; b < 32; b++)
1440 printf (" %02x", bytes[b]);
1446 #include <ao_aprs.h>
1451 #if PACKET_HAS_SLAVE
1452 ao_packet_slave_stop();
1459 static const struct ao_cmds ao_radio_cmds[] = {
1460 { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
1463 { ao_radio_aprs, "G\0Send APRS packet" },
1465 { ao_radio_show, "R\0Show CC1120 status" },
1466 { ao_radio_beep, "b\0Emit an RDF beacon" },
1467 { ao_radio_packet, "p\0Send a test packet" },
1468 { ao_radio_test_recv, "q\0Recv a test packet" },
1476 ao_radio_configured = 0;
1477 ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN));
1480 AO_CC1120_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN));
1481 for (i = 0; i < 10000; i++) {
1482 if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0)
1485 AO_CC1120_SPI_CS_PORT->bsrr = (1 << AO_CC1120_SPI_CS_PIN);
1487 ao_panic(AO_PANIC_SELF_TEST_CC1120);
1490 /* Enable the EXTI interrupt for the appropriate pin */
1491 ao_enable_port(AO_CC1120_INT_PORT);
1492 ao_exti_setup(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1493 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
1496 /* Enable the hacked up GPIO3 pin */
1497 ao_enable_port(AO_CC1120_MCU_WAKEUP_PORT);
1498 ao_exti_setup(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN,
1499 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED,
1500 ao_radio_mcu_wakeup_isr);
1502 ao_cmd_register(&ao_radio_cmds[0]);