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_send_sync(d,l) ao_spi_send_sync((d), (l), AO_CC1120_SPI_BUS)
48 #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1120_SPI_BUS)
49 #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1120_SPI_BUS)
50 #define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1120_SPI_BUS)
51 #define ao_radio_duplex(o,i,l) ao_spi_duplex((o), (i), (l), AO_CC1120_SPI_BUS)
54 ao_radio_reg_read(uint16_t addr)
60 printf("\t\tao_radio_reg_read (%04x): ", addr); flush();
62 if (CC1120_IS_EXTENDED(addr)) {
63 data[0] = ((1 << CC1120_READ) |
69 data[0] = ((1 << CC1120_READ) |
75 ao_radio_spi_send(data, d);
76 ao_radio_spi_recv(data, 1);
79 printf (" %02x\n", data[0]);
85 ao_radio_reg_write(uint16_t addr, uint8_t value)
91 printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value);
93 if (CC1120_IS_EXTENDED(addr)) {
94 data[0] = ((0 << CC1120_READ) |
100 data[0] = ((0 << CC1120_READ) |
101 (0 << CC1120_BURST) |
107 ao_radio_spi_send(data, d+1);
112 _ao_radio_burst_read_start (uint16_t addr)
117 if (CC1120_IS_EXTENDED(addr)) {
118 data[0] = ((1 << CC1120_READ) |
119 (1 << CC1120_BURST) |
124 data[0] = ((1 << CC1120_READ) |
125 (1 << CC1120_BURST) |
130 ao_radio_spi_send_sync(data, d);
134 ao_radio_burst_read_stop (void)
141 ao_radio_strobe(uint8_t addr)
146 printf("\t\tao_radio_strobe (%02x): ", addr); flush();
149 ao_radio_duplex(&addr, &in, 1);
152 printf("%02x\n", in); flush();
159 ao_radio_fifo_read(uint8_t *data, uint8_t len)
161 uint8_t addr = ((1 << CC1120_READ) |
162 (1 << CC1120_BURST) |
167 ao_radio_duplex(&addr, &status, 1);
168 ao_radio_spi_recv(data, len);
175 ao_radio_fifo_write_start(void)
177 uint8_t addr = ((0 << CC1120_READ) |
178 (1 << CC1120_BURST) |
183 ao_radio_duplex(&addr, &status, 1);
187 static inline uint8_t ao_radio_fifo_write_stop(uint8_t status) {
193 ao_radio_fifo_write(uint8_t *data, uint8_t len)
195 uint8_t status = ao_radio_fifo_write_start();
196 ao_radio_spi_send(data, len);
197 return ao_radio_fifo_write_stop(status);
201 ao_radio_fifo_write_fixed(uint8_t data, uint8_t len)
203 uint8_t status = ao_radio_fifo_write_start();
204 ao_radio_spi_send_fixed(data, len);
205 return ao_radio_fifo_write_stop(status);
209 ao_radio_tx_fifo_space(void)
211 return CC1120_FIFO_SIZE - ao_radio_reg_read(CC1120_NUM_TXBYTES);
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_start_tx(void)
269 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr);
270 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
271 ao_exti_enable(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN);
272 ao_radio_tx_finished = 0;
273 ao_radio_strobe(CC1120_STX);
280 uint8_t state = (ao_radio_strobe(CC1120_SIDLE) >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK;
281 if (state == CC1120_STATUS_STATE_IDLE)
283 if (state == CC1120_STATUS_STATE_TX_FIFO_ERROR)
284 ao_radio_strobe(CC1120_SFTX);
285 if (state == CC1120_STATUS_STATE_RX_FIFO_ERROR)
286 ao_radio_strobe(CC1120_SFRX);
288 /* Flush any pending TX bytes */
289 ao_radio_strobe(CC1120_SFTX);
293 * Packet deviation is 20.5kHz
295 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
297 * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz
300 #define PACKET_DEV_E 5
301 #define PACKET_DEV_M 80
304 * For our packet data
306 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
307 * Rdata = -------------------------------------- * fosc
310 * Symbol rate 38400 Baud:
312 * DATARATE_M = 239914
314 * CHANBW = 74.42 (round to 100)
316 * Symbol rate 9600 Baud:
318 * DATARATE_M = 239914
320 * CHANBW = 58.58 (round to 62.5)
322 * Symbol rate 2400 Baud:
324 * DATARATE_M = 239914
326 * CHANBW = 47.61 (round to 50)
329 #define PACKET_DRATE_M 239914
331 #define PACKET_DRATE_E_384 9
332 #define PACKET_CHAN_BW_384 0x02 /* 200 / 2 = 100 */
334 #define PACKET_DRATE_E_96 7
335 #define PACKET_CHAN_BW_96 0x42 /* 125 / 2 = 62.5 */
337 #define PACKET_DRATE_E_24 5
338 #define PACKET_CHAN_BW_24 0x04 /* 200 / 4 = 50 */
340 static const uint16_t packet_setup[] = {
341 CC1120_DEVIATION_M, PACKET_DEV_M,
342 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
343 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
344 (PACKET_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
345 CC1120_DRATE1, ((PACKET_DRATE_M >> 8) & 0xff),
346 CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff),
347 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
348 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
349 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
350 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
351 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
352 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
353 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
354 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
355 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
356 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
357 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
358 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
359 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
360 AO_CC1120_MARC_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP,
363 static const uint16_t packet_setup_384[] = {
364 CC1120_DRATE2, ((PACKET_DRATE_E_384 << CC1120_DRATE2_DATARATE_E) |
365 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
366 CC1120_CHAN_BW, PACKET_CHAN_BW_384,
367 CC1120_PA_CFG0, 0x7b,
370 static const uint16_t packet_setup_96[] = {
371 CC1120_DRATE2, ((PACKET_DRATE_E_96 << CC1120_DRATE2_DATARATE_E) |
372 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
373 CC1120_CHAN_BW, PACKET_CHAN_BW_96,
374 CC1120_PA_CFG0, 0x7d,
377 static const uint16_t packet_setup_24[] = {
378 CC1120_DRATE2, ((PACKET_DRATE_E_24 << CC1120_DRATE2_DATARATE_E) |
379 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
380 CC1120_CHAN_BW, PACKET_CHAN_BW_24,
381 CC1120_PA_CFG0, 0x7e,
384 static const uint16_t packet_tx_setup[] = {
385 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
386 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
387 AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG,
390 static const uint16_t packet_rx_setup[] = {
391 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
392 (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT)),
393 AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT,
397 * RDF deviation is 5kHz
399 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
401 * 32e6Hz / (2 ** 24) * (256 + 71) * (2 ** 3) = 4989
406 #define RDF_PACKET_LEN 50
409 * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
411 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
412 * Rdata = -------------------------------------- * fosc
418 * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
420 #define RDF_DRATE_E 5
421 #define RDF_DRATE_M 25166
422 #define RDF_PACKET_LEN 50
424 static const uint16_t rdf_setup[] = {
425 CC1120_DEVIATION_M, RDF_DEV_M,
426 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
427 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
428 (RDF_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
429 CC1120_DRATE2, ((RDF_DRATE_E << CC1120_DRATE2_DATARATE_E) |
430 (((RDF_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
431 CC1120_DRATE1, ((RDF_DRATE_M >> 8) & 0xff),
432 CC1120_DRATE0, ((RDF_DRATE_M >> 0) & 0xff),
433 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
434 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
435 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
436 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
437 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
438 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
439 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
440 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
441 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
442 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
443 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
444 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
445 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
446 CC1120_PA_CFG0, 0x7e,
450 * APRS deviation is 3kHz
452 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
454 * 32e6Hz / (2 ** 24) * (256 + 137) * (2 ** 2) = 2998Hz
458 #define APRS_DEV_M 137
461 * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate)
463 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
464 * Rdata = -------------------------------------- * fosc
467 * DATARATE_M = 239914
470 * Rdata = 9599.998593330383301
473 #define APRS_DRATE_E 7
474 #define APRS_DRATE_M 239914
476 static const uint16_t aprs_setup[] = {
477 CC1120_DEVIATION_M, APRS_DEV_M,
478 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
479 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
480 (APRS_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
481 CC1120_DRATE2, ((APRS_DRATE_E << CC1120_DRATE2_DATARATE_E) |
482 (((APRS_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
483 CC1120_DRATE1, ((APRS_DRATE_M >> 8) & 0xff),
484 CC1120_DRATE0, ((APRS_DRATE_M >> 0) & 0xff),
485 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
486 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
487 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
488 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
489 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
490 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
491 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
492 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
493 CC1120_PA_CFG0, 0x7d,
497 * For Test mode, we want an unmodulated carrier. To do that, we
498 * set the deviation to zero and enable a preamble so that the radio
499 * turns on before we send any data
502 static const uint16_t test_setup[] = {
503 CC1120_DEVIATION_M, 0,
504 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
505 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
506 (0 << CC1120_MODCFG_DEV_E_DEV_E)),
507 CC1120_DRATE2, ((APRS_DRATE_E << CC1120_DRATE2_DATARATE_E) |
508 (((APRS_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
509 CC1120_DRATE1, ((APRS_DRATE_M >> 8) & 0xff),
510 CC1120_DRATE0, ((APRS_DRATE_M >> 0) & 0xff),
511 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
512 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
513 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
514 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
515 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
516 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
517 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
518 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
521 #define AO_PKT_CFG0_INFINITE ((0 << CC1120_PKT_CFG0_RESERVED7) | \
522 (CC1120_PKT_CFG0_LENGTH_CONFIG_INFINITE << CC1120_PKT_CFG0_LENGTH_CONFIG) | \
523 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | \
524 (0 << CC1120_PKT_CFG0_UART_MODE_EN) | \
525 (0 << CC1120_PKT_CFG0_UART_SWAP_EN))
527 #define AO_PKT_CFG0_FIXED ((0 << CC1120_PKT_CFG0_RESERVED7) | \
528 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) | \
529 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | \
530 (0 << CC1120_PKT_CFG0_UART_MODE_EN) | \
531 (0 << CC1120_PKT_CFG0_UART_SWAP_EN))
533 static uint16_t ao_radio_mode;
535 #define AO_RADIO_MODE_BITS_PACKET 1
536 #define AO_RADIO_MODE_BITS_PACKET_TX 2
537 #define AO_RADIO_MODE_BITS_TX_BUF 4
538 #define AO_RADIO_MODE_BITS_TX_FINISH 8
539 #define AO_RADIO_MODE_BITS_PACKET_RX 16
540 #define AO_RADIO_MODE_BITS_RDF 32
541 #define AO_RADIO_MODE_BITS_APRS 64
542 #define AO_RADIO_MODE_BITS_TEST 128
543 #define AO_RADIO_MODE_BITS_INFINITE 256
544 #define AO_RADIO_MODE_BITS_FIXED 512
546 #define AO_RADIO_MODE_NONE 0
547 #define AO_RADIO_MODE_PACKET_TX_BUF (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_BUF)
548 #define AO_RADIO_MODE_PACKET_TX_FINISH (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_FINISH)
549 #define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_RX)
550 #define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_TX_FINISH)
551 #define AO_RADIO_MODE_APRS_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
552 #define AO_RADIO_MODE_APRS_LAST_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_BUF)
553 #define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
554 #define AO_RADIO_MODE_TEST (AO_RADIO_MODE_BITS_TEST | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
557 _ao_radio_set_regs(const uint16_t *regs, int nreg)
561 for (i = 0; i < nreg; i++) {
562 ao_radio_reg_write(regs[0], regs[1]);
567 #define ao_radio_set_regs(setup) _ao_radio_set_regs(setup, (sizeof (setup) / sizeof(setup[0])) >> 1)
570 ao_radio_set_mode(uint16_t new_mode)
574 if (new_mode == ao_radio_mode)
577 changes = new_mode & (~ao_radio_mode);
579 if (changes & AO_RADIO_MODE_BITS_PACKET) {
580 ao_radio_set_regs(packet_setup);
582 switch (ao_config.radio_rate) {
584 case AO_RADIO_RATE_38400:
585 ao_radio_set_regs(packet_setup_384);
587 case AO_RADIO_RATE_9600:
588 ao_radio_set_regs(packet_setup_96);
590 case AO_RADIO_RATE_2400:
591 ao_radio_set_regs(packet_setup_24);
596 if (changes & AO_RADIO_MODE_BITS_PACKET_TX)
597 ao_radio_set_regs(packet_tx_setup);
599 if (changes & AO_RADIO_MODE_BITS_TX_BUF)
600 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_TXFIFO_THR);
602 if (changes & AO_RADIO_MODE_BITS_TX_FINISH)
603 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG);
605 if (changes & AO_RADIO_MODE_BITS_PACKET_RX)
606 ao_radio_set_regs(packet_rx_setup);
608 if (changes & AO_RADIO_MODE_BITS_RDF)
609 ao_radio_set_regs(rdf_setup);
611 if (changes & AO_RADIO_MODE_BITS_APRS)
612 ao_radio_set_regs(aprs_setup);
614 if (changes & AO_RADIO_MODE_BITS_TEST)
615 ao_radio_set_regs(test_setup);
617 if (changes & AO_RADIO_MODE_BITS_INFINITE)
618 ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_INFINITE);
620 if (changes & AO_RADIO_MODE_BITS_FIXED)
621 ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_FIXED);
623 ao_radio_mode = new_mode;
626 static const uint16_t radio_setup[] = {
627 #include "ao_cc1120_CC1120.h"
630 static uint8_t ao_radio_configured = 0;
635 ao_radio_strobe(CC1120_SRES);
637 ao_radio_set_regs(radio_setup);
643 ao_radio_configured = 1;
647 ao_radio_set_len(uint8_t len)
649 static uint8_t last_len;
651 if (len != last_len) {
652 ao_radio_reg_write(CC1120_PKT_LEN, len);
658 ao_radio_get(uint8_t len)
660 static uint32_t last_radio_setting;
661 static uint8_t last_radio_rate;
663 ao_mutex_get(&ao_radio_mutex);
665 if (!ao_radio_configured)
667 if (ao_config.radio_setting != last_radio_setting) {
668 ao_radio_reg_write(CC1120_FREQ2, ao_config.radio_setting >> 16);
669 ao_radio_reg_write(CC1120_FREQ1, ao_config.radio_setting >> 8);
670 ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting);
671 last_radio_setting = ao_config.radio_setting;
673 if (ao_config.radio_rate != last_radio_rate) {
674 ao_radio_mode &= ~AO_RADIO_MODE_BITS_PACKET;
675 last_radio_rate = ao_config.radio_rate;
677 ao_radio_set_len(len);
680 #define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
683 ao_rdf_start(uint8_t len)
688 ao_radio_set_mode(AO_RADIO_MODE_RDF);
698 ao_arch_block_interrupts();
699 while (!ao_radio_wake && !ao_radio_abort && !ao_radio_mcu_wake)
700 ao_sleep(&ao_radio_wake);
701 ao_arch_release_interrupts();
702 if (ao_radio_mcu_wake)
703 ao_radio_check_marc_status();
712 ao_rdf_start(AO_RADIO_RDF_LEN);
714 ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN);
720 ao_radio_continuity(uint8_t c)
725 ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN);
727 status = ao_radio_fifo_write_start();
728 for (i = 0; i < 3; i++) {
729 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
731 ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN);
733 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN);
735 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
736 status = ao_radio_fifo_write_stop(status);
742 ao_radio_rdf_abort(void)
745 ao_wakeup(&ao_radio_wake);
749 ao_radio_test_cmd(void)
752 static uint8_t radio_on;
754 if (ao_cmd_lex_c != '\n') {
756 mode = (uint8_t) ao_cmd_lex_u32;
759 if ((mode & 2) && !radio_on) {
761 ao_monitor_disable();
764 ao_packet_slave_stop();
767 ao_radio_set_mode(AO_RADIO_MODE_TEST);
768 ao_radio_strobe(CC1120_STX);
771 for (t = 0; t < 10; t++) {
772 printf ("status: %02x\n", ao_radio_status());
773 ao_delay(AO_MS_TO_TICKS(100));
780 printf ("Hit a character to stop..."); flush();
784 if ((mode & 1) && radio_on) {
795 ao_radio_wait_isr(uint16_t timeout)
799 ao_arch_block_interrupts();
800 while (!ao_radio_wake && !ao_radio_mcu_wake && !ao_radio_abort)
801 if (ao_sleep(&ao_radio_wake))
803 ao_arch_release_interrupts();
806 if (ao_radio_mcu_wake)
807 ao_radio_check_marc_status();
811 ao_radio_wait_tx(uint8_t wait_fifo)
813 uint8_t fifo_space = 0;
816 ao_radio_wait_isr(0);
819 fifo_space = ao_radio_tx_fifo_space();
820 } while (!fifo_space && !ao_radio_abort);
824 static uint8_t tx_data[(AO_RADIO_MAX_SEND + 4) * 2];
827 ao_radio_send(const void *d, uint8_t size)
829 uint8_t *e = tx_data;
835 encode_len = ao_fec_encode(d, size, tx_data);
837 ao_radio_get(encode_len);
841 /* Flush any pending TX bytes */
842 ao_radio_strobe(CC1120_SFTX);
845 fifo_space = CC1120_FIFO_SIZE;
847 this_len = encode_len;
850 if (this_len > fifo_space) {
851 this_len = fifo_space;
852 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_BUF);
854 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_FINISH);
857 ao_radio_fifo_write(e, this_len);
859 encode_len -= this_len;
865 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
868 fifo_space = ao_radio_wait_tx(encode_len != 0);
869 if (ao_radio_abort) {
874 while (started && !ao_radio_abort && !ao_radio_tx_finished)
875 ao_radio_wait_isr(0);
879 #define AO_RADIO_LOTS 64
882 ao_radio_send_aprs(ao_radio_fill_func fill)
884 uint8_t buf[AO_RADIO_LOTS], *b;
892 fifo_space = CC1120_FIFO_SIZE;
894 cnt = (*fill)(buf, sizeof(buf));
901 /* At the last buffer, set the total length */
903 ao_radio_set_len(total & 0xff);
907 uint8_t this_len = cnt;
909 /* Wait for some space in the fifo */
910 while (!ao_radio_abort && (fifo_space = ao_radio_tx_fifo_space()) == 0) {
912 ao_radio_wait_isr(0);
916 if (this_len > fifo_space)
917 this_len = fifo_space;
923 ao_radio_set_mode(AO_RADIO_MODE_APRS_LAST_BUF);
925 ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
927 ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
929 ao_radio_fifo_write(b, this_len);
936 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
938 if (ao_radio_abort) {
942 /* Wait for the transmitter to go idle */
944 ao_radio_wait_isr(0);
949 static uint8_t rx_data[(AO_RADIO_MAX_RECV + 4) * 2 * 8];
950 static uint16_t rx_data_count;
951 static uint16_t rx_data_consumed;
952 static uint16_t rx_data_cur;
953 static uint8_t rx_ignore;
954 static uint8_t rx_waiting;
955 static uint8_t rx_starting;
956 static uint8_t rx_task_id;
957 static uint32_t rx_fast_start;
958 static uint32_t rx_slow_start;
959 static uint32_t rx_missed;
962 static uint32_t rx_start_tick, rx_packet_tick, rx_done_tick, rx_last_done_tick;
964 uint32_t ao_rx_start_tick, ao_rx_packet_tick, ao_rx_done_tick, ao_rx_last_done_tick;
966 #include <ao_profile.h>
970 ao_radio_rx_isr(void)
975 if (ao_radio_try_select(rx_task_id)) {
978 _ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
991 ao_wakeup(&ao_radio_wake);
993 d = AO_CC1120_SPI.dr;
994 AO_CC1120_SPI.dr = 0;
995 if (rx_ignore == 0) {
996 if (rx_data_cur < rx_data_count)
997 rx_data[rx_data_cur++] = d;
998 if (rx_data_cur >= rx_data_count) {
999 ao_spi_clr_cs(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN));
1000 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
1002 if (rx_waiting && rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) {
1004 if (!rx_packet_tick)
1005 rx_packet_tick = ao_profile_tick();
1006 if (rx_data_cur < rx_data_count)
1010 ao_wakeup(&ao_radio_wake);
1018 ao_radio_rx_wait(void)
1020 ao_alarm(AO_MS_TO_TICKS(100));
1021 ao_arch_block_interrupts();
1023 while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&
1027 if (ao_sleep(&ao_radio_wake))
1031 ao_arch_release_interrupts();
1033 if (ao_radio_abort || ao_radio_mcu_wake)
1035 rx_data_consumed += AO_FEC_DECODE_BLOCK;
1037 return rx_data_cur - rx_data_consumed;
1039 return AO_FEC_DECODE_BLOCK;
1043 ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout)
1046 uint8_t radio_rssi = 0;
1050 size -= 2; /* status bytes */
1051 if (size > AO_RADIO_MAX_RECV) {
1052 ao_delay(AO_SEC_TO_TICKS(1));
1056 rx_start_tick = ao_profile_tick();
1059 len = size + 2; /* CRC bytes */
1060 len += 1 + ~(len & 1); /* 1 or two pad bytes */
1061 len *= 2; /* 1/2 rate convolution */
1062 rx_data_count = len * 8; /* bytes to bits */
1064 rx_data_consumed = 0;
1067 /* Must be set before changing the frequency; any abort
1068 * after the frequency is set needs to terminate the read
1069 * so that the registers can be reprogrammed
1076 ao_radio_mcu_wake = 0;
1078 ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
1080 /* configure interrupt pin */
1081 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT);
1082 ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1083 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
1085 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
1086 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
1089 rx_task_id = ao_cur_task->task_id;
1091 ao_radio_strobe(CC1120_SRX);
1095 ao_arch_block_interrupts();
1096 while (rx_starting && !ao_radio_abort) {
1097 if (ao_sleep(&ao_radio_wake))
1100 uint8_t rx_task_id_save = rx_task_id;
1103 ao_arch_release_interrupts();
1107 if (ao_radio_abort) {
1113 if (rx_task_id_save) {
1116 _ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
1118 uint8_t ignore = AO_CC1120_SPI.dr;
1120 AO_CC1120_SPI.dr = 0;
1125 ret = ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait);
1127 ao_radio_burst_read_stop();
1129 if (ao_radio_mcu_wake)
1130 ao_radio_check_marc_status();
1135 /* Convert from 'real' rssi to cc1111-style values */
1137 rssi0 = ao_radio_reg_read(CC1120_RSSI0);
1139 int8_t rssi = ao_radio_reg_read(CC1120_RSSI1);
1140 ao_radio_rssi = rssi;
1142 /* Bound it to the representable range */
1145 radio_rssi = AO_RADIO_FROM_RSSI (rssi);
1152 /* Store the received RSSI value; the crc-OK byte is already done */
1154 ((uint8_t *) d)[size] = radio_rssi;
1157 rx_last_done_tick = rx_done_tick;
1158 rx_done_tick = ao_profile_tick();
1160 ao_rx_start_tick = rx_start_tick;
1161 ao_rx_packet_tick = rx_packet_tick;
1162 ao_rx_done_tick = rx_done_tick;
1163 ao_rx_last_done_tick = rx_last_done_tick;
1171 static char *cc1120_state_name[] = {
1172 [CC1120_STATUS_STATE_IDLE] = "IDLE",
1173 [CC1120_STATUS_STATE_RX] = "RX",
1174 [CC1120_STATUS_STATE_TX] = "TX",
1175 [CC1120_STATUS_STATE_FSTXON] = "FSTXON",
1176 [CC1120_STATUS_STATE_CALIBRATE] = "CALIBRATE",
1177 [CC1120_STATUS_STATE_SETTLING] = "SETTLING",
1178 [CC1120_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
1179 [CC1120_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
1182 struct ao_cc1120_reg {
1187 static const struct ao_cc1120_reg ao_cc1120_reg[] = {
1188 { .addr = CC1120_IOCFG3, .name = "IOCFG3" },
1189 { .addr = CC1120_IOCFG2, .name = "IOCFG2" },
1190 { .addr = CC1120_IOCFG1, .name = "IOCFG1" },
1191 { .addr = CC1120_IOCFG0, .name = "IOCFG0" },
1192 { .addr = CC1120_SYNC3, .name = "SYNC3" },
1193 { .addr = CC1120_SYNC2, .name = "SYNC2" },
1194 { .addr = CC1120_SYNC1, .name = "SYNC1" },
1195 { .addr = CC1120_SYNC0, .name = "SYNC0" },
1196 { .addr = CC1120_SYNC_CFG1, .name = "SYNC_CFG1" },
1197 { .addr = CC1120_SYNC_CFG0, .name = "SYNC_CFG0" },
1198 { .addr = CC1120_DEVIATION_M, .name = "DEVIATION_M" },
1199 { .addr = CC1120_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
1200 { .addr = CC1120_DCFILT_CFG, .name = "DCFILT_CFG" },
1201 { .addr = CC1120_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
1202 { .addr = CC1120_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
1203 { .addr = CC1120_FREQ_IF_CFG, .name = "FREQ_IF_CFG" },
1204 { .addr = CC1120_IQIC, .name = "IQIC" },
1205 { .addr = CC1120_CHAN_BW, .name = "CHAN_BW" },
1206 { .addr = CC1120_MDMCFG1, .name = "MDMCFG1" },
1207 { .addr = CC1120_MDMCFG0, .name = "MDMCFG0" },
1208 { .addr = CC1120_DRATE2, .name = "DRATE2" },
1209 { .addr = CC1120_DRATE1, .name = "DRATE1" },
1210 { .addr = CC1120_DRATE0, .name = "DRATE0" },
1211 { .addr = CC1120_AGC_REF, .name = "AGC_REF" },
1212 { .addr = CC1120_AGC_CS_THR, .name = "AGC_CS_THR" },
1213 { .addr = CC1120_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
1214 { .addr = CC1120_AGC_CFG3, .name = "AGC_CFG3" },
1215 { .addr = CC1120_AGC_CFG2, .name = "AGC_CFG2" },
1216 { .addr = CC1120_AGC_CFG1, .name = "AGC_CFG1" },
1217 { .addr = CC1120_AGC_CFG0, .name = "AGC_CFG0" },
1218 { .addr = CC1120_FIFO_CFG, .name = "FIFO_CFG" },
1219 { .addr = CC1120_DEV_ADDR, .name = "DEV_ADDR" },
1220 { .addr = CC1120_SETTLING_CFG, .name = "SETTLING_CFG" },
1221 { .addr = CC1120_FS_CFG, .name = "FS_CFG" },
1222 { .addr = CC1120_WOR_CFG1, .name = "WOR_CFG1" },
1223 { .addr = CC1120_WOR_CFG0, .name = "WOR_CFG0" },
1224 { .addr = CC1120_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
1225 { .addr = CC1120_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
1226 { .addr = CC1120_PKT_CFG2, .name = "PKT_CFG2" },
1227 { .addr = CC1120_PKT_CFG1, .name = "PKT_CFG1" },
1228 { .addr = CC1120_PKT_CFG0, .name = "PKT_CFG0" },
1229 { .addr = CC1120_RFEND_CFG1, .name = "RFEND_CFG1" },
1230 { .addr = CC1120_RFEND_CFG0, .name = "RFEND_CFG0" },
1231 { .addr = CC1120_PA_CFG2, .name = "PA_CFG2" },
1232 { .addr = CC1120_PA_CFG1, .name = "PA_CFG1" },
1233 { .addr = CC1120_PA_CFG0, .name = "PA_CFG0" },
1234 { .addr = CC1120_PKT_LEN, .name = "PKT_LEN" },
1235 { .addr = CC1120_IF_MIX_CFG, .name = "IF_MIX_CFG" },
1236 { .addr = CC1120_FREQOFF_CFG, .name = "FREQOFF_CFG" },
1237 { .addr = CC1120_TOC_CFG, .name = "TOC_CFG" },
1238 { .addr = CC1120_MARC_SPARE, .name = "MARC_SPARE" },
1239 { .addr = CC1120_ECG_CFG, .name = "ECG_CFG" },
1240 { .addr = CC1120_SOFT_TX_DATA_CFG, .name = "SOFT_TX_DATA_CFG" },
1241 { .addr = CC1120_EXT_CTRL, .name = "EXT_CTRL" },
1242 { .addr = CC1120_RCCAL_FINE, .name = "RCCAL_FINE" },
1243 { .addr = CC1120_RCCAL_COARSE, .name = "RCCAL_COARSE" },
1244 { .addr = CC1120_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
1245 { .addr = CC1120_FREQOFF1, .name = "FREQOFF1" },
1246 { .addr = CC1120_FREQOFF0, .name = "FREQOFF0" },
1247 { .addr = CC1120_FREQ2, .name = "FREQ2" },
1248 { .addr = CC1120_FREQ1, .name = "FREQ1" },
1249 { .addr = CC1120_FREQ0, .name = "FREQ0" },
1250 { .addr = CC1120_IF_ADC2, .name = "IF_ADC2" },
1251 { .addr = CC1120_IF_ADC1, .name = "IF_ADC1" },
1252 { .addr = CC1120_IF_ADC0, .name = "IF_ADC0" },
1253 { .addr = CC1120_FS_DIG1, .name = "FS_DIG1" },
1254 { .addr = CC1120_FS_DIG0, .name = "FS_DIG0" },
1255 { .addr = CC1120_FS_CAL3, .name = "FS_CAL3" },
1256 { .addr = CC1120_FS_CAL2, .name = "FS_CAL2" },
1257 { .addr = CC1120_FS_CAL1, .name = "FS_CAL1" },
1258 { .addr = CC1120_FS_CAL0, .name = "FS_CAL0" },
1259 { .addr = CC1120_FS_CHP, .name = "FS_CHP" },
1260 { .addr = CC1120_FS_DIVTWO, .name = "FS_DIVTWO" },
1261 { .addr = CC1120_FS_DSM1, .name = "FS_DSM1" },
1262 { .addr = CC1120_FS_DSM0, .name = "FS_DSM0" },
1263 { .addr = CC1120_FS_DVC1, .name = "FS_DVC1" },
1264 { .addr = CC1120_FS_DVC0, .name = "FS_DVC0" },
1265 { .addr = CC1120_FS_LBI, .name = "FS_LBI" },
1266 { .addr = CC1120_FS_PFD, .name = "FS_PFD" },
1267 { .addr = CC1120_FS_PRE, .name = "FS_PRE" },
1268 { .addr = CC1120_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
1269 { .addr = CC1120_FS_SPARE, .name = "FS_SPARE" },
1270 { .addr = CC1120_FS_VCO4, .name = "FS_VCO4" },
1271 { .addr = CC1120_FS_VCO3, .name = "FS_VCO3" },
1272 { .addr = CC1120_FS_VCO2, .name = "FS_VCO2" },
1273 { .addr = CC1120_FS_VCO1, .name = "FS_VCO1" },
1274 { .addr = CC1120_FS_VCO0, .name = "FS_VCO0" },
1275 { .addr = CC1120_GBIAS6, .name = "GBIAS6" },
1276 { .addr = CC1120_GBIAS5, .name = "GBIAS5" },
1277 { .addr = CC1120_GBIAS4, .name = "GBIAS4" },
1278 { .addr = CC1120_GBIAS3, .name = "GBIAS3" },
1279 { .addr = CC1120_GBIAS2, .name = "GBIAS2" },
1280 { .addr = CC1120_GBIAS1, .name = "GBIAS1" },
1281 { .addr = CC1120_GBIAS0, .name = "GBIAS0" },
1282 { .addr = CC1120_IFAMP, .name = "IFAMP" },
1283 { .addr = CC1120_LNA, .name = "LNA" },
1284 { .addr = CC1120_RXMIX, .name = "RXMIX" },
1285 { .addr = CC1120_XOSC5, .name = "XOSC5" },
1286 { .addr = CC1120_XOSC4, .name = "XOSC4" },
1287 { .addr = CC1120_XOSC3, .name = "XOSC3" },
1288 { .addr = CC1120_XOSC2, .name = "XOSC2" },
1289 { .addr = CC1120_XOSC1, .name = "XOSC1" },
1290 { .addr = CC1120_XOSC0, .name = "XOSC0" },
1291 { .addr = CC1120_ANALOG_SPARE, .name = "ANALOG_SPARE" },
1292 { .addr = CC1120_PA_CFG3, .name = "PA_CFG3" },
1293 { .addr = CC1120_WOR_TIME1, .name = "WOR_TIME1" },
1294 { .addr = CC1120_WOR_TIME0, .name = "WOR_TIME0" },
1295 { .addr = CC1120_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
1296 { .addr = CC1120_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
1297 { .addr = CC1120_BIST, .name = "BIST" },
1298 { .addr = CC1120_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
1299 { .addr = CC1120_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
1300 { .addr = CC1120_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
1301 { .addr = CC1120_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
1302 { .addr = CC1120_IQIE_I1, .name = "IQIE_I1" },
1303 { .addr = CC1120_IQIE_I0, .name = "IQIE_I0" },
1304 { .addr = CC1120_IQIE_Q1, .name = "IQIE_Q1" },
1305 { .addr = CC1120_IQIE_Q0, .name = "IQIE_Q0" },
1306 { .addr = CC1120_RSSI1, .name = "RSSI1" },
1307 { .addr = CC1120_RSSI0, .name = "RSSI0" },
1308 { .addr = CC1120_MARCSTATE, .name = "MARCSTATE" },
1309 { .addr = CC1120_LQI_VAL, .name = "LQI_VAL" },
1310 { .addr = CC1120_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
1311 { .addr = CC1120_DEM_STATUS, .name = "DEM_STATUS" },
1312 { .addr = CC1120_FREQOFF_EST1, .name = "FREQOFF_EST1" },
1313 { .addr = CC1120_FREQOFF_EST0, .name = "FREQOFF_EST0" },
1314 { .addr = CC1120_AGC_GAIN3, .name = "AGC_GAIN3" },
1315 { .addr = CC1120_AGC_GAIN2, .name = "AGC_GAIN2" },
1316 { .addr = CC1120_AGC_GAIN1, .name = "AGC_GAIN1" },
1317 { .addr = CC1120_AGC_GAIN0, .name = "AGC_GAIN0" },
1318 { .addr = CC1120_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
1319 { .addr = CC1120_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
1320 { .addr = CC1120_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
1321 { .addr = CC1120_RNDGEN, .name = "RNDGEN" },
1322 { .addr = CC1120_MAGN2, .name = "MAGN2" },
1323 { .addr = CC1120_MAGN1, .name = "MAGN1" },
1324 { .addr = CC1120_MAGN0, .name = "MAGN0" },
1325 { .addr = CC1120_ANG1, .name = "ANG1" },
1326 { .addr = CC1120_ANG0, .name = "ANG0" },
1327 { .addr = CC1120_CHFILT_I2, .name = "CHFILT_I2" },
1328 { .addr = CC1120_CHFILT_I1, .name = "CHFILT_I1" },
1329 { .addr = CC1120_CHFILT_I0, .name = "CHFILT_I0" },
1330 { .addr = CC1120_CHFILT_Q2, .name = "CHFILT_Q2" },
1331 { .addr = CC1120_CHFILT_Q1, .name = "CHFILT_Q1" },
1332 { .addr = CC1120_CHFILT_Q0, .name = "CHFILT_Q0" },
1333 { .addr = CC1120_GPIO_STATUS, .name = "GPIO_STATUS" },
1334 { .addr = CC1120_FSCAL_CTRL, .name = "FSCAL_CTRL" },
1335 { .addr = CC1120_PHASE_ADJUST, .name = "PHASE_ADJUST" },
1336 { .addr = CC1120_PARTNUMBER, .name = "PARTNUMBER" },
1337 { .addr = CC1120_PARTVERSION, .name = "PARTVERSION" },
1338 { .addr = CC1120_SERIAL_STATUS, .name = "SERIAL_STATUS" },
1339 { .addr = CC1120_RX_STATUS, .name = "RX_STATUS" },
1340 { .addr = CC1120_TX_STATUS, .name = "TX_STATUS" },
1341 { .addr = CC1120_MARC_STATUS1, .name = "MARC_STATUS1" },
1342 { .addr = CC1120_MARC_STATUS0, .name = "MARC_STATUS0" },
1343 { .addr = CC1120_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
1344 { .addr = CC1120_FSRF_TEST, .name = "FSRF_TEST" },
1345 { .addr = CC1120_PRE_TEST, .name = "PRE_TEST" },
1346 { .addr = CC1120_PRE_OVR, .name = "PRE_OVR" },
1347 { .addr = CC1120_ADC_TEST, .name = "ADC_TEST" },
1348 { .addr = CC1120_DVC_TEST, .name = "DVC_TEST" },
1349 { .addr = CC1120_ATEST, .name = "ATEST" },
1350 { .addr = CC1120_ATEST_LVDS, .name = "ATEST_LVDS" },
1351 { .addr = CC1120_ATEST_MODE, .name = "ATEST_MODE" },
1352 { .addr = CC1120_XOSC_TEST1, .name = "XOSC_TEST1" },
1353 { .addr = CC1120_XOSC_TEST0, .name = "XOSC_TEST0" },
1354 { .addr = CC1120_RXFIRST, .name = "RXFIRST" },
1355 { .addr = CC1120_TXFIRST, .name = "TXFIRST" },
1356 { .addr = CC1120_RXLAST, .name = "RXLAST" },
1357 { .addr = CC1120_TXLAST, .name = "TXLAST" },
1358 { .addr = CC1120_NUM_TXBYTES, .name = "NUM_TXBYTES" },
1359 { .addr = CC1120_NUM_RXBYTES, .name = "NUM_RXBYTES" },
1360 { .addr = CC1120_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
1361 { .addr = CC1120_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
1364 #define AO_NUM_CC1120_REG (sizeof ao_cc1120_reg / sizeof ao_cc1120_reg[0])
1366 static void ao_radio_show(void) {
1367 uint8_t status = ao_radio_status();
1371 status = ao_radio_status();
1372 printf ("Status: %02x\n", status);
1373 printf ("CHIP_RDY: %d\n", (status >> CC1120_STATUS_CHIP_RDY) & 1);
1374 printf ("STATE: %s\n", cc1120_state_name[(status >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK]);
1375 printf ("MARC: %02x\n", ao_radio_get_marc_status());
1377 for (i = 0; i < AO_NUM_CC1120_REG; i++)
1378 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name);
1380 printf("RX fast start: %u\n", rx_fast_start);
1381 printf("RX slow start: %u\n", rx_slow_start);
1382 printf("RX missed: %u\n", rx_missed);
1386 static void ao_radio_beep(void) {
1390 static void ao_radio_packet(void) {
1391 static const uint8_t packet[] = {
1393 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1394 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1395 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1396 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1402 ao_radio_send(packet, sizeof (packet));
1406 ao_radio_test_recv(void)
1411 if (ao_radio_recv(bytes, 34, 0)) {
1412 if (bytes[33] & 0x80)
1416 printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32]));
1417 for (b = 0; b < 32; b++)
1418 printf (" %02x", bytes[b]);
1424 #include <ao_aprs.h>
1429 ao_packet_slave_stop();
1435 static const struct ao_cmds ao_radio_cmds[] = {
1436 { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
1439 { ao_radio_aprs, "G\0Send APRS packet" },
1441 { ao_radio_show, "R\0Show CC1120 status" },
1442 { ao_radio_beep, "b\0Emit an RDF beacon" },
1443 { ao_radio_packet, "p\0Send a test packet" },
1444 { ao_radio_test_recv, "q\0Recv a test packet" },
1452 ao_radio_configured = 0;
1453 ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN));
1456 AO_CC1120_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN));
1457 for (i = 0; i < 10000; i++) {
1458 if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0)
1461 AO_CC1120_SPI_CS_PORT->bsrr = (1 << AO_CC1120_SPI_CS_PIN);
1463 ao_panic(AO_PANIC_SELF_TEST_CC1120);
1466 /* Enable the EXTI interrupt for the appropriate pin */
1467 ao_enable_port(AO_CC1120_INT_PORT);
1468 ao_exti_setup(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1469 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
1472 /* Enable the hacked up GPIO3 pin */
1473 ao_enable_port(AO_CC1120_MCU_WAKEUP_PORT);
1474 ao_exti_setup(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN,
1475 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED,
1476 ao_radio_mcu_wakeup_isr);
1478 ao_cmd_register(&ao_radio_cmds[0]);