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_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) >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK;
279 if (state == CC1120_STATUS_STATE_IDLE)
281 if (state == CC1120_STATUS_STATE_TX_FIFO_ERROR)
282 ao_radio_strobe(CC1120_SFTX);
283 if (state == CC1120_STATUS_STATE_RX_FIFO_ERROR)
284 ao_radio_strobe(CC1120_SFRX);
286 /* Flush any pending TX bytes */
287 ao_radio_strobe(CC1120_SFTX);
293 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
295 * Deviation for 38400 baud should be 20.5kHz:
297 * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz
299 * Deviation for 9600 baud should be 5.125kHz:
301 * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 3) = 5127Hz
303 * Deviation for 2400 baud should be 1.28125kHz, but cc1111 and
304 * cc115l can't do that, so we'll use 1.5kHz instead:
306 * 32e6Hz / (2 ** 24) * (256 + 137) * (2 ** 1) = 1499Hz
309 #define PACKET_DEV_M_384 80
310 #define PACKET_DEV_E_384 5
312 #define PACKET_DEV_M_96 80
313 #define PACKET_DEV_E_96 3
315 #define PACKET_DEV_M_24 137
316 #define PACKET_DEV_E_24 1
319 * For our packet data
321 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
322 * Rdata = -------------------------------------- * fosc
325 * Given the bit period of the baseband, T, the bandwidth of the
326 * baseband signal is B = 1/(2T). The overall bandwidth of the
327 * modulated signal is then Channel bandwidth = 2Δf + 2B.
329 * 38400 -- 2 * 20500 + 38400 = 79.4 kHz
330 * 9600 -- 2 * 5.125 + 9600 = 19.9 kHz
331 * 2400 -- 2 * 1.5 + 2400 = 5.4 khz
333 * Symbol rate 38400 Baud:
335 * DATARATE_M = 239914
337 * CHANBW = 79.4 (round to 100)
339 * Symbol rate 9600 Baud:
341 * DATARATE_M = 239914
343 * CHANBW = 19.9 (round to 20)
345 * Symbol rate 2400 Baud:
347 * DATARATE_M = 239914
349 * CHANBW = 5.0 (round to 8.0)
352 #define PACKET_DRATE_M 239914
354 #define PACKET_DRATE_E_384 9
357 #define PACKET_CHAN_BW_384 ((0 << CC1120_CHAN_BW_CHFILT_BYPASS) | \
358 (CC1120_CHAN_BW_ADC_CIC_DECFACT_20 << CC1120_CHAN_BW_ADC_CIC_DECFACT) | \
359 (2 << CC1120_CHAN_BW_BB_CIC_DECFACT))
361 #define PACKET_DRATE_E_96 7
363 #define PACKET_CHAN_BW_96 ((0 << CC1120_CHAN_BW_CHFILT_BYPASS) | \
364 (CC1120_CHAN_BW_ADC_CIC_DECFACT_20 << CC1120_CHAN_BW_ADC_CIC_DECFACT) | \
365 (10 << CC1120_CHAN_BW_BB_CIC_DECFACT))
367 #define PACKET_DRATE_E_24 5
369 #define PACKET_CHAN_BW_24 ((0 << CC1120_CHAN_BW_CHFILT_BYPASS) | \
370 (CC1120_CHAN_BW_ADC_CIC_DECFACT_20 << CC1120_CHAN_BW_ADC_CIC_DECFACT) | \
371 (25 << CC1120_CHAN_BW_BB_CIC_DECFACT))
373 static const uint16_t packet_setup[] = {
374 CC1120_DRATE1, ((PACKET_DRATE_M >> 8) & 0xff),
375 CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff),
376 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
377 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
378 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
379 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
380 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
381 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
382 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
383 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
384 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
385 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
386 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
387 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
388 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
389 AO_CC1120_MARC_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP,
392 static const uint16_t packet_setup_384[] = {
393 CC1120_DEVIATION_M, PACKET_DEV_M_384,
394 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
395 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
396 (PACKET_DEV_E_384 << CC1120_MODCFG_DEV_E_DEV_E)),
397 CC1120_DRATE2, ((PACKET_DRATE_E_384 << CC1120_DRATE2_DATARATE_E) |
398 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
399 CC1120_CHAN_BW, PACKET_CHAN_BW_384,
400 CC1120_PA_CFG0, 0x7b,
403 static const uint16_t packet_setup_96[] = {
404 CC1120_DEVIATION_M, PACKET_DEV_M_96,
405 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
406 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
407 (PACKET_DEV_E_96 << CC1120_MODCFG_DEV_E_DEV_E)),
408 CC1120_DRATE2, ((PACKET_DRATE_E_96 << CC1120_DRATE2_DATARATE_E) |
409 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
410 CC1120_CHAN_BW, PACKET_CHAN_BW_96,
411 CC1120_PA_CFG0, 0x7d,
414 static const uint16_t packet_setup_24[] = {
415 CC1120_DEVIATION_M, PACKET_DEV_M_24,
416 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
417 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
418 (PACKET_DEV_E_24 << CC1120_MODCFG_DEV_E_DEV_E)),
419 CC1120_DRATE2, ((PACKET_DRATE_E_24 << CC1120_DRATE2_DATARATE_E) |
420 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
421 CC1120_CHAN_BW, PACKET_CHAN_BW_24,
422 CC1120_PA_CFG0, 0x7e,
425 static const uint16_t packet_tx_setup[] = {
426 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
427 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
428 AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG,
431 static const uint16_t packet_rx_setup[] = {
432 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
433 (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT)),
434 AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT,
438 * RDF deviation is 5kHz
440 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
442 * 32e6Hz / (2 ** 24) * (256 + 71) * (2 ** 3) = 4989
447 #define RDF_PACKET_LEN 50
450 * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
452 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
453 * Rdata = -------------------------------------- * fosc
459 * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
461 #define RDF_DRATE_E 5
462 #define RDF_DRATE_M 25166
463 #define RDF_PACKET_LEN 50
465 static const uint16_t rdf_setup[] = {
466 CC1120_DEVIATION_M, RDF_DEV_M,
467 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
468 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
469 (RDF_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
470 CC1120_DRATE2, ((RDF_DRATE_E << CC1120_DRATE2_DATARATE_E) |
471 (((RDF_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
472 CC1120_DRATE1, ((RDF_DRATE_M >> 8) & 0xff),
473 CC1120_DRATE0, ((RDF_DRATE_M >> 0) & 0xff),
474 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
475 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
476 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
477 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
478 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
479 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
480 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
481 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
482 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
483 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
484 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
485 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
486 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
487 CC1120_PA_CFG0, 0x7e,
491 * APRS deviation is 3kHz
493 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
495 * 32e6Hz / (2 ** 24) * (256 + 137) * (2 ** 2) = 2998Hz
499 #define APRS_DEV_M 137
502 * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate)
504 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
505 * Rdata = -------------------------------------- * fosc
508 * DATARATE_M = 239914
511 * Rdata = 9599.998593330383301
514 #define APRS_DRATE_E 7
515 #define APRS_DRATE_M 239914
517 static const uint16_t aprs_setup[] = {
518 CC1120_DEVIATION_M, APRS_DEV_M,
519 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
520 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
521 (APRS_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
522 CC1120_DRATE2, ((APRS_DRATE_E << CC1120_DRATE2_DATARATE_E) |
523 (((APRS_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
524 CC1120_DRATE1, ((APRS_DRATE_M >> 8) & 0xff),
525 CC1120_DRATE0, ((APRS_DRATE_M >> 0) & 0xff),
526 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
527 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
528 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
529 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
530 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
531 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
532 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
533 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
534 CC1120_PA_CFG0, 0x7d,
538 * For Test mode, we want an unmodulated carrier. To do that, we
539 * set the deviation to zero and enable a preamble so that the radio
540 * turns on before we send any data
543 static const uint16_t test_setup[] = {
544 CC1120_DEVIATION_M, 0,
545 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
546 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
547 (0 << CC1120_MODCFG_DEV_E_DEV_E)),
548 CC1120_DRATE2, ((APRS_DRATE_E << CC1120_DRATE2_DATARATE_E) |
549 (((APRS_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
550 CC1120_DRATE1, ((APRS_DRATE_M >> 8) & 0xff),
551 CC1120_DRATE0, ((APRS_DRATE_M >> 0) & 0xff),
552 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
553 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
554 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
555 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
556 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
557 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
558 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
559 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
562 #define AO_PKT_CFG0_INFINITE ((0 << CC1120_PKT_CFG0_RESERVED7) | \
563 (CC1120_PKT_CFG0_LENGTH_CONFIG_INFINITE << CC1120_PKT_CFG0_LENGTH_CONFIG) | \
564 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | \
565 (0 << CC1120_PKT_CFG0_UART_MODE_EN) | \
566 (0 << CC1120_PKT_CFG0_UART_SWAP_EN))
568 #define AO_PKT_CFG0_FIXED ((0 << CC1120_PKT_CFG0_RESERVED7) | \
569 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) | \
570 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | \
571 (0 << CC1120_PKT_CFG0_UART_MODE_EN) | \
572 (0 << CC1120_PKT_CFG0_UART_SWAP_EN))
574 static uint16_t ao_radio_mode;
576 #define AO_RADIO_MODE_BITS_PACKET 1
577 #define AO_RADIO_MODE_BITS_PACKET_TX 2
578 #define AO_RADIO_MODE_BITS_TX_BUF 4
579 #define AO_RADIO_MODE_BITS_TX_FINISH 8
580 #define AO_RADIO_MODE_BITS_PACKET_RX 16
581 #define AO_RADIO_MODE_BITS_RDF 32
582 #define AO_RADIO_MODE_BITS_APRS 64
583 #define AO_RADIO_MODE_BITS_TEST 128
584 #define AO_RADIO_MODE_BITS_INFINITE 256
585 #define AO_RADIO_MODE_BITS_FIXED 512
587 #define AO_RADIO_MODE_NONE 0
588 #define AO_RADIO_MODE_PACKET_TX_BUF (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_BUF)
589 #define AO_RADIO_MODE_PACKET_TX_FINISH (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_FINISH)
590 #define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_RX)
591 #define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_TX_FINISH)
592 #define AO_RADIO_MODE_APRS_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
593 #define AO_RADIO_MODE_APRS_LAST_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_BUF)
594 #define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
595 #define AO_RADIO_MODE_TEST (AO_RADIO_MODE_BITS_TEST | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
598 _ao_radio_set_regs(const uint16_t *regs, int nreg)
602 for (i = 0; i < nreg; i++) {
603 ao_radio_reg_write(regs[0], regs[1]);
608 #define ao_radio_set_regs(setup) _ao_radio_set_regs(setup, (sizeof (setup) / sizeof(setup[0])) >> 1)
611 ao_radio_set_mode(uint16_t new_mode)
615 if (new_mode == ao_radio_mode)
618 changes = new_mode & (~ao_radio_mode);
620 if (changes & AO_RADIO_MODE_BITS_PACKET) {
621 ao_radio_set_regs(packet_setup);
623 switch (ao_config.radio_rate) {
625 case AO_RADIO_RATE_38400:
626 ao_radio_set_regs(packet_setup_384);
628 case AO_RADIO_RATE_9600:
629 ao_radio_set_regs(packet_setup_96);
631 case AO_RADIO_RATE_2400:
632 ao_radio_set_regs(packet_setup_24);
637 if (changes & AO_RADIO_MODE_BITS_PACKET_TX)
638 ao_radio_set_regs(packet_tx_setup);
640 if (changes & AO_RADIO_MODE_BITS_TX_BUF)
641 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_TXFIFO_THR);
643 if (changes & AO_RADIO_MODE_BITS_TX_FINISH)
644 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG);
646 if (changes & AO_RADIO_MODE_BITS_PACKET_RX)
647 ao_radio_set_regs(packet_rx_setup);
649 if (changes & AO_RADIO_MODE_BITS_RDF)
650 ao_radio_set_regs(rdf_setup);
652 if (changes & AO_RADIO_MODE_BITS_APRS)
653 ao_radio_set_regs(aprs_setup);
655 if (changes & AO_RADIO_MODE_BITS_TEST)
656 ao_radio_set_regs(test_setup);
658 if (changes & AO_RADIO_MODE_BITS_INFINITE)
659 ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_INFINITE);
661 if (changes & AO_RADIO_MODE_BITS_FIXED)
662 ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_FIXED);
664 ao_radio_mode = new_mode;
667 static const uint16_t radio_setup[] = {
668 #include "ao_cc1120_CC1120.h"
671 static uint8_t ao_radio_configured = 0;
676 ao_radio_strobe(CC1120_SRES);
678 ao_radio_set_regs(radio_setup);
684 ao_radio_configured = 1;
688 ao_radio_set_len(uint8_t len)
690 static uint8_t last_len;
692 if (len != last_len) {
693 ao_radio_reg_write(CC1120_PKT_LEN, len);
699 ao_radio_get(uint8_t len)
701 static uint32_t last_radio_setting;
702 static uint8_t last_radio_rate;
704 ao_mutex_get(&ao_radio_mutex);
706 if (!ao_radio_configured)
708 if (ao_config.radio_setting != last_radio_setting) {
709 ao_radio_reg_write(CC1120_FREQ2, ao_config.radio_setting >> 16);
710 ao_radio_reg_write(CC1120_FREQ1, ao_config.radio_setting >> 8);
711 ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting);
712 last_radio_setting = ao_config.radio_setting;
714 if (ao_config.radio_rate != last_radio_rate) {
715 ao_radio_mode &= ~AO_RADIO_MODE_BITS_PACKET;
716 last_radio_rate = ao_config.radio_rate;
718 ao_radio_set_len(len);
721 #define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
724 ao_rdf_start(uint8_t len)
729 ao_radio_set_mode(AO_RADIO_MODE_RDF);
739 ao_arch_block_interrupts();
740 while (!ao_radio_wake && !ao_radio_abort && !ao_radio_mcu_wake)
741 ao_sleep(&ao_radio_wake);
742 ao_arch_release_interrupts();
743 if (ao_radio_mcu_wake)
744 ao_radio_check_marc_status();
753 ao_rdf_start(AO_RADIO_RDF_LEN);
755 ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN);
761 ao_radio_continuity(uint8_t c)
766 ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN);
768 status = ao_radio_fifo_write_start();
769 for (i = 0; i < 3; i++) {
770 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
772 ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN);
774 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN);
776 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
777 status = ao_radio_fifo_write_stop(status);
783 ao_radio_rdf_abort(void)
786 ao_wakeup(&ao_radio_wake);
790 ao_radio_test_cmd(void)
793 static uint8_t radio_on;
795 if (ao_cmd_lex_c != '\n') {
797 mode = (uint8_t) ao_cmd_lex_u32;
800 if ((mode & 2) && !radio_on) {
802 ao_monitor_disable();
805 ao_packet_slave_stop();
808 ao_radio_set_mode(AO_RADIO_MODE_TEST);
809 ao_radio_strobe(CC1120_STX);
812 for (t = 0; t < 10; t++) {
813 printf ("status: %02x\n", ao_radio_status());
814 ao_delay(AO_MS_TO_TICKS(100));
821 printf ("Hit a character to stop..."); flush();
825 if ((mode & 1) && radio_on) {
836 ao_radio_wait_isr(uint16_t timeout)
838 ao_arch_block_interrupts();
839 while (!ao_radio_wake && !ao_radio_mcu_wake && !ao_radio_abort)
840 if (ao_sleep_for(&ao_radio_wake, timeout))
842 ao_arch_release_interrupts();
843 if (ao_radio_mcu_wake)
844 ao_radio_check_marc_status();
848 ao_radio_wait_tx(uint8_t wait_fifo)
850 uint8_t fifo_space = 0;
853 ao_radio_wait_isr(0);
856 fifo_space = ao_radio_tx_fifo_space();
857 } while (!fifo_space && !ao_radio_abort);
861 static uint8_t tx_data[(AO_RADIO_MAX_SEND + 4) * 2];
864 ao_radio_send(const void *d, uint8_t size)
866 uint8_t *e = tx_data;
872 encode_len = ao_fec_encode(d, size, tx_data);
874 ao_radio_get(encode_len);
878 /* Flush any pending TX bytes */
879 ao_radio_strobe(CC1120_SFTX);
882 fifo_space = CC1120_FIFO_SIZE;
884 this_len = encode_len;
887 if (this_len > fifo_space) {
888 this_len = fifo_space;
889 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_BUF);
891 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_FINISH);
894 ao_radio_fifo_write(e, this_len);
896 encode_len -= this_len;
902 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
905 fifo_space = ao_radio_wait_tx(encode_len != 0);
906 if (ao_radio_abort) {
911 while (started && !ao_radio_abort && !ao_radio_tx_finished)
912 ao_radio_wait_isr(0);
916 #define AO_RADIO_LOTS 64
919 ao_radio_send_aprs(ao_radio_fill_func fill)
921 uint8_t buf[AO_RADIO_LOTS], *b;
929 fifo_space = CC1120_FIFO_SIZE;
931 cnt = (*fill)(buf, sizeof(buf));
938 /* At the last buffer, set the total length */
940 ao_radio_set_len(total & 0xff);
944 uint8_t this_len = cnt;
946 /* Wait for some space in the fifo */
947 while (!ao_radio_abort && (fifo_space = ao_radio_tx_fifo_space()) == 0) {
949 ao_radio_wait_isr(0);
953 if (this_len > fifo_space)
954 this_len = fifo_space;
960 ao_radio_set_mode(AO_RADIO_MODE_APRS_LAST_BUF);
962 ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
964 ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
966 ao_radio_fifo_write(b, this_len);
973 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
975 if (ao_radio_abort) {
979 /* Wait for the transmitter to go idle */
981 ao_radio_wait_isr(0);
986 static uint8_t rx_data[(AO_RADIO_MAX_RECV + 4) * 2 * 8];
987 static uint16_t rx_data_count;
988 static uint16_t rx_data_consumed;
989 static uint16_t rx_data_cur;
990 static uint8_t rx_ignore;
991 static uint8_t rx_waiting;
992 static uint8_t rx_starting;
993 static uint8_t rx_task_id;
994 static uint32_t rx_fast_start;
995 static uint32_t rx_slow_start;
996 static uint32_t rx_missed;
999 static uint32_t rx_start_tick, rx_packet_tick, rx_done_tick, rx_last_done_tick;
1001 uint32_t ao_rx_start_tick, ao_rx_packet_tick, ao_rx_done_tick, ao_rx_last_done_tick;
1003 #include <ao_profile.h>
1007 ao_radio_rx_isr(void)
1012 if (ao_radio_try_select(rx_task_id)) {
1015 _ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
1028 ao_wakeup(&ao_radio_wake);
1030 d = ao_radio_spi_recv_byte();
1031 if (rx_ignore == 0) {
1032 if (rx_data_cur < rx_data_count)
1033 rx_data[rx_data_cur++] = d;
1034 if (rx_data_cur >= rx_data_count) {
1035 ao_spi_clr_cs(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN));
1036 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
1038 if (rx_waiting && rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) {
1040 if (!rx_packet_tick)
1041 rx_packet_tick = ao_profile_tick();
1042 if (rx_data_cur < rx_data_count)
1046 ao_wakeup(&ao_radio_wake);
1054 ao_radio_rx_wait(void)
1056 ao_arch_block_interrupts();
1058 while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&
1062 if (ao_sleep_for(&ao_radio_wake, AO_MS_TO_TICKS(100)))
1066 ao_arch_release_interrupts();
1067 if (ao_radio_abort || ao_radio_mcu_wake)
1069 rx_data_consumed += AO_FEC_DECODE_BLOCK;
1071 return rx_data_cur - rx_data_consumed;
1073 return AO_FEC_DECODE_BLOCK;
1077 ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout)
1080 uint8_t radio_rssi = 0;
1084 size -= 2; /* status bytes */
1085 if (size > AO_RADIO_MAX_RECV) {
1086 ao_delay(AO_SEC_TO_TICKS(1));
1090 rx_start_tick = ao_profile_tick();
1093 len = size + 2; /* CRC bytes */
1094 len += 1 + ~(len & 1); /* 1 or two pad bytes */
1095 len *= 2; /* 1/2 rate convolution */
1096 rx_data_count = len * 8; /* bytes to bits */
1098 rx_data_consumed = 0;
1101 /* Must be set before changing the frequency; any abort
1102 * after the frequency is set needs to terminate the read
1103 * so that the registers can be reprogrammed
1110 ao_radio_mcu_wake = 0;
1112 ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
1114 /* configure interrupt pin */
1115 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT);
1116 ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1117 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
1120 rx_task_id = ao_cur_task->task_id;
1122 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
1123 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
1125 ao_radio_strobe(CC1120_SRX);
1127 ao_arch_block_interrupts();
1128 while (rx_starting && !ao_radio_abort) {
1129 if (ao_sleep_for(&ao_radio_wake, timeout))
1132 uint8_t rx_task_id_save = rx_task_id;
1135 ao_arch_release_interrupts();
1137 if (ao_radio_abort) {
1138 if (rx_task_id_save == 0)
1139 ao_radio_burst_read_stop();
1144 if (rx_task_id_save) {
1147 _ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
1149 (void) ao_radio_spi_recv_byte();
1154 ret = ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait);
1156 ao_radio_burst_read_stop();
1158 if (ao_radio_mcu_wake)
1159 ao_radio_check_marc_status();
1164 /* Convert from 'real' rssi to cc1111-style values */
1166 rssi0 = ao_radio_reg_read(CC1120_RSSI0);
1168 int8_t rssi = ao_radio_reg_read(CC1120_RSSI1);
1169 ao_radio_rssi = rssi;
1171 /* Bound it to the representable range */
1174 radio_rssi = AO_RADIO_FROM_RSSI (rssi);
1181 /* Store the received RSSI value; the crc-OK byte is already done */
1183 ((uint8_t *) d)[size] = radio_rssi;
1186 rx_last_done_tick = rx_done_tick;
1187 rx_done_tick = ao_profile_tick();
1189 ao_rx_start_tick = rx_start_tick;
1190 ao_rx_packet_tick = rx_packet_tick;
1191 ao_rx_done_tick = rx_done_tick;
1192 ao_rx_last_done_tick = rx_last_done_tick;
1200 static char *cc1120_state_name[] = {
1201 [CC1120_STATUS_STATE_IDLE] = "IDLE",
1202 [CC1120_STATUS_STATE_RX] = "RX",
1203 [CC1120_STATUS_STATE_TX] = "TX",
1204 [CC1120_STATUS_STATE_FSTXON] = "FSTXON",
1205 [CC1120_STATUS_STATE_CALIBRATE] = "CALIBRATE",
1206 [CC1120_STATUS_STATE_SETTLING] = "SETTLING",
1207 [CC1120_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
1208 [CC1120_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
1211 struct ao_cc1120_reg {
1216 static const struct ao_cc1120_reg ao_cc1120_reg[] = {
1217 { .addr = CC1120_IOCFG3, .name = "IOCFG3" },
1218 { .addr = CC1120_IOCFG2, .name = "IOCFG2" },
1219 { .addr = CC1120_IOCFG1, .name = "IOCFG1" },
1220 { .addr = CC1120_IOCFG0, .name = "IOCFG0" },
1221 { .addr = CC1120_SYNC3, .name = "SYNC3" },
1222 { .addr = CC1120_SYNC2, .name = "SYNC2" },
1223 { .addr = CC1120_SYNC1, .name = "SYNC1" },
1224 { .addr = CC1120_SYNC0, .name = "SYNC0" },
1225 { .addr = CC1120_SYNC_CFG1, .name = "SYNC_CFG1" },
1226 { .addr = CC1120_SYNC_CFG0, .name = "SYNC_CFG0" },
1227 { .addr = CC1120_DEVIATION_M, .name = "DEVIATION_M" },
1228 { .addr = CC1120_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
1229 { .addr = CC1120_DCFILT_CFG, .name = "DCFILT_CFG" },
1230 { .addr = CC1120_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
1231 { .addr = CC1120_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
1232 { .addr = CC1120_FREQ_IF_CFG, .name = "FREQ_IF_CFG" },
1233 { .addr = CC1120_IQIC, .name = "IQIC" },
1234 { .addr = CC1120_CHAN_BW, .name = "CHAN_BW" },
1235 { .addr = CC1120_MDMCFG1, .name = "MDMCFG1" },
1236 { .addr = CC1120_MDMCFG0, .name = "MDMCFG0" },
1237 { .addr = CC1120_DRATE2, .name = "DRATE2" },
1238 { .addr = CC1120_DRATE1, .name = "DRATE1" },
1239 { .addr = CC1120_DRATE0, .name = "DRATE0" },
1240 { .addr = CC1120_AGC_REF, .name = "AGC_REF" },
1241 { .addr = CC1120_AGC_CS_THR, .name = "AGC_CS_THR" },
1242 { .addr = CC1120_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
1243 { .addr = CC1120_AGC_CFG3, .name = "AGC_CFG3" },
1244 { .addr = CC1120_AGC_CFG2, .name = "AGC_CFG2" },
1245 { .addr = CC1120_AGC_CFG1, .name = "AGC_CFG1" },
1246 { .addr = CC1120_AGC_CFG0, .name = "AGC_CFG0" },
1247 { .addr = CC1120_FIFO_CFG, .name = "FIFO_CFG" },
1248 { .addr = CC1120_DEV_ADDR, .name = "DEV_ADDR" },
1249 { .addr = CC1120_SETTLING_CFG, .name = "SETTLING_CFG" },
1250 { .addr = CC1120_FS_CFG, .name = "FS_CFG" },
1251 { .addr = CC1120_WOR_CFG1, .name = "WOR_CFG1" },
1252 { .addr = CC1120_WOR_CFG0, .name = "WOR_CFG0" },
1253 { .addr = CC1120_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
1254 { .addr = CC1120_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
1255 { .addr = CC1120_PKT_CFG2, .name = "PKT_CFG2" },
1256 { .addr = CC1120_PKT_CFG1, .name = "PKT_CFG1" },
1257 { .addr = CC1120_PKT_CFG0, .name = "PKT_CFG0" },
1258 { .addr = CC1120_RFEND_CFG1, .name = "RFEND_CFG1" },
1259 { .addr = CC1120_RFEND_CFG0, .name = "RFEND_CFG0" },
1260 { .addr = CC1120_PA_CFG2, .name = "PA_CFG2" },
1261 { .addr = CC1120_PA_CFG1, .name = "PA_CFG1" },
1262 { .addr = CC1120_PA_CFG0, .name = "PA_CFG0" },
1263 { .addr = CC1120_PKT_LEN, .name = "PKT_LEN" },
1264 { .addr = CC1120_IF_MIX_CFG, .name = "IF_MIX_CFG" },
1265 { .addr = CC1120_FREQOFF_CFG, .name = "FREQOFF_CFG" },
1266 { .addr = CC1120_TOC_CFG, .name = "TOC_CFG" },
1267 { .addr = CC1120_MARC_SPARE, .name = "MARC_SPARE" },
1268 { .addr = CC1120_ECG_CFG, .name = "ECG_CFG" },
1269 { .addr = CC1120_SOFT_TX_DATA_CFG, .name = "SOFT_TX_DATA_CFG" },
1270 { .addr = CC1120_EXT_CTRL, .name = "EXT_CTRL" },
1271 { .addr = CC1120_RCCAL_FINE, .name = "RCCAL_FINE" },
1272 { .addr = CC1120_RCCAL_COARSE, .name = "RCCAL_COARSE" },
1273 { .addr = CC1120_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
1274 { .addr = CC1120_FREQOFF1, .name = "FREQOFF1" },
1275 { .addr = CC1120_FREQOFF0, .name = "FREQOFF0" },
1276 { .addr = CC1120_FREQ2, .name = "FREQ2" },
1277 { .addr = CC1120_FREQ1, .name = "FREQ1" },
1278 { .addr = CC1120_FREQ0, .name = "FREQ0" },
1279 { .addr = CC1120_IF_ADC2, .name = "IF_ADC2" },
1280 { .addr = CC1120_IF_ADC1, .name = "IF_ADC1" },
1281 { .addr = CC1120_IF_ADC0, .name = "IF_ADC0" },
1282 { .addr = CC1120_FS_DIG1, .name = "FS_DIG1" },
1283 { .addr = CC1120_FS_DIG0, .name = "FS_DIG0" },
1284 { .addr = CC1120_FS_CAL3, .name = "FS_CAL3" },
1285 { .addr = CC1120_FS_CAL2, .name = "FS_CAL2" },
1286 { .addr = CC1120_FS_CAL1, .name = "FS_CAL1" },
1287 { .addr = CC1120_FS_CAL0, .name = "FS_CAL0" },
1288 { .addr = CC1120_FS_CHP, .name = "FS_CHP" },
1289 { .addr = CC1120_FS_DIVTWO, .name = "FS_DIVTWO" },
1290 { .addr = CC1120_FS_DSM1, .name = "FS_DSM1" },
1291 { .addr = CC1120_FS_DSM0, .name = "FS_DSM0" },
1292 { .addr = CC1120_FS_DVC1, .name = "FS_DVC1" },
1293 { .addr = CC1120_FS_DVC0, .name = "FS_DVC0" },
1294 { .addr = CC1120_FS_LBI, .name = "FS_LBI" },
1295 { .addr = CC1120_FS_PFD, .name = "FS_PFD" },
1296 { .addr = CC1120_FS_PRE, .name = "FS_PRE" },
1297 { .addr = CC1120_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
1298 { .addr = CC1120_FS_SPARE, .name = "FS_SPARE" },
1299 { .addr = CC1120_FS_VCO4, .name = "FS_VCO4" },
1300 { .addr = CC1120_FS_VCO3, .name = "FS_VCO3" },
1301 { .addr = CC1120_FS_VCO2, .name = "FS_VCO2" },
1302 { .addr = CC1120_FS_VCO1, .name = "FS_VCO1" },
1303 { .addr = CC1120_FS_VCO0, .name = "FS_VCO0" },
1304 { .addr = CC1120_GBIAS6, .name = "GBIAS6" },
1305 { .addr = CC1120_GBIAS5, .name = "GBIAS5" },
1306 { .addr = CC1120_GBIAS4, .name = "GBIAS4" },
1307 { .addr = CC1120_GBIAS3, .name = "GBIAS3" },
1308 { .addr = CC1120_GBIAS2, .name = "GBIAS2" },
1309 { .addr = CC1120_GBIAS1, .name = "GBIAS1" },
1310 { .addr = CC1120_GBIAS0, .name = "GBIAS0" },
1311 { .addr = CC1120_IFAMP, .name = "IFAMP" },
1312 { .addr = CC1120_LNA, .name = "LNA" },
1313 { .addr = CC1120_RXMIX, .name = "RXMIX" },
1314 { .addr = CC1120_XOSC5, .name = "XOSC5" },
1315 { .addr = CC1120_XOSC4, .name = "XOSC4" },
1316 { .addr = CC1120_XOSC3, .name = "XOSC3" },
1317 { .addr = CC1120_XOSC2, .name = "XOSC2" },
1318 { .addr = CC1120_XOSC1, .name = "XOSC1" },
1319 { .addr = CC1120_XOSC0, .name = "XOSC0" },
1320 { .addr = CC1120_ANALOG_SPARE, .name = "ANALOG_SPARE" },
1321 { .addr = CC1120_PA_CFG3, .name = "PA_CFG3" },
1322 { .addr = CC1120_WOR_TIME1, .name = "WOR_TIME1" },
1323 { .addr = CC1120_WOR_TIME0, .name = "WOR_TIME0" },
1324 { .addr = CC1120_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
1325 { .addr = CC1120_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
1326 { .addr = CC1120_BIST, .name = "BIST" },
1327 { .addr = CC1120_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
1328 { .addr = CC1120_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
1329 { .addr = CC1120_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
1330 { .addr = CC1120_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
1331 { .addr = CC1120_IQIE_I1, .name = "IQIE_I1" },
1332 { .addr = CC1120_IQIE_I0, .name = "IQIE_I0" },
1333 { .addr = CC1120_IQIE_Q1, .name = "IQIE_Q1" },
1334 { .addr = CC1120_IQIE_Q0, .name = "IQIE_Q0" },
1335 { .addr = CC1120_RSSI1, .name = "RSSI1" },
1336 { .addr = CC1120_RSSI0, .name = "RSSI0" },
1337 { .addr = CC1120_MARCSTATE, .name = "MARCSTATE" },
1338 { .addr = CC1120_LQI_VAL, .name = "LQI_VAL" },
1339 { .addr = CC1120_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
1340 { .addr = CC1120_DEM_STATUS, .name = "DEM_STATUS" },
1341 { .addr = CC1120_FREQOFF_EST1, .name = "FREQOFF_EST1" },
1342 { .addr = CC1120_FREQOFF_EST0, .name = "FREQOFF_EST0" },
1343 { .addr = CC1120_AGC_GAIN3, .name = "AGC_GAIN3" },
1344 { .addr = CC1120_AGC_GAIN2, .name = "AGC_GAIN2" },
1345 { .addr = CC1120_AGC_GAIN1, .name = "AGC_GAIN1" },
1346 { .addr = CC1120_AGC_GAIN0, .name = "AGC_GAIN0" },
1347 { .addr = CC1120_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
1348 { .addr = CC1120_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
1349 { .addr = CC1120_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
1350 { .addr = CC1120_RNDGEN, .name = "RNDGEN" },
1351 { .addr = CC1120_MAGN2, .name = "MAGN2" },
1352 { .addr = CC1120_MAGN1, .name = "MAGN1" },
1353 { .addr = CC1120_MAGN0, .name = "MAGN0" },
1354 { .addr = CC1120_ANG1, .name = "ANG1" },
1355 { .addr = CC1120_ANG0, .name = "ANG0" },
1356 { .addr = CC1120_CHFILT_I2, .name = "CHFILT_I2" },
1357 { .addr = CC1120_CHFILT_I1, .name = "CHFILT_I1" },
1358 { .addr = CC1120_CHFILT_I0, .name = "CHFILT_I0" },
1359 { .addr = CC1120_CHFILT_Q2, .name = "CHFILT_Q2" },
1360 { .addr = CC1120_CHFILT_Q1, .name = "CHFILT_Q1" },
1361 { .addr = CC1120_CHFILT_Q0, .name = "CHFILT_Q0" },
1362 { .addr = CC1120_GPIO_STATUS, .name = "GPIO_STATUS" },
1363 { .addr = CC1120_FSCAL_CTRL, .name = "FSCAL_CTRL" },
1364 { .addr = CC1120_PHASE_ADJUST, .name = "PHASE_ADJUST" },
1365 { .addr = CC1120_PARTNUMBER, .name = "PARTNUMBER" },
1366 { .addr = CC1120_PARTVERSION, .name = "PARTVERSION" },
1367 { .addr = CC1120_SERIAL_STATUS, .name = "SERIAL_STATUS" },
1368 { .addr = CC1120_RX_STATUS, .name = "RX_STATUS" },
1369 { .addr = CC1120_TX_STATUS, .name = "TX_STATUS" },
1370 { .addr = CC1120_MARC_STATUS1, .name = "MARC_STATUS1" },
1371 { .addr = CC1120_MARC_STATUS0, .name = "MARC_STATUS0" },
1372 { .addr = CC1120_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
1373 { .addr = CC1120_FSRF_TEST, .name = "FSRF_TEST" },
1374 { .addr = CC1120_PRE_TEST, .name = "PRE_TEST" },
1375 { .addr = CC1120_PRE_OVR, .name = "PRE_OVR" },
1376 { .addr = CC1120_ADC_TEST, .name = "ADC_TEST" },
1377 { .addr = CC1120_DVC_TEST, .name = "DVC_TEST" },
1378 { .addr = CC1120_ATEST, .name = "ATEST" },
1379 { .addr = CC1120_ATEST_LVDS, .name = "ATEST_LVDS" },
1380 { .addr = CC1120_ATEST_MODE, .name = "ATEST_MODE" },
1381 { .addr = CC1120_XOSC_TEST1, .name = "XOSC_TEST1" },
1382 { .addr = CC1120_XOSC_TEST0, .name = "XOSC_TEST0" },
1383 { .addr = CC1120_RXFIRST, .name = "RXFIRST" },
1384 { .addr = CC1120_TXFIRST, .name = "TXFIRST" },
1385 { .addr = CC1120_RXLAST, .name = "RXLAST" },
1386 { .addr = CC1120_TXLAST, .name = "TXLAST" },
1387 { .addr = CC1120_NUM_TXBYTES, .name = "NUM_TXBYTES" },
1388 { .addr = CC1120_NUM_RXBYTES, .name = "NUM_RXBYTES" },
1389 { .addr = CC1120_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
1390 { .addr = CC1120_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
1393 #define AO_NUM_CC1120_REG (sizeof ao_cc1120_reg / sizeof ao_cc1120_reg[0])
1395 static void ao_radio_show(void) {
1396 uint8_t status = ao_radio_status();
1400 status = ao_radio_status();
1401 printf ("Status: %02x\n", status);
1402 printf ("CHIP_RDY: %d\n", (status >> CC1120_STATUS_CHIP_RDY) & 1);
1403 printf ("STATE: %s\n", cc1120_state_name[(status >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK]);
1404 printf ("MARC: %02x\n", ao_radio_get_marc_status());
1406 for (i = 0; i < AO_NUM_CC1120_REG; i++)
1407 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name);
1409 printf("RX fast start: %u\n", rx_fast_start);
1410 printf("RX slow start: %u\n", rx_slow_start);
1411 printf("RX missed: %u\n", rx_missed);
1415 static void ao_radio_beep(void) {
1419 static void ao_radio_packet(void) {
1420 static const uint8_t packet[] = {
1422 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1423 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1424 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1425 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1431 ao_radio_send(packet, sizeof (packet));
1435 ao_radio_test_recv(void)
1440 if (ao_radio_recv(bytes, 34, 0)) {
1441 if (bytes[33] & 0x80)
1445 printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32]));
1446 for (b = 0; b < 32; b++)
1447 printf (" %02x", bytes[b]);
1453 #include <ao_aprs.h>
1458 ao_packet_slave_stop();
1464 static const struct ao_cmds ao_radio_cmds[] = {
1465 { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
1468 { ao_radio_aprs, "G\0Send APRS packet" },
1470 { ao_radio_show, "R\0Show CC1120 status" },
1471 { ao_radio_beep, "b\0Emit an RDF beacon" },
1472 { ao_radio_packet, "p\0Send a test packet" },
1473 { ao_radio_test_recv, "q\0Recv a test packet" },
1481 ao_radio_configured = 0;
1482 ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN));
1485 AO_CC1120_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN));
1486 for (i = 0; i < 10000; i++) {
1487 if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0)
1490 AO_CC1120_SPI_CS_PORT->bsrr = (1 << AO_CC1120_SPI_CS_PIN);
1492 ao_panic(AO_PANIC_SELF_TEST_CC1120);
1495 /* Enable the EXTI interrupt for the appropriate pin */
1496 ao_enable_port(AO_CC1120_INT_PORT);
1497 ao_exti_setup(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1498 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
1501 /* Enable the hacked up GPIO3 pin */
1502 ao_enable_port(AO_CC1120_MCU_WAKEUP_PORT);
1503 ao_exti_setup(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN,
1504 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED,
1505 ao_radio_mcu_wakeup_isr);
1507 ao_cmd_register(&ao_radio_cmds[0]);