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 void ao_radio_fifo_write_stop(void) {
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 ao_radio_fifo_write_stop();
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 ao_radio_fifo_write_stop();
209 ao_radio_int_pin(void)
211 return ao_gpio_get(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_CC1120_INT);
216 ao_radio_status(void)
218 return ao_radio_strobe (CC1120_SNOP);
223 ao_radio_recv_abort(void)
226 ao_wakeup(&ao_radio_wake);
229 #define ao_radio_rdf_value 0x55
232 ao_radio_get_marc_status(void)
234 return ao_radio_reg_read(CC1120_MARC_STATUS1);
238 ao_radio_mcu_wakeup_isr(void)
240 ao_radio_mcu_wake = 1;
241 ao_wakeup(&ao_radio_wake);
246 ao_radio_check_marc_status(void)
248 ao_radio_mcu_wake = 0;
249 ao_radio_marc_status = ao_radio_get_marc_status();
251 /* Anyt other than 'tx/rx finished' means an error occurred */
252 if (ao_radio_marc_status & ~(CC1120_MARC_STATUS1_TX_FINISHED|CC1120_MARC_STATUS1_RX_FINISHED))
254 if (ao_radio_marc_status & (CC1120_MARC_STATUS1_TX_FINISHED))
255 ao_radio_tx_finished = 1;
261 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
263 ao_wakeup(&ao_radio_wake);
267 ao_radio_enable_isr(void)
269 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
270 ao_exti_enable(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN);
274 ao_radio_start_tx(void)
276 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr);
277 ao_radio_tx_finished = 0;
278 ao_radio_strobe(CC1120_STX);
285 uint8_t state = (ao_radio_strobe(CC1120_SIDLE) >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK;
286 if (state == CC1120_STATUS_STATE_IDLE)
288 if (state == CC1120_STATUS_STATE_TX_FIFO_ERROR)
289 ao_radio_strobe(CC1120_SFTX);
290 if (state == CC1120_STATUS_STATE_RX_FIFO_ERROR)
291 ao_radio_strobe(CC1120_SFRX);
293 /* Flush any pending TX bytes */
294 ao_radio_strobe(CC1120_SFTX);
300 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
302 * Deviation for 38400 baud should be 20.5kHz:
304 * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz
306 * Deviation for 9600 baud should be 5.125kHz:
308 * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 3) = 5127Hz
310 * Deviation for 2400 baud should be 1.28125kHz, but cc1111 and
311 * cc115l can't do that, so we'll use 1.5kHz instead:
313 * 32e6Hz / (2 ** 24) * (256 + 137) * (2 ** 1) = 1499Hz
316 #define PACKET_DEV_M_384 80
317 #define PACKET_DEV_E_384 5
319 #define PACKET_DEV_M_96 80
320 #define PACKET_DEV_E_96 3
322 #define PACKET_DEV_M_24 137
323 #define PACKET_DEV_E_24 1
326 * For our packet data
328 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
329 * Rdata = -------------------------------------- * fosc
332 * Given the bit period of the baseband, T, the bandwidth of the
333 * baseband signal is B = 1/(2T). The overall bandwidth of the
334 * modulated signal is then Channel bandwidth = 2Δf + 2B.
336 * 38400 -- 2 * 20500 + 38400 = 79.4 kHz
337 * 9600 -- 2 * 5.125 + 9600 = 19.9 kHz
338 * 2400 -- 2 * 1.5 + 2400 = 5.4 khz
340 * Symbol rate 38400 Baud:
342 * DATARATE_M = 239914
344 * CHANBW = 79.4 (round to 100)
346 * Symbol rate 9600 Baud:
348 * DATARATE_M = 239914
350 * CHANBW = 19.9 (round to 20)
352 * Symbol rate 2400 Baud:
354 * DATARATE_M = 239914
356 * CHANBW = 5.0 (round to 8.0)
359 #define PACKET_DRATE_M 239914
361 #define PACKET_DRATE_E_384 9
364 #define PACKET_CHAN_BW_384 ((0 << CC1120_CHAN_BW_CHFILT_BYPASS) | \
365 (CC1120_CHAN_BW_ADC_CIC_DECFACT_20 << CC1120_CHAN_BW_ADC_CIC_DECFACT) | \
366 (2 << CC1120_CHAN_BW_BB_CIC_DECFACT))
368 #define PACKET_DRATE_E_96 7
370 #define PACKET_CHAN_BW_96 ((0 << CC1120_CHAN_BW_CHFILT_BYPASS) | \
371 (CC1120_CHAN_BW_ADC_CIC_DECFACT_20 << CC1120_CHAN_BW_ADC_CIC_DECFACT) | \
372 (10 << CC1120_CHAN_BW_BB_CIC_DECFACT))
374 #define PACKET_DRATE_E_24 5
376 #define PACKET_CHAN_BW_24 ((0 << CC1120_CHAN_BW_CHFILT_BYPASS) | \
377 (CC1120_CHAN_BW_ADC_CIC_DECFACT_20 << CC1120_CHAN_BW_ADC_CIC_DECFACT) | \
378 (25 << CC1120_CHAN_BW_BB_CIC_DECFACT))
380 static const uint16_t packet_setup[] = {
381 CC1120_DRATE1, ((PACKET_DRATE_M >> 8) & 0xff),
382 CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff),
383 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
384 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
385 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
386 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
387 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
388 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
389 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
390 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
391 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
392 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
393 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
394 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
395 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
396 AO_CC1120_MARC_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP,
399 static const uint16_t packet_setup_384[] = {
400 CC1120_DEVIATION_M, PACKET_DEV_M_384,
401 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
402 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
403 (PACKET_DEV_E_384 << CC1120_MODCFG_DEV_E_DEV_E)),
404 CC1120_DRATE2, ((PACKET_DRATE_E_384 << CC1120_DRATE2_DATARATE_E) |
405 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
406 CC1120_CHAN_BW, PACKET_CHAN_BW_384,
407 CC1120_PA_CFG0, 0x7b,
410 static const uint16_t packet_setup_96[] = {
411 CC1120_DEVIATION_M, PACKET_DEV_M_96,
412 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
413 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
414 (PACKET_DEV_E_96 << CC1120_MODCFG_DEV_E_DEV_E)),
415 CC1120_DRATE2, ((PACKET_DRATE_E_96 << CC1120_DRATE2_DATARATE_E) |
416 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
417 CC1120_CHAN_BW, PACKET_CHAN_BW_96,
418 CC1120_PA_CFG0, 0x7d,
421 static const uint16_t packet_setup_24[] = {
422 CC1120_DEVIATION_M, PACKET_DEV_M_24,
423 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
424 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
425 (PACKET_DEV_E_24 << CC1120_MODCFG_DEV_E_DEV_E)),
426 CC1120_DRATE2, ((PACKET_DRATE_E_24 << CC1120_DRATE2_DATARATE_E) |
427 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
428 CC1120_CHAN_BW, PACKET_CHAN_BW_24,
429 CC1120_PA_CFG0, 0x7e,
432 #define AO_CC1120_TX_BUFFER 64
434 static const uint16_t packet_tx_setup[] = {
435 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
436 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
437 CC1120_FIFO_CFG, ((0 << CC1120_FIFO_CFG_CRC_AUTOFLUSH) |
438 (AO_CC1120_TX_BUFFER << CC1120_FIFO_CFG_FIFO_THR)),
441 static const uint16_t packet_rx_setup[] = {
442 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
443 (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT)),
444 AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT,
448 * RDF deviation is 5kHz
450 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
452 * 32e6Hz / (2 ** 24) * (256 + 71) * (2 ** 3) = 4989
457 #define RDF_PACKET_LEN 50
460 * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
462 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
463 * Rdata = -------------------------------------- * fosc
469 * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
471 #define RDF_DRATE_E 5
472 #define RDF_DRATE_M 25166
473 #define RDF_PACKET_LEN 50
475 static const uint16_t rdf_setup[] = {
476 CC1120_DEVIATION_M, RDF_DEV_M,
477 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
478 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
479 (RDF_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
480 CC1120_DRATE2, ((RDF_DRATE_E << CC1120_DRATE2_DATARATE_E) |
481 (((RDF_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
482 CC1120_DRATE1, ((RDF_DRATE_M >> 8) & 0xff),
483 CC1120_DRATE0, ((RDF_DRATE_M >> 0) & 0xff),
484 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
485 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
486 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
487 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
488 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
489 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
490 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
491 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
492 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
493 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
494 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
495 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
496 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
497 CC1120_PA_CFG0, 0x7e,
501 * APRS deviation is 3kHz
503 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
505 * 32e6Hz / (2 ** 24) * (256 + 137) * (2 ** 2) = 2998Hz
509 #define APRS_DEV_M 137
512 * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate)
514 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
515 * Rdata = -------------------------------------- * fosc
518 * DATARATE_M = 239914
521 * Rdata = 9599.998593330383301
524 #define APRS_DRATE_E 7
525 #define APRS_DRATE_M 239914
527 static const uint16_t aprs_setup[] = {
528 CC1120_DEVIATION_M, APRS_DEV_M,
529 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
530 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
531 (APRS_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
532 CC1120_DRATE2, ((APRS_DRATE_E << CC1120_DRATE2_DATARATE_E) |
533 (((APRS_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
534 CC1120_DRATE1, ((APRS_DRATE_M >> 8) & 0xff),
535 CC1120_DRATE0, ((APRS_DRATE_M >> 0) & 0xff),
536 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
537 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
538 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
539 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
540 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
541 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
542 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
543 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
544 CC1120_PA_CFG0, 0x7d,
545 CC1120_FIFO_CFG, ((0 << CC1120_FIFO_CFG_CRC_AUTOFLUSH) |
546 (AO_CC1120_TX_BUFFER << CC1120_FIFO_CFG_FIFO_THR)),
550 * For Test mode, we want an unmodulated carrier. To do that, we
551 * set the deviation to zero and enable a preamble so that the radio
552 * turns on before we send any data
555 static const uint16_t test_setup[] = {
556 CC1120_DEVIATION_M, 0,
557 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
558 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
559 (0 << CC1120_MODCFG_DEV_E_DEV_E)),
560 CC1120_DRATE2, ((APRS_DRATE_E << CC1120_DRATE2_DATARATE_E) |
561 (((APRS_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
562 CC1120_DRATE1, ((APRS_DRATE_M >> 8) & 0xff),
563 CC1120_DRATE0, ((APRS_DRATE_M >> 0) & 0xff),
564 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
565 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
566 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
567 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
568 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
569 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
570 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
571 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
574 #define AO_PKT_CFG0_INFINITE ((0 << CC1120_PKT_CFG0_RESERVED7) | \
575 (CC1120_PKT_CFG0_LENGTH_CONFIG_INFINITE << CC1120_PKT_CFG0_LENGTH_CONFIG) | \
576 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | \
577 (0 << CC1120_PKT_CFG0_UART_MODE_EN) | \
578 (0 << CC1120_PKT_CFG0_UART_SWAP_EN))
580 #define AO_PKT_CFG0_FIXED ((0 << CC1120_PKT_CFG0_RESERVED7) | \
581 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) | \
582 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | \
583 (0 << CC1120_PKT_CFG0_UART_MODE_EN) | \
584 (0 << CC1120_PKT_CFG0_UART_SWAP_EN))
586 static uint16_t ao_radio_mode;
588 #define AO_RADIO_MODE_BITS_PACKET 1
589 #define AO_RADIO_MODE_BITS_PACKET_TX 2
590 #define AO_RADIO_MODE_BITS_TX_BUF 4
591 #define AO_RADIO_MODE_BITS_TX_FINISH 8
592 #define AO_RADIO_MODE_BITS_PACKET_RX 16
593 #define AO_RADIO_MODE_BITS_RDF 32
594 #define AO_RADIO_MODE_BITS_APRS 64
595 #define AO_RADIO_MODE_BITS_TEST 128
596 #define AO_RADIO_MODE_BITS_INFINITE 256
597 #define AO_RADIO_MODE_BITS_FIXED 512
599 #define AO_RADIO_MODE_NONE 0
600 #define AO_RADIO_MODE_PACKET_TX_BUF (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_BUF)
601 #define AO_RADIO_MODE_PACKET_TX_FINISH (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_FINISH)
602 #define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_RX)
603 #define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_TX_FINISH)
604 #define AO_RADIO_MODE_APRS_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
605 #define AO_RADIO_MODE_APRS_LAST_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_BUF)
606 #define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
607 #define AO_RADIO_MODE_TEST (AO_RADIO_MODE_BITS_TEST | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
610 _ao_radio_set_regs(const uint16_t *regs, int nreg)
614 for (i = 0; i < nreg; i++) {
615 ao_radio_reg_write(regs[0], regs[1]);
620 #define ao_radio_set_regs(setup) _ao_radio_set_regs(setup, (sizeof (setup) / sizeof(setup[0])) >> 1)
623 ao_radio_set_mode(uint16_t new_mode)
627 if (new_mode == ao_radio_mode)
630 changes = new_mode & (~ao_radio_mode);
632 if (changes & AO_RADIO_MODE_BITS_PACKET) {
633 ao_radio_set_regs(packet_setup);
635 switch (ao_config.radio_rate) {
637 case AO_RADIO_RATE_38400:
638 ao_radio_set_regs(packet_setup_384);
640 case AO_RADIO_RATE_9600:
641 ao_radio_set_regs(packet_setup_96);
643 case AO_RADIO_RATE_2400:
644 ao_radio_set_regs(packet_setup_24);
649 if (changes & AO_RADIO_MODE_BITS_PACKET_TX)
650 ao_radio_set_regs(packet_tx_setup);
652 if (changes & AO_RADIO_MODE_BITS_TX_BUF)
653 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_TXFIFO_THR);
655 if (changes & AO_RADIO_MODE_BITS_TX_FINISH)
656 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG);
658 if (changes & AO_RADIO_MODE_BITS_PACKET_RX)
659 ao_radio_set_regs(packet_rx_setup);
661 if (changes & AO_RADIO_MODE_BITS_RDF)
662 ao_radio_set_regs(rdf_setup);
664 if (changes & AO_RADIO_MODE_BITS_APRS)
665 ao_radio_set_regs(aprs_setup);
667 if (changes & AO_RADIO_MODE_BITS_TEST)
668 ao_radio_set_regs(test_setup);
670 if (changes & AO_RADIO_MODE_BITS_INFINITE)
671 ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_INFINITE);
673 if (changes & AO_RADIO_MODE_BITS_FIXED)
674 ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_FIXED);
676 ao_radio_mode = new_mode;
679 static const uint16_t radio_setup[] = {
680 #include "ao_cc1120_CC1120.h"
683 static uint8_t ao_radio_configured = 0;
688 ao_radio_strobe(CC1120_SRES);
690 ao_radio_set_regs(radio_setup);
696 ao_radio_configured = 1;
700 ao_radio_set_len(uint8_t len)
702 static uint8_t last_len;
704 if (len != last_len) {
705 ao_radio_reg_write(CC1120_PKT_LEN, len);
711 ao_radio_get(uint8_t len)
713 static uint32_t last_radio_setting;
714 static uint8_t last_radio_rate;
716 ao_mutex_get(&ao_radio_mutex);
718 if (!ao_radio_configured)
720 if (ao_config.radio_setting != last_radio_setting) {
721 ao_radio_reg_write(CC1120_FREQ2, ao_config.radio_setting >> 16);
722 ao_radio_reg_write(CC1120_FREQ1, ao_config.radio_setting >> 8);
723 ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting);
724 last_radio_setting = ao_config.radio_setting;
726 if (ao_config.radio_rate != last_radio_rate) {
727 ao_radio_mode &= ~AO_RADIO_MODE_BITS_PACKET;
728 last_radio_rate = ao_config.radio_rate;
730 ao_radio_set_len(len);
733 #define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
736 ao_rdf_start(uint8_t len)
741 ao_radio_set_mode(AO_RADIO_MODE_RDF);
751 ao_arch_block_interrupts();
752 while (!ao_radio_wake && !ao_radio_abort && !ao_radio_mcu_wake) {
753 ao_radio_enable_isr();
754 ao_sleep(&ao_radio_wake);
756 ao_arch_release_interrupts();
757 if (ao_radio_mcu_wake)
758 ao_radio_check_marc_status();
767 ao_rdf_start(AO_RADIO_RDF_LEN);
769 ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN);
775 ao_radio_continuity(uint8_t c)
779 ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN);
781 (void) 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 ao_radio_fifo_write_stop();
795 ao_radio_rdf_abort(void)
798 ao_wakeup(&ao_radio_wake);
802 ao_radio_test_cmd(void)
805 static uint8_t radio_on;
807 if (ao_cmd_lex_c != '\n') {
809 mode = (uint8_t) ao_cmd_lex_u32;
812 if ((mode & 2) && !radio_on) {
814 ao_monitor_disable();
817 ao_packet_slave_stop();
820 ao_radio_set_mode(AO_RADIO_MODE_TEST);
821 ao_radio_strobe(CC1120_STX);
824 for (t = 0; t < 10; t++) {
825 printf ("status: %02x\n", ao_radio_status());
826 ao_delay(AO_MS_TO_TICKS(100));
833 printf ("Hit a character to stop..."); flush();
837 if ((mode & 1) && radio_on) {
848 ao_radio_wait_isr(uint16_t timeout)
850 ao_arch_block_interrupts();
851 while (!ao_radio_wake && !ao_radio_mcu_wake && !ao_radio_abort)
852 if (ao_sleep_for(&ao_radio_wake, timeout))
854 ao_arch_release_interrupts();
855 if (ao_radio_mcu_wake)
856 ao_radio_check_marc_status();
860 ao_radio_wait_fifo(void)
862 while (ao_radio_int_pin() != 0 && !ao_radio_abort) {
864 ao_radio_enable_isr();
865 ao_radio_wait_isr(0);
869 static uint8_t tx_data[(AO_RADIO_MAX_SEND + 4) * 2];
872 ao_radio_send(const void *d, uint8_t size)
874 uint8_t *e = tx_data;
879 encode_len = ao_fec_encode(d, size, tx_data);
881 ao_radio_get(encode_len);
885 /* Flush any pending TX bytes */
886 ao_radio_strobe(CC1120_SFTX);
889 this_len = encode_len;
892 ao_radio_wait_fifo();
897 if (this_len > AO_CC1120_TX_BUFFER) {
898 this_len = AO_CC1120_TX_BUFFER;
899 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_BUF);
901 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_FINISH);
904 ao_radio_fifo_write(e, this_len);
906 encode_len -= this_len;
913 while (started && !ao_radio_abort && !ao_radio_tx_finished) {
915 ao_radio_enable_isr();
916 ao_radio_wait_isr(0);
924 ao_radio_send_aprs(ao_radio_fill_func fill)
926 uint8_t buf[AO_CC1120_TX_BUFFER];
936 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr);
938 cnt = (*fill)(buf, sizeof(buf));
945 /* Wait for some space in the fifo */
947 ao_radio_wait_fifo();
953 ao_radio_set_len(total & 0xff);
954 ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
956 ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
958 ao_radio_fifo_write(buf, cnt);
965 /* Wait for the transmitter to go idle */
966 while (started && ao_radio_int_pin() != 0 && !ao_radio_abort) {
968 ao_radio_enable_isr();
969 ao_radio_wait_isr(0);
976 static uint8_t rx_data[(AO_RADIO_MAX_RECV + 4) * 2 * 8];
977 static uint16_t rx_data_count;
978 static uint16_t rx_data_consumed;
979 static uint16_t rx_data_cur;
980 static uint8_t rx_ignore;
981 static uint8_t rx_waiting;
982 static uint8_t rx_starting;
983 static uint8_t rx_task_id;
984 static uint32_t rx_fast_start;
985 static uint32_t rx_slow_start;
986 static uint32_t rx_missed;
989 static uint32_t rx_start_tick, rx_packet_tick, rx_done_tick, rx_last_done_tick;
991 uint32_t ao_rx_start_tick, ao_rx_packet_tick, ao_rx_done_tick, ao_rx_last_done_tick;
993 #include <ao_profile.h>
997 ao_radio_rx_isr(void)
1004 if (ao_radio_try_select(rx_task_id)) {
1007 _ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
1020 ao_wakeup(&ao_radio_wake);
1022 d = ao_radio_spi_recv_byte();
1023 if (rx_ignore == 0) {
1024 if (rx_data_cur < rx_data_count)
1025 rx_data[rx_data_cur++] = d;
1026 if (rx_data_cur >= rx_data_count) {
1027 ao_spi_clr_cs(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN));
1028 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
1030 if (rx_waiting && rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) {
1032 if (!rx_packet_tick)
1033 rx_packet_tick = ao_profile_tick();
1034 if (rx_data_cur < rx_data_count)
1038 ao_wakeup(&ao_radio_wake);
1046 ao_radio_rx_wait(void)
1048 ao_arch_block_interrupts();
1050 while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&
1054 if (ao_sleep_for(&ao_radio_wake, AO_MS_TO_TICKS(100)))
1058 ao_arch_release_interrupts();
1059 if (ao_radio_abort || ao_radio_mcu_wake)
1061 rx_data_consumed += AO_FEC_DECODE_BLOCK;
1063 return rx_data_cur - rx_data_consumed;
1065 return AO_FEC_DECODE_BLOCK;
1069 ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout)
1072 uint8_t radio_rssi = 0;
1076 size -= 2; /* status bytes */
1077 if (size > AO_RADIO_MAX_RECV) {
1078 ao_delay(AO_SEC_TO_TICKS(1));
1082 rx_start_tick = ao_profile_tick();
1085 len = size + 2; /* CRC bytes */
1086 len += 1 + ~(len & 1); /* 1 or two pad bytes */
1087 len *= 2; /* 1/2 rate convolution */
1088 rx_data_count = len * 8; /* bytes to bits */
1090 rx_data_consumed = 0;
1093 /* Must be set before changing the frequency; any abort
1094 * after the frequency is set needs to terminate the read
1095 * so that the registers can be reprogrammed
1102 ao_radio_mcu_wake = 0;
1104 ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
1106 /* configure interrupt pin */
1107 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT);
1108 ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1109 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
1112 rx_task_id = ao_cur_task->task_id;
1114 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
1115 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
1117 ao_radio_strobe(CC1120_SRX);
1119 ao_arch_block_interrupts();
1120 while (rx_starting && !ao_radio_abort) {
1121 if (ao_sleep_for(&ao_radio_wake, timeout))
1124 uint8_t rx_task_id_save = rx_task_id;
1127 ao_arch_release_interrupts();
1129 if (ao_radio_abort) {
1130 if (rx_task_id_save == 0)
1131 ao_radio_burst_read_stop();
1136 if (rx_task_id_save) {
1139 _ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
1141 (void) ao_radio_spi_recv_byte();
1146 ret = ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait);
1148 ao_radio_burst_read_stop();
1150 if (ao_radio_mcu_wake)
1151 ao_radio_check_marc_status();
1156 /* Convert from 'real' rssi to cc1111-style values */
1158 rssi0 = ao_radio_reg_read(CC1120_RSSI0);
1160 int8_t rssi = ao_radio_reg_read(CC1120_RSSI1);
1161 ao_radio_rssi = rssi;
1163 /* Bound it to the representable range */
1166 radio_rssi = AO_RADIO_FROM_RSSI (rssi);
1173 /* Store the received RSSI value; the crc-OK byte is already done */
1175 ((uint8_t *) d)[size] = radio_rssi;
1178 rx_last_done_tick = rx_done_tick;
1179 rx_done_tick = ao_profile_tick();
1181 ao_rx_start_tick = rx_start_tick;
1182 ao_rx_packet_tick = rx_packet_tick;
1183 ao_rx_done_tick = rx_done_tick;
1184 ao_rx_last_done_tick = rx_last_done_tick;
1192 static char *cc1120_state_name[] = {
1193 [CC1120_STATUS_STATE_IDLE] = "IDLE",
1194 [CC1120_STATUS_STATE_RX] = "RX",
1195 [CC1120_STATUS_STATE_TX] = "TX",
1196 [CC1120_STATUS_STATE_FSTXON] = "FSTXON",
1197 [CC1120_STATUS_STATE_CALIBRATE] = "CALIBRATE",
1198 [CC1120_STATUS_STATE_SETTLING] = "SETTLING",
1199 [CC1120_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
1200 [CC1120_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
1203 struct ao_cc1120_reg {
1208 static const struct ao_cc1120_reg ao_cc1120_reg[] = {
1209 { .addr = CC1120_IOCFG3, .name = "IOCFG3" },
1210 { .addr = CC1120_IOCFG2, .name = "IOCFG2" },
1211 { .addr = CC1120_IOCFG1, .name = "IOCFG1" },
1212 { .addr = CC1120_IOCFG0, .name = "IOCFG0" },
1213 { .addr = CC1120_SYNC3, .name = "SYNC3" },
1214 { .addr = CC1120_SYNC2, .name = "SYNC2" },
1215 { .addr = CC1120_SYNC1, .name = "SYNC1" },
1216 { .addr = CC1120_SYNC0, .name = "SYNC0" },
1217 { .addr = CC1120_SYNC_CFG1, .name = "SYNC_CFG1" },
1218 { .addr = CC1120_SYNC_CFG0, .name = "SYNC_CFG0" },
1219 { .addr = CC1120_DEVIATION_M, .name = "DEVIATION_M" },
1220 { .addr = CC1120_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
1221 { .addr = CC1120_DCFILT_CFG, .name = "DCFILT_CFG" },
1222 { .addr = CC1120_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
1223 { .addr = CC1120_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
1224 { .addr = CC1120_FREQ_IF_CFG, .name = "FREQ_IF_CFG" },
1225 { .addr = CC1120_IQIC, .name = "IQIC" },
1226 { .addr = CC1120_CHAN_BW, .name = "CHAN_BW" },
1227 { .addr = CC1120_MDMCFG1, .name = "MDMCFG1" },
1228 { .addr = CC1120_MDMCFG0, .name = "MDMCFG0" },
1229 { .addr = CC1120_DRATE2, .name = "DRATE2" },
1230 { .addr = CC1120_DRATE1, .name = "DRATE1" },
1231 { .addr = CC1120_DRATE0, .name = "DRATE0" },
1232 { .addr = CC1120_AGC_REF, .name = "AGC_REF" },
1233 { .addr = CC1120_AGC_CS_THR, .name = "AGC_CS_THR" },
1234 { .addr = CC1120_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
1235 { .addr = CC1120_AGC_CFG3, .name = "AGC_CFG3" },
1236 { .addr = CC1120_AGC_CFG2, .name = "AGC_CFG2" },
1237 { .addr = CC1120_AGC_CFG1, .name = "AGC_CFG1" },
1238 { .addr = CC1120_AGC_CFG0, .name = "AGC_CFG0" },
1239 { .addr = CC1120_FIFO_CFG, .name = "FIFO_CFG" },
1240 { .addr = CC1120_DEV_ADDR, .name = "DEV_ADDR" },
1241 { .addr = CC1120_SETTLING_CFG, .name = "SETTLING_CFG" },
1242 { .addr = CC1120_FS_CFG, .name = "FS_CFG" },
1243 { .addr = CC1120_WOR_CFG1, .name = "WOR_CFG1" },
1244 { .addr = CC1120_WOR_CFG0, .name = "WOR_CFG0" },
1245 { .addr = CC1120_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
1246 { .addr = CC1120_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
1247 { .addr = CC1120_PKT_CFG2, .name = "PKT_CFG2" },
1248 { .addr = CC1120_PKT_CFG1, .name = "PKT_CFG1" },
1249 { .addr = CC1120_PKT_CFG0, .name = "PKT_CFG0" },
1250 { .addr = CC1120_RFEND_CFG1, .name = "RFEND_CFG1" },
1251 { .addr = CC1120_RFEND_CFG0, .name = "RFEND_CFG0" },
1252 { .addr = CC1120_PA_CFG2, .name = "PA_CFG2" },
1253 { .addr = CC1120_PA_CFG1, .name = "PA_CFG1" },
1254 { .addr = CC1120_PA_CFG0, .name = "PA_CFG0" },
1255 { .addr = CC1120_PKT_LEN, .name = "PKT_LEN" },
1256 { .addr = CC1120_IF_MIX_CFG, .name = "IF_MIX_CFG" },
1257 { .addr = CC1120_FREQOFF_CFG, .name = "FREQOFF_CFG" },
1258 { .addr = CC1120_TOC_CFG, .name = "TOC_CFG" },
1259 { .addr = CC1120_MARC_SPARE, .name = "MARC_SPARE" },
1260 { .addr = CC1120_ECG_CFG, .name = "ECG_CFG" },
1261 { .addr = CC1120_SOFT_TX_DATA_CFG, .name = "SOFT_TX_DATA_CFG" },
1262 { .addr = CC1120_EXT_CTRL, .name = "EXT_CTRL" },
1263 { .addr = CC1120_RCCAL_FINE, .name = "RCCAL_FINE" },
1264 { .addr = CC1120_RCCAL_COARSE, .name = "RCCAL_COARSE" },
1265 { .addr = CC1120_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
1266 { .addr = CC1120_FREQOFF1, .name = "FREQOFF1" },
1267 { .addr = CC1120_FREQOFF0, .name = "FREQOFF0" },
1268 { .addr = CC1120_FREQ2, .name = "FREQ2" },
1269 { .addr = CC1120_FREQ1, .name = "FREQ1" },
1270 { .addr = CC1120_FREQ0, .name = "FREQ0" },
1271 { .addr = CC1120_IF_ADC2, .name = "IF_ADC2" },
1272 { .addr = CC1120_IF_ADC1, .name = "IF_ADC1" },
1273 { .addr = CC1120_IF_ADC0, .name = "IF_ADC0" },
1274 { .addr = CC1120_FS_DIG1, .name = "FS_DIG1" },
1275 { .addr = CC1120_FS_DIG0, .name = "FS_DIG0" },
1276 { .addr = CC1120_FS_CAL3, .name = "FS_CAL3" },
1277 { .addr = CC1120_FS_CAL2, .name = "FS_CAL2" },
1278 { .addr = CC1120_FS_CAL1, .name = "FS_CAL1" },
1279 { .addr = CC1120_FS_CAL0, .name = "FS_CAL0" },
1280 { .addr = CC1120_FS_CHP, .name = "FS_CHP" },
1281 { .addr = CC1120_FS_DIVTWO, .name = "FS_DIVTWO" },
1282 { .addr = CC1120_FS_DSM1, .name = "FS_DSM1" },
1283 { .addr = CC1120_FS_DSM0, .name = "FS_DSM0" },
1284 { .addr = CC1120_FS_DVC1, .name = "FS_DVC1" },
1285 { .addr = CC1120_FS_DVC0, .name = "FS_DVC0" },
1286 { .addr = CC1120_FS_LBI, .name = "FS_LBI" },
1287 { .addr = CC1120_FS_PFD, .name = "FS_PFD" },
1288 { .addr = CC1120_FS_PRE, .name = "FS_PRE" },
1289 { .addr = CC1120_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
1290 { .addr = CC1120_FS_SPARE, .name = "FS_SPARE" },
1291 { .addr = CC1120_FS_VCO4, .name = "FS_VCO4" },
1292 { .addr = CC1120_FS_VCO3, .name = "FS_VCO3" },
1293 { .addr = CC1120_FS_VCO2, .name = "FS_VCO2" },
1294 { .addr = CC1120_FS_VCO1, .name = "FS_VCO1" },
1295 { .addr = CC1120_FS_VCO0, .name = "FS_VCO0" },
1296 { .addr = CC1120_GBIAS6, .name = "GBIAS6" },
1297 { .addr = CC1120_GBIAS5, .name = "GBIAS5" },
1298 { .addr = CC1120_GBIAS4, .name = "GBIAS4" },
1299 { .addr = CC1120_GBIAS3, .name = "GBIAS3" },
1300 { .addr = CC1120_GBIAS2, .name = "GBIAS2" },
1301 { .addr = CC1120_GBIAS1, .name = "GBIAS1" },
1302 { .addr = CC1120_GBIAS0, .name = "GBIAS0" },
1303 { .addr = CC1120_IFAMP, .name = "IFAMP" },
1304 { .addr = CC1120_LNA, .name = "LNA" },
1305 { .addr = CC1120_RXMIX, .name = "RXMIX" },
1306 { .addr = CC1120_XOSC5, .name = "XOSC5" },
1307 { .addr = CC1120_XOSC4, .name = "XOSC4" },
1308 { .addr = CC1120_XOSC3, .name = "XOSC3" },
1309 { .addr = CC1120_XOSC2, .name = "XOSC2" },
1310 { .addr = CC1120_XOSC1, .name = "XOSC1" },
1311 { .addr = CC1120_XOSC0, .name = "XOSC0" },
1312 { .addr = CC1120_ANALOG_SPARE, .name = "ANALOG_SPARE" },
1313 { .addr = CC1120_PA_CFG3, .name = "PA_CFG3" },
1314 { .addr = CC1120_WOR_TIME1, .name = "WOR_TIME1" },
1315 { .addr = CC1120_WOR_TIME0, .name = "WOR_TIME0" },
1316 { .addr = CC1120_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
1317 { .addr = CC1120_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
1318 { .addr = CC1120_BIST, .name = "BIST" },
1319 { .addr = CC1120_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
1320 { .addr = CC1120_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
1321 { .addr = CC1120_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
1322 { .addr = CC1120_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
1323 { .addr = CC1120_IQIE_I1, .name = "IQIE_I1" },
1324 { .addr = CC1120_IQIE_I0, .name = "IQIE_I0" },
1325 { .addr = CC1120_IQIE_Q1, .name = "IQIE_Q1" },
1326 { .addr = CC1120_IQIE_Q0, .name = "IQIE_Q0" },
1327 { .addr = CC1120_RSSI1, .name = "RSSI1" },
1328 { .addr = CC1120_RSSI0, .name = "RSSI0" },
1329 { .addr = CC1120_MARCSTATE, .name = "MARCSTATE" },
1330 { .addr = CC1120_LQI_VAL, .name = "LQI_VAL" },
1331 { .addr = CC1120_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
1332 { .addr = CC1120_DEM_STATUS, .name = "DEM_STATUS" },
1333 { .addr = CC1120_FREQOFF_EST1, .name = "FREQOFF_EST1" },
1334 { .addr = CC1120_FREQOFF_EST0, .name = "FREQOFF_EST0" },
1335 { .addr = CC1120_AGC_GAIN3, .name = "AGC_GAIN3" },
1336 { .addr = CC1120_AGC_GAIN2, .name = "AGC_GAIN2" },
1337 { .addr = CC1120_AGC_GAIN1, .name = "AGC_GAIN1" },
1338 { .addr = CC1120_AGC_GAIN0, .name = "AGC_GAIN0" },
1339 { .addr = CC1120_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
1340 { .addr = CC1120_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
1341 { .addr = CC1120_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
1342 { .addr = CC1120_RNDGEN, .name = "RNDGEN" },
1343 { .addr = CC1120_MAGN2, .name = "MAGN2" },
1344 { .addr = CC1120_MAGN1, .name = "MAGN1" },
1345 { .addr = CC1120_MAGN0, .name = "MAGN0" },
1346 { .addr = CC1120_ANG1, .name = "ANG1" },
1347 { .addr = CC1120_ANG0, .name = "ANG0" },
1348 { .addr = CC1120_CHFILT_I2, .name = "CHFILT_I2" },
1349 { .addr = CC1120_CHFILT_I1, .name = "CHFILT_I1" },
1350 { .addr = CC1120_CHFILT_I0, .name = "CHFILT_I0" },
1351 { .addr = CC1120_CHFILT_Q2, .name = "CHFILT_Q2" },
1352 { .addr = CC1120_CHFILT_Q1, .name = "CHFILT_Q1" },
1353 { .addr = CC1120_CHFILT_Q0, .name = "CHFILT_Q0" },
1354 { .addr = CC1120_GPIO_STATUS, .name = "GPIO_STATUS" },
1355 { .addr = CC1120_FSCAL_CTRL, .name = "FSCAL_CTRL" },
1356 { .addr = CC1120_PHASE_ADJUST, .name = "PHASE_ADJUST" },
1357 { .addr = CC1120_PARTNUMBER, .name = "PARTNUMBER" },
1358 { .addr = CC1120_PARTVERSION, .name = "PARTVERSION" },
1359 { .addr = CC1120_SERIAL_STATUS, .name = "SERIAL_STATUS" },
1360 { .addr = CC1120_RX_STATUS, .name = "RX_STATUS" },
1361 { .addr = CC1120_TX_STATUS, .name = "TX_STATUS" },
1362 { .addr = CC1120_MARC_STATUS1, .name = "MARC_STATUS1" },
1363 { .addr = CC1120_MARC_STATUS0, .name = "MARC_STATUS0" },
1364 { .addr = CC1120_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
1365 { .addr = CC1120_FSRF_TEST, .name = "FSRF_TEST" },
1366 { .addr = CC1120_PRE_TEST, .name = "PRE_TEST" },
1367 { .addr = CC1120_PRE_OVR, .name = "PRE_OVR" },
1368 { .addr = CC1120_ADC_TEST, .name = "ADC_TEST" },
1369 { .addr = CC1120_DVC_TEST, .name = "DVC_TEST" },
1370 { .addr = CC1120_ATEST, .name = "ATEST" },
1371 { .addr = CC1120_ATEST_LVDS, .name = "ATEST_LVDS" },
1372 { .addr = CC1120_ATEST_MODE, .name = "ATEST_MODE" },
1373 { .addr = CC1120_XOSC_TEST1, .name = "XOSC_TEST1" },
1374 { .addr = CC1120_XOSC_TEST0, .name = "XOSC_TEST0" },
1375 { .addr = CC1120_RXFIRST, .name = "RXFIRST" },
1376 { .addr = CC1120_TXFIRST, .name = "TXFIRST" },
1377 { .addr = CC1120_RXLAST, .name = "RXLAST" },
1378 { .addr = CC1120_TXLAST, .name = "TXLAST" },
1379 { .addr = CC1120_NUM_TXBYTES, .name = "NUM_TXBYTES" },
1380 { .addr = CC1120_NUM_RXBYTES, .name = "NUM_RXBYTES" },
1381 { .addr = CC1120_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
1382 { .addr = CC1120_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
1385 #define AO_NUM_CC1120_REG (sizeof ao_cc1120_reg / sizeof ao_cc1120_reg[0])
1387 static void ao_radio_show(void) {
1388 uint8_t status = ao_radio_status();
1392 status = ao_radio_status();
1393 printf ("Status: %02x\n", status);
1394 printf ("CHIP_RDY: %d\n", (status >> CC1120_STATUS_CHIP_RDY) & 1);
1395 printf ("STATE: %s\n", cc1120_state_name[(status >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK]);
1396 printf ("MARC: %02x\n", ao_radio_get_marc_status());
1398 for (i = 0; i < AO_NUM_CC1120_REG; i++)
1399 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name);
1401 printf("RX fast start: %u\n", rx_fast_start);
1402 printf("RX slow start: %u\n", rx_slow_start);
1403 printf("RX missed: %u\n", rx_missed);
1407 static void ao_radio_beep(void) {
1411 static void ao_radio_packet(void) {
1412 static const uint8_t packet[] = {
1414 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
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,
1423 ao_radio_send(packet, sizeof (packet));
1427 ao_radio_test_recv(void)
1432 if (ao_radio_recv(bytes, 34, 0)) {
1433 if (bytes[33] & 0x80)
1437 printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32]));
1438 for (b = 0; b < 32; b++)
1439 printf (" %02x", bytes[b]);
1445 #include <ao_aprs.h>
1450 #if PACKET_HAS_SLAVE
1451 ao_packet_slave_stop();
1458 static const struct ao_cmds ao_radio_cmds[] = {
1459 { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
1462 { ao_radio_aprs, "G\0Send APRS packet" },
1464 { ao_radio_show, "R\0Show CC1120 status" },
1465 { ao_radio_beep, "b\0Emit an RDF beacon" },
1466 { ao_radio_packet, "p\0Send a test packet" },
1467 { ao_radio_test_recv, "q\0Recv a test packet" },
1475 ao_radio_configured = 0;
1476 ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN));
1479 AO_CC1120_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN));
1480 for (i = 0; i < 10000; i++) {
1481 if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0)
1484 AO_CC1120_SPI_CS_PORT->bsrr = (1 << AO_CC1120_SPI_CS_PIN);
1486 ao_panic(AO_PANIC_SELF_TEST_CC1120);
1489 /* Enable the EXTI interrupt for the appropriate pin */
1490 ao_enable_port(AO_CC1120_INT_PORT);
1491 ao_exti_setup(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1492 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
1495 /* Enable the hacked up GPIO3 pin */
1496 ao_enable_port(AO_CC1120_MCU_WAKEUP_PORT);
1497 ao_exti_setup(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN,
1498 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED,
1499 ao_radio_mcu_wakeup_isr);
1501 ao_cmd_register(&ao_radio_cmds[0]);