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_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)
46 #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)
47 #define ao_radio_deselect() ao_spi_put_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS)
48 #define ao_radio_spi_start_bytes() ao_spi_start_bytes(AO_CC1120_SPI_BUS)
49 #define ao_radio_spi_stop_bytes() ao_spi_stop_bytes(AO_CC1120_SPI_BUS)
50 #define ao_radio_spi_send_byte(b) ao_spi_send_byte(b, AO_CC1120_SPI_BUS)
51 #define ao_radio_spi_recv_byte() ao_spi_recv_byte(AO_CC1120_SPI_BUS)
52 #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1120_SPI_BUS)
53 #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1120_SPI_BUS)
54 #define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1120_SPI_BUS)
55 #define ao_radio_duplex(o,i,l) ao_spi_duplex((o), (i), (l), AO_CC1120_SPI_BUS)
58 ao_radio_reg_read(uint16_t addr)
64 printf("\t\tao_radio_reg_read (%04x): ", addr); flush();
66 if (CC1120_IS_EXTENDED(addr)) {
67 data[0] = ((1 << CC1120_READ) |
73 data[0] = ((1 << CC1120_READ) |
79 ao_radio_spi_send(data, d);
80 ao_radio_spi_recv(data, 1);
83 printf (" %02x\n", data[0]);
89 ao_radio_reg_write(uint16_t addr, uint8_t value)
95 printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value);
97 if (CC1120_IS_EXTENDED(addr)) {
98 data[0] = ((0 << CC1120_READ) |
104 data[0] = ((0 << CC1120_READ) |
105 (0 << CC1120_BURST) |
111 ao_radio_spi_send(data, d+1);
116 _ao_radio_burst_read_start (uint16_t addr)
118 ao_radio_spi_start_bytes();
120 if (CC1120_IS_EXTENDED(addr)) {
121 ao_radio_spi_send_byte((1 << CC1120_READ) |
122 (1 << CC1120_BURST) |
125 addr |= ((1 << CC1120_READ) |
126 (1 << CC1120_BURST));
128 ao_radio_spi_send_byte(addr);
132 ao_radio_burst_read_stop (void)
134 ao_radio_spi_stop_bytes();
140 ao_radio_strobe(uint8_t addr)
145 printf("\t\tao_radio_strobe (%02x): ", addr); flush();
148 ao_radio_duplex(&addr, &in, 1);
151 printf("%02x\n", in); flush();
158 ao_radio_fifo_read(uint8_t *data, uint8_t len)
160 uint8_t addr = ((1 << CC1120_READ) |
161 (1 << CC1120_BURST) |
166 ao_radio_duplex(&addr, &status, 1);
167 ao_radio_spi_recv(data, len);
174 ao_radio_fifo_write_start(void)
176 uint8_t addr = ((0 << CC1120_READ) |
177 (1 << CC1120_BURST) |
182 ao_radio_duplex(&addr, &status, 1);
186 static inline uint8_t ao_radio_fifo_write_stop(uint8_t status) {
192 ao_radio_fifo_write(uint8_t *data, uint8_t len)
194 uint8_t status = ao_radio_fifo_write_start();
195 ao_radio_spi_send(data, len);
196 return ao_radio_fifo_write_stop(status);
200 ao_radio_fifo_write_fixed(uint8_t data, uint8_t len)
202 uint8_t status = ao_radio_fifo_write_start();
203 ao_radio_spi_send_fixed(data, len);
204 return ao_radio_fifo_write_stop(status);
208 ao_radio_int_pin(void)
210 return ao_gpio_get(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_CC1120_INT);
215 ao_radio_status(void)
217 return ao_radio_strobe (CC1120_SNOP);
222 ao_radio_recv_abort(void)
225 ao_wakeup(&ao_radio_wake);
228 #define ao_radio_rdf_value 0x55
231 ao_radio_get_marc_status(void)
233 return ao_radio_reg_read(CC1120_MARC_STATUS1);
237 ao_radio_mcu_wakeup_isr(void)
239 ao_radio_mcu_wake = 1;
240 ao_wakeup(&ao_radio_wake);
245 ao_radio_check_marc_status(void)
247 ao_radio_mcu_wake = 0;
248 ao_radio_marc_status = ao_radio_get_marc_status();
250 /* Anyt other than 'tx/rx finished' means an error occurred */
251 if (ao_radio_marc_status & ~(CC1120_MARC_STATUS1_TX_FINISHED|CC1120_MARC_STATUS1_RX_FINISHED))
253 if (ao_radio_marc_status & (CC1120_MARC_STATUS1_TX_FINISHED))
254 ao_radio_tx_finished = 1;
260 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
262 ao_wakeup(&ao_radio_wake);
266 ao_radio_enable_isr(void)
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);
273 ao_radio_start_tx(void)
275 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr);
276 ao_radio_tx_finished = 0;
277 ao_radio_strobe(CC1120_STX);
284 uint8_t state = (ao_radio_strobe(CC1120_SIDLE) >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK;
285 if (state == CC1120_STATUS_STATE_IDLE)
287 if (state == CC1120_STATUS_STATE_TX_FIFO_ERROR)
288 ao_radio_strobe(CC1120_SFTX);
289 if (state == CC1120_STATUS_STATE_RX_FIFO_ERROR)
290 ao_radio_strobe(CC1120_SFRX);
292 /* Flush any pending TX bytes */
293 ao_radio_strobe(CC1120_SFTX);
299 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
301 * Deviation for 38400 baud should be 20.5kHz:
303 * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz
305 * Deviation for 9600 baud should be 5.125kHz:
307 * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 3) = 5127Hz
309 * Deviation for 2400 baud should be 1.28125kHz, but cc1111 and
310 * cc115l can't do that, so we'll use 1.5kHz instead:
312 * 32e6Hz / (2 ** 24) * (256 + 137) * (2 ** 1) = 1499Hz
315 #define PACKET_DEV_M_384 80
316 #define PACKET_DEV_E_384 5
318 #define PACKET_DEV_M_96 80
319 #define PACKET_DEV_E_96 3
321 #define PACKET_DEV_M_24 137
322 #define PACKET_DEV_E_24 1
325 * For our packet data
327 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
328 * Rdata = -------------------------------------- * fosc
331 * Given the bit period of the baseband, T, the bandwidth of the
332 * baseband signal is B = 1/(2T). The overall bandwidth of the
333 * modulated signal is then Channel bandwidth = 2Δf + 2B.
335 * 38400 -- 2 * 20500 + 38400 = 79.4 kHz
336 * 9600 -- 2 * 5.125 + 9600 = 19.9 kHz
337 * 2400 -- 2 * 1.5 + 2400 = 5.4 khz
339 * Symbol rate 38400 Baud:
341 * DATARATE_M = 239914
343 * CHANBW = 79.4 (round to 100)
345 * Symbol rate 9600 Baud:
347 * DATARATE_M = 239914
349 * CHANBW = 19.9 (round to 20)
351 * Symbol rate 2400 Baud:
353 * DATARATE_M = 239914
355 * CHANBW = 5.0 (round to 8.0)
358 #define PACKET_DRATE_M 239914
360 #define PACKET_DRATE_E_384 9
363 #define PACKET_CHAN_BW_384 ((0 << CC1120_CHAN_BW_CHFILT_BYPASS) | \
364 (CC1120_CHAN_BW_ADC_CIC_DECFACT_20 << CC1120_CHAN_BW_ADC_CIC_DECFACT) | \
365 (2 << CC1120_CHAN_BW_BB_CIC_DECFACT))
367 #define PACKET_DRATE_E_96 7
369 #define PACKET_CHAN_BW_96 ((0 << CC1120_CHAN_BW_CHFILT_BYPASS) | \
370 (CC1120_CHAN_BW_ADC_CIC_DECFACT_20 << CC1120_CHAN_BW_ADC_CIC_DECFACT) | \
371 (10 << CC1120_CHAN_BW_BB_CIC_DECFACT))
373 #define PACKET_DRATE_E_24 5
375 #define PACKET_CHAN_BW_24 ((0 << CC1120_CHAN_BW_CHFILT_BYPASS) | \
376 (CC1120_CHAN_BW_ADC_CIC_DECFACT_20 << CC1120_CHAN_BW_ADC_CIC_DECFACT) | \
377 (25 << CC1120_CHAN_BW_BB_CIC_DECFACT))
379 static const uint16_t packet_setup[] = {
380 CC1120_DRATE1, ((PACKET_DRATE_M >> 8) & 0xff),
381 CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff),
382 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
383 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
384 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
385 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
386 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
387 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
388 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
389 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
390 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
391 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
392 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
393 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
394 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
395 AO_CC1120_MARC_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP,
398 static const uint16_t packet_setup_384[] = {
399 CC1120_DEVIATION_M, PACKET_DEV_M_384,
400 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
401 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
402 (PACKET_DEV_E_384 << CC1120_MODCFG_DEV_E_DEV_E)),
403 CC1120_DRATE2, ((PACKET_DRATE_E_384 << CC1120_DRATE2_DATARATE_E) |
404 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
405 CC1120_CHAN_BW, PACKET_CHAN_BW_384,
406 CC1120_PA_CFG0, 0x7b,
409 static const uint16_t packet_setup_96[] = {
410 CC1120_DEVIATION_M, PACKET_DEV_M_96,
411 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
412 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
413 (PACKET_DEV_E_96 << CC1120_MODCFG_DEV_E_DEV_E)),
414 CC1120_DRATE2, ((PACKET_DRATE_E_96 << CC1120_DRATE2_DATARATE_E) |
415 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
416 CC1120_CHAN_BW, PACKET_CHAN_BW_96,
417 CC1120_PA_CFG0, 0x7d,
420 static const uint16_t packet_setup_24[] = {
421 CC1120_DEVIATION_M, PACKET_DEV_M_24,
422 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
423 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
424 (PACKET_DEV_E_24 << CC1120_MODCFG_DEV_E_DEV_E)),
425 CC1120_DRATE2, ((PACKET_DRATE_E_24 << CC1120_DRATE2_DATARATE_E) |
426 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
427 CC1120_CHAN_BW, PACKET_CHAN_BW_24,
428 CC1120_PA_CFG0, 0x7e,
431 #define AO_CC1120_TX_BUFFER 64
433 static const uint16_t packet_tx_setup[] = {
434 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
435 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
436 CC1120_FIFO_CFG, ((0 << CC1120_FIFO_CFG_CRC_AUTOFLUSH) |
437 (AO_CC1120_TX_BUFFER << CC1120_FIFO_CFG_FIFO_THR)),
440 static const uint16_t packet_rx_setup[] = {
441 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
442 (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT)),
443 AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT,
447 * RDF deviation is 5kHz
449 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
451 * 32e6Hz / (2 ** 24) * (256 + 71) * (2 ** 3) = 4989
456 #define RDF_PACKET_LEN 50
459 * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
461 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
462 * Rdata = -------------------------------------- * fosc
468 * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
470 #define RDF_DRATE_E 5
471 #define RDF_DRATE_M 25166
472 #define RDF_PACKET_LEN 50
474 static const uint16_t rdf_setup[] = {
475 CC1120_DEVIATION_M, RDF_DEV_M,
476 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
477 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
478 (RDF_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
479 CC1120_DRATE2, ((RDF_DRATE_E << CC1120_DRATE2_DATARATE_E) |
480 (((RDF_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
481 CC1120_DRATE1, ((RDF_DRATE_M >> 8) & 0xff),
482 CC1120_DRATE0, ((RDF_DRATE_M >> 0) & 0xff),
483 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
484 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
485 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
486 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
487 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
488 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
489 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
490 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
491 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
492 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
493 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
494 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
495 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
496 CC1120_PA_CFG0, 0x7e,
500 * APRS deviation is 3kHz
502 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
504 * 32e6Hz / (2 ** 24) * (256 + 137) * (2 ** 2) = 2998Hz
508 #define APRS_DEV_M 137
511 * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate)
513 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
514 * Rdata = -------------------------------------- * fosc
517 * DATARATE_M = 239914
520 * Rdata = 9599.998593330383301
523 #define APRS_DRATE_E 7
524 #define APRS_DRATE_M 239914
526 static const uint16_t aprs_setup[] = {
527 CC1120_DEVIATION_M, APRS_DEV_M,
528 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
529 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
530 (APRS_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
531 CC1120_DRATE2, ((APRS_DRATE_E << CC1120_DRATE2_DATARATE_E) |
532 (((APRS_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
533 CC1120_DRATE1, ((APRS_DRATE_M >> 8) & 0xff),
534 CC1120_DRATE0, ((APRS_DRATE_M >> 0) & 0xff),
535 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
536 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
537 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
538 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
539 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
540 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
541 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
542 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
543 CC1120_PA_CFG0, 0x7d,
544 CC1120_FIFO_CFG, ((0 << CC1120_FIFO_CFG_CRC_AUTOFLUSH) |
545 (AO_CC1120_TX_BUFFER << CC1120_FIFO_CFG_FIFO_THR)),
549 * For Test mode, we want an unmodulated carrier. To do that, we
550 * set the deviation to zero and enable a preamble so that the radio
551 * turns on before we send any data
554 static const uint16_t test_setup[] = {
555 CC1120_DEVIATION_M, 0,
556 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
557 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
558 (0 << CC1120_MODCFG_DEV_E_DEV_E)),
559 CC1120_DRATE2, ((APRS_DRATE_E << CC1120_DRATE2_DATARATE_E) |
560 (((APRS_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
561 CC1120_DRATE1, ((APRS_DRATE_M >> 8) & 0xff),
562 CC1120_DRATE0, ((APRS_DRATE_M >> 0) & 0xff),
563 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
564 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
565 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
566 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
567 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
568 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
569 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
570 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
573 #define AO_PKT_CFG0_INFINITE ((0 << CC1120_PKT_CFG0_RESERVED7) | \
574 (CC1120_PKT_CFG0_LENGTH_CONFIG_INFINITE << CC1120_PKT_CFG0_LENGTH_CONFIG) | \
575 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | \
576 (0 << CC1120_PKT_CFG0_UART_MODE_EN) | \
577 (0 << CC1120_PKT_CFG0_UART_SWAP_EN))
579 #define AO_PKT_CFG0_FIXED ((0 << CC1120_PKT_CFG0_RESERVED7) | \
580 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) | \
581 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | \
582 (0 << CC1120_PKT_CFG0_UART_MODE_EN) | \
583 (0 << CC1120_PKT_CFG0_UART_SWAP_EN))
585 static uint16_t ao_radio_mode;
587 #define AO_RADIO_MODE_BITS_PACKET 1
588 #define AO_RADIO_MODE_BITS_PACKET_TX 2
589 #define AO_RADIO_MODE_BITS_TX_BUF 4
590 #define AO_RADIO_MODE_BITS_TX_FINISH 8
591 #define AO_RADIO_MODE_BITS_PACKET_RX 16
592 #define AO_RADIO_MODE_BITS_RDF 32
593 #define AO_RADIO_MODE_BITS_APRS 64
594 #define AO_RADIO_MODE_BITS_TEST 128
595 #define AO_RADIO_MODE_BITS_INFINITE 256
596 #define AO_RADIO_MODE_BITS_FIXED 512
598 #define AO_RADIO_MODE_NONE 0
599 #define AO_RADIO_MODE_PACKET_TX_BUF (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_BUF)
600 #define AO_RADIO_MODE_PACKET_TX_FINISH (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_FINISH)
601 #define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_RX)
602 #define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_TX_FINISH)
603 #define AO_RADIO_MODE_APRS_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
604 #define AO_RADIO_MODE_APRS_LAST_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_BUF)
605 #define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
606 #define AO_RADIO_MODE_TEST (AO_RADIO_MODE_BITS_TEST | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
609 _ao_radio_set_regs(const uint16_t *regs, int nreg)
613 for (i = 0; i < nreg; i++) {
614 ao_radio_reg_write(regs[0], regs[1]);
619 #define ao_radio_set_regs(setup) _ao_radio_set_regs(setup, (sizeof (setup) / sizeof(setup[0])) >> 1)
622 ao_radio_set_mode(uint16_t new_mode)
626 if (new_mode == ao_radio_mode)
629 changes = new_mode & (~ao_radio_mode);
631 if (changes & AO_RADIO_MODE_BITS_PACKET) {
632 ao_radio_set_regs(packet_setup);
634 switch (ao_config.radio_rate) {
636 case AO_RADIO_RATE_38400:
637 ao_radio_set_regs(packet_setup_384);
639 case AO_RADIO_RATE_9600:
640 ao_radio_set_regs(packet_setup_96);
642 case AO_RADIO_RATE_2400:
643 ao_radio_set_regs(packet_setup_24);
648 if (changes & AO_RADIO_MODE_BITS_PACKET_TX)
649 ao_radio_set_regs(packet_tx_setup);
651 if (changes & AO_RADIO_MODE_BITS_TX_BUF)
652 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_TXFIFO_THR);
654 if (changes & AO_RADIO_MODE_BITS_TX_FINISH)
655 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG);
657 if (changes & AO_RADIO_MODE_BITS_PACKET_RX)
658 ao_radio_set_regs(packet_rx_setup);
660 if (changes & AO_RADIO_MODE_BITS_RDF)
661 ao_radio_set_regs(rdf_setup);
663 if (changes & AO_RADIO_MODE_BITS_APRS)
664 ao_radio_set_regs(aprs_setup);
666 if (changes & AO_RADIO_MODE_BITS_TEST)
667 ao_radio_set_regs(test_setup);
669 if (changes & AO_RADIO_MODE_BITS_INFINITE)
670 ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_INFINITE);
672 if (changes & AO_RADIO_MODE_BITS_FIXED)
673 ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_FIXED);
675 ao_radio_mode = new_mode;
678 static const uint16_t radio_setup[] = {
679 #include "ao_cc1120_CC1120.h"
682 static uint8_t ao_radio_configured = 0;
687 ao_radio_strobe(CC1120_SRES);
689 ao_radio_set_regs(radio_setup);
695 ao_radio_configured = 1;
699 ao_radio_set_len(uint8_t len)
701 static uint8_t last_len;
703 if (len != last_len) {
704 ao_radio_reg_write(CC1120_PKT_LEN, len);
710 ao_radio_get(uint8_t len)
712 static uint32_t last_radio_setting;
713 static uint8_t last_radio_rate;
715 ao_mutex_get(&ao_radio_mutex);
717 if (!ao_radio_configured)
719 if (ao_config.radio_setting != last_radio_setting) {
720 ao_radio_reg_write(CC1120_FREQ2, ao_config.radio_setting >> 16);
721 ao_radio_reg_write(CC1120_FREQ1, ao_config.radio_setting >> 8);
722 ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting);
723 last_radio_setting = ao_config.radio_setting;
725 if (ao_config.radio_rate != last_radio_rate) {
726 ao_radio_mode &= ~AO_RADIO_MODE_BITS_PACKET;
727 last_radio_rate = ao_config.radio_rate;
729 ao_radio_set_len(len);
732 #define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
735 ao_rdf_start(uint8_t len)
740 ao_radio_set_mode(AO_RADIO_MODE_RDF);
750 ao_arch_block_interrupts();
751 while (!ao_radio_wake && !ao_radio_abort && !ao_radio_mcu_wake) {
752 ao_radio_enable_isr();
753 ao_sleep(&ao_radio_wake);
755 ao_arch_release_interrupts();
756 if (ao_radio_mcu_wake)
757 ao_radio_check_marc_status();
766 ao_rdf_start(AO_RADIO_RDF_LEN);
768 ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN);
774 ao_radio_continuity(uint8_t c)
779 ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN);
781 status = ao_radio_fifo_write_start();
782 for (i = 0; i < 3; i++) {
783 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
785 ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN);
787 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN);
789 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
790 status = ao_radio_fifo_write_stop(status);
796 ao_radio_rdf_abort(void)
799 ao_wakeup(&ao_radio_wake);
803 ao_radio_test_cmd(void)
806 static uint8_t radio_on;
808 if (ao_cmd_lex_c != '\n') {
810 mode = (uint8_t) ao_cmd_lex_u32;
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(uint16_t 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(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, 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(__xdata void *d, uint8_t size, uint8_t 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 += 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 = 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 ao_packet_slave_stop();
1457 static const struct ao_cmds ao_radio_cmds[] = {
1458 { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
1461 { ao_radio_aprs, "G\0Send APRS packet" },
1463 { ao_radio_show, "R\0Show CC1120 status" },
1464 { ao_radio_beep, "b\0Emit an RDF beacon" },
1465 { ao_radio_packet, "p\0Send a test packet" },
1466 { ao_radio_test_recv, "q\0Recv a test packet" },
1474 ao_radio_configured = 0;
1475 ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN));
1478 AO_CC1120_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN));
1479 for (i = 0; i < 10000; i++) {
1480 if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0)
1483 AO_CC1120_SPI_CS_PORT->bsrr = (1 << AO_CC1120_SPI_CS_PIN);
1485 ao_panic(AO_PANIC_SELF_TEST_CC1120);
1488 /* Enable the EXTI interrupt for the appropriate pin */
1489 ao_enable_port(AO_CC1120_INT_PORT);
1490 ao_exti_setup(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1491 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
1494 /* Enable the hacked up GPIO3 pin */
1495 ao_enable_port(AO_CC1120_MCU_WAKEUP_PORT);
1496 ao_exti_setup(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN,
1497 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED,
1498 ao_radio_mcu_wakeup_isr);
1500 ao_cmd_register(&ao_radio_cmds[0]);