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_select() ao_spi_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS,AO_SPI_SPEED_4MHz)
45 #define ao_radio_deselect() ao_spi_put_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS)
46 #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1120_SPI_BUS)
47 #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1120_SPI_BUS)
48 #define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1120_SPI_BUS)
49 #define ao_radio_duplex(o,i,l) ao_spi_duplex((o), (i), (l), AO_CC1120_SPI_BUS)
52 ao_radio_reg_read(uint16_t addr)
58 printf("\t\tao_radio_reg_read (%04x): ", addr); flush();
60 if (CC1120_IS_EXTENDED(addr)) {
61 data[0] = ((1 << CC1120_READ) |
67 data[0] = ((1 << CC1120_READ) |
73 ao_radio_spi_send(data, d);
74 ao_radio_spi_recv(data, 1);
77 printf (" %02x\n", data[0]);
83 ao_radio_reg_write(uint16_t addr, uint8_t value)
89 printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value);
91 if (CC1120_IS_EXTENDED(addr)) {
92 data[0] = ((0 << CC1120_READ) |
98 data[0] = ((0 << CC1120_READ) |
105 ao_radio_spi_send(data, d+1);
110 ao_radio_burst_read_start (uint16_t addr)
115 if (CC1120_IS_EXTENDED(addr)) {
116 data[0] = ((1 << CC1120_READ) |
117 (1 << CC1120_BURST) |
122 data[0] = ((1 << CC1120_READ) |
123 (1 << CC1120_BURST) |
128 ao_radio_spi_send(data, d);
132 ao_radio_burst_read_stop (void)
139 ao_radio_strobe(uint8_t addr)
144 printf("\t\tao_radio_strobe (%02x): ", addr); flush();
147 ao_radio_duplex(&addr, &in, 1);
150 printf("%02x\n", in); flush();
156 ao_radio_fifo_read(uint8_t *data, uint8_t len)
158 uint8_t addr = ((1 << CC1120_READ) |
159 (1 << CC1120_BURST) |
164 ao_radio_duplex(&addr, &status, 1);
165 ao_radio_spi_recv(data, len);
171 ao_radio_fifo_write_start(void)
173 uint8_t addr = ((0 << CC1120_READ) |
174 (1 << CC1120_BURST) |
179 ao_radio_duplex(&addr, &status, 1);
183 static inline uint8_t ao_radio_fifo_write_stop(uint8_t status) {
189 ao_radio_fifo_write(uint8_t *data, uint8_t len)
191 uint8_t status = ao_radio_fifo_write_start();
192 ao_radio_spi_send(data, len);
193 return ao_radio_fifo_write_stop(status);
197 ao_radio_fifo_write_fixed(uint8_t data, uint8_t len)
199 uint8_t status = ao_radio_fifo_write_start();
200 ao_radio_spi_send_fixed(data, len);
201 return ao_radio_fifo_write_stop(status);
205 ao_radio_tx_fifo_space(void)
207 return CC1120_FIFO_SIZE - ao_radio_reg_read(CC1120_NUM_TXBYTES);
211 ao_radio_status(void)
213 return ao_radio_strobe (CC1120_SNOP);
217 ao_radio_recv_abort(void)
220 ao_wakeup(&ao_radio_wake);
223 #define ao_radio_rdf_value 0x55
226 ao_radio_get_marc_status(void)
228 return ao_radio_reg_read(CC1120_MARC_STATUS1);
232 ao_radio_mcu_wakeup_isr(void)
234 ao_radio_mcu_wake = 1;
235 ao_wakeup(&ao_radio_wake);
240 ao_radio_check_marc_status(void)
242 ao_radio_mcu_wake = 0;
243 ao_radio_marc_status = ao_radio_get_marc_status();
245 /* Anyt other than 'tx/rx finished' means an error occurred */
246 if (ao_radio_marc_status & ~(CC1120_MARC_STATUS1_TX_FINISHED|CC1120_MARC_STATUS1_RX_FINISHED))
248 if (ao_radio_marc_status & (CC1120_MARC_STATUS1_TX_FINISHED))
249 ao_radio_tx_finished = 1;
255 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
257 ao_wakeup(&ao_radio_wake);
261 ao_radio_start_tx(void)
263 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr);
264 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
265 ao_exti_enable(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN);
266 ao_radio_tx_finished = 0;
267 ao_radio_strobe(CC1120_STX);
274 uint8_t state = ao_radio_strobe(CC1120_SIDLE);
275 if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_IDLE)
277 if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_TX_FIFO_ERROR)
278 ao_radio_strobe(CC1120_SFTX);
280 /* Flush any pending TX bytes */
281 ao_radio_strobe(CC1120_SFTX);
285 * Packet deviation is 20.5kHz
287 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
289 * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz
292 #define PACKET_DEV_E 5
293 #define PACKET_DEV_M 80
296 * For our packet data, set the symbol rate to 38400 Baud
298 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
299 * Rdata = -------------------------------------- * fosc
303 * DATARATE_M = 239914
306 #define PACKET_DRATE_E 9
307 #define PACKET_DRATE_M 239914
309 static const uint16_t packet_setup[] = {
310 CC1120_DEVIATION_M, PACKET_DEV_M,
311 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
312 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
313 (PACKET_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
314 CC1120_DRATE2, ((PACKET_DRATE_E << CC1120_DRATE2_DATARATE_E) |
315 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
316 CC1120_DRATE1, ((PACKET_DRATE_M >> 8) & 0xff),
317 CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff),
318 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
319 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
320 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
321 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
322 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
323 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
324 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
325 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
326 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
327 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
328 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
329 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
330 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
331 CC1120_SOFT_TX_DATA_CFG,((0 << CC1120_SOFT_TX_DATA_CFG_SOFT_TX_DATA_EN)),
332 CC1120_MDMCFG1, ((0 << CC1120_MDMCFG1_CARRIER_SENSE_GATE) |
333 (1 << CC1120_MDMCFG1_FIFO_EN) |
334 (0 << CC1120_MDMCFG1_MANCHESTER_EN) |
335 (0 << CC1120_MDMCFG1_INVERT_DATA_EN) |
336 (0 << CC1120_MDMCFG1_COLLISION_DETECT_EN) |
337 (CC1120_MDMCFG1_DVGA_GAIN_9 << CC1120_MDMCFG1_DVGA_GAIN) |
338 (0 << CC1120_MDMCFG1_SINGLE_ADC_EN)),
339 CC1120_MDMCFG0, (0x5),
340 AO_CC1120_MARC_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP,
343 static const uint16_t packet_tx_setup[] = {
344 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
345 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
346 AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG,
349 static const uint16_t packet_rx_setup[] = {
350 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
351 (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT)),
352 AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT,
356 * RDF deviation is 5kHz
358 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
360 * 32e6Hz / (2 ** 24) * (256 + 71) * (2 ** 3) = 4989
365 #define RDF_PACKET_LEN 50
368 * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
370 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
371 * Rdata = -------------------------------------- * fosc
377 * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
379 #define RDF_DRATE_E 5
380 #define RDF_DRATE_M 25166
381 #define RDF_PACKET_LEN 50
383 static const uint16_t rdf_setup[] = {
384 CC1120_DEVIATION_M, RDF_DEV_M,
385 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
386 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
387 (RDF_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
388 CC1120_DRATE2, ((RDF_DRATE_E << CC1120_DRATE2_DATARATE_E) |
389 (((RDF_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
390 CC1120_DRATE1, ((RDF_DRATE_M >> 8) & 0xff),
391 CC1120_DRATE0, ((RDF_DRATE_M >> 0) & 0xff),
392 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
393 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
394 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
395 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
396 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
397 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
398 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
399 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
400 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
401 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
402 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
403 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
404 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
405 CC1120_MDMCFG1, ((0 << CC1120_MDMCFG1_CARRIER_SENSE_GATE) |
406 (1 << CC1120_MDMCFG1_FIFO_EN) |
407 (0 << CC1120_MDMCFG1_MANCHESTER_EN) |
408 (0 << CC1120_MDMCFG1_INVERT_DATA_EN) |
409 (0 << CC1120_MDMCFG1_COLLISION_DETECT_EN) |
410 (CC1120_MDMCFG1_DVGA_GAIN_9 << CC1120_MDMCFG1_DVGA_GAIN) |
411 (0 << CC1120_MDMCFG1_SINGLE_ADC_EN)),
412 CC1120_MDMCFG0, (0x5),
413 CC1120_SOFT_TX_DATA_CFG,((0 << CC1120_SOFT_TX_DATA_CFG_SOFT_TX_DATA_EN)),
417 * APRS deviation is 3kHz
419 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
421 * 32e6Hz / (2 ** 24) * (256 + 137) * (2 ** 2) = 2998Hz
425 #define APRS_DEV_M 137
428 * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate)
430 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
431 * Rdata = -------------------------------------- * fosc
434 * DATARATE_M = 239914
437 * Rdata = 9599.998593330383301
440 #define APRS_DRATE_E 7
441 #define APRS_DRATE_M 239914
443 static const uint16_t aprs_setup[] = {
444 CC1120_DEVIATION_M, APRS_DEV_M,
445 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
446 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
447 (APRS_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
448 CC1120_DRATE2, ((APRS_DRATE_E << CC1120_DRATE2_DATARATE_E) |
449 (((APRS_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
450 CC1120_DRATE1, ((APRS_DRATE_M >> 8) & 0xff),
451 CC1120_DRATE0, ((APRS_DRATE_M >> 0) & 0xff),
452 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
453 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
454 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
455 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
456 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
457 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
458 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
459 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
460 CC1120_MDMCFG1, ((0 << CC1120_MDMCFG1_CARRIER_SENSE_GATE) |
461 (1 << CC1120_MDMCFG1_FIFO_EN) |
462 (0 << CC1120_MDMCFG1_MANCHESTER_EN) |
463 (0 << CC1120_MDMCFG1_INVERT_DATA_EN) |
464 (0 << CC1120_MDMCFG1_COLLISION_DETECT_EN) |
465 (CC1120_MDMCFG1_DVGA_GAIN_9 << CC1120_MDMCFG1_DVGA_GAIN) |
466 (0 << CC1120_MDMCFG1_SINGLE_ADC_EN)),
467 CC1120_MDMCFG0, (0x5),
468 CC1120_SOFT_TX_DATA_CFG,((0 << CC1120_SOFT_TX_DATA_CFG_SOFT_TX_DATA_EN)),
472 * For Test mode, we want an unmodulated carrier. To do that,
473 * we enable soft TX mode and set the deviation to zero
476 static const uint16_t test_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_TRANSPARENT_SERIAL << 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_SOFT_TX_DATA_CFG,((1 << CC1120_SOFT_TX_DATA_CFG_SOFT_TX_DATA_EN)),
494 CC1120_MDMCFG1, ((0 << CC1120_MDMCFG1_CARRIER_SENSE_GATE) |
495 (0 << CC1120_MDMCFG1_FIFO_EN) |
496 (0 << CC1120_MDMCFG1_MANCHESTER_EN) |
497 (0 << CC1120_MDMCFG1_INVERT_DATA_EN) |
498 (0 << CC1120_MDMCFG1_COLLISION_DETECT_EN) |
499 (CC1120_MDMCFG1_DVGA_GAIN_9 << CC1120_MDMCFG1_DVGA_GAIN) |
500 (0 << CC1120_MDMCFG1_SINGLE_ADC_EN)),
501 CC1120_MDMCFG0, (0x45),
502 CC1120_SOFT_TX_DATA_IN, 0,
505 #define AO_PKT_CFG0_INFINITE ((0 << CC1120_PKT_CFG0_RESERVED7) | \
506 (CC1120_PKT_CFG0_LENGTH_CONFIG_INFINITE << CC1120_PKT_CFG0_LENGTH_CONFIG) | \
507 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | \
508 (0 << CC1120_PKT_CFG0_UART_MODE_EN) | \
509 (0 << CC1120_PKT_CFG0_UART_SWAP_EN))
511 #define AO_PKT_CFG0_FIXED ((0 << CC1120_PKT_CFG0_RESERVED7) | \
512 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) | \
513 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | \
514 (0 << CC1120_PKT_CFG0_UART_MODE_EN) | \
515 (0 << CC1120_PKT_CFG0_UART_SWAP_EN))
517 static uint16_t ao_radio_mode;
519 #define AO_RADIO_MODE_BITS_PACKET 1
520 #define AO_RADIO_MODE_BITS_PACKET_TX 2
521 #define AO_RADIO_MODE_BITS_TX_BUF 4
522 #define AO_RADIO_MODE_BITS_TX_FINISH 8
523 #define AO_RADIO_MODE_BITS_PACKET_RX 16
524 #define AO_RADIO_MODE_BITS_RDF 32
525 #define AO_RADIO_MODE_BITS_APRS 64
526 #define AO_RADIO_MODE_BITS_TEST 128
527 #define AO_RADIO_MODE_BITS_INFINITE 256
528 #define AO_RADIO_MODE_BITS_FIXED 512
530 #define AO_RADIO_MODE_NONE 0
531 #define AO_RADIO_MODE_PACKET_TX_BUF (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_BUF)
532 #define AO_RADIO_MODE_PACKET_TX_FINISH (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_FINISH)
533 #define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_RX)
534 #define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_TX_FINISH)
535 #define AO_RADIO_MODE_APRS_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
536 #define AO_RADIO_MODE_APRS_LAST_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_BUF)
537 #define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
538 #define AO_RADIO_MODE_TEST (AO_RADIO_MODE_BITS_TEST | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
541 ao_radio_set_mode(uint16_t new_mode)
546 if (new_mode == ao_radio_mode)
549 changes = new_mode & (~ao_radio_mode);
550 if (changes & AO_RADIO_MODE_BITS_PACKET)
551 for (i = 0; i < sizeof (packet_setup) / sizeof (packet_setup[0]); i += 2)
552 ao_radio_reg_write(packet_setup[i], packet_setup[i+1]);
554 if (changes & AO_RADIO_MODE_BITS_PACKET_TX)
555 for (i = 0; i < sizeof (packet_tx_setup) / sizeof (packet_tx_setup[0]); i += 2)
556 ao_radio_reg_write(packet_tx_setup[i], packet_tx_setup[i+1]);
558 if (changes & AO_RADIO_MODE_BITS_TX_BUF)
559 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_TXFIFO_THR);
561 if (changes & AO_RADIO_MODE_BITS_TX_FINISH)
562 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG);
564 if (changes & AO_RADIO_MODE_BITS_PACKET_RX)
565 for (i = 0; i < sizeof (packet_rx_setup) / sizeof (packet_rx_setup[0]); i += 2)
566 ao_radio_reg_write(packet_rx_setup[i], packet_rx_setup[i+1]);
568 if (changes & AO_RADIO_MODE_BITS_RDF)
569 for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2)
570 ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]);
572 if (changes & AO_RADIO_MODE_BITS_APRS)
573 for (i = 0; i < sizeof (aprs_setup) / sizeof (aprs_setup[0]); i += 2)
574 ao_radio_reg_write(aprs_setup[i], aprs_setup[i+1]);
576 if (changes & AO_RADIO_MODE_BITS_TEST)
577 for (i = 0; i < sizeof (test_setup) / sizeof (test_setup[0]); i += 2)
578 ao_radio_reg_write(test_setup[i], test_setup[i+1]);
580 if (changes & AO_RADIO_MODE_BITS_INFINITE)
581 ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_INFINITE);
583 if (changes & AO_RADIO_MODE_BITS_FIXED)
584 ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_FIXED);
586 ao_radio_mode = new_mode;
589 static const uint16_t radio_setup[] = {
590 #include "ao_cc1120_CC1120.h"
593 static uint8_t ao_radio_configured = 0;
600 ao_radio_strobe(CC1120_SRES);
602 for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2)
603 ao_radio_reg_write(radio_setup[i], radio_setup[i+1]);
609 ao_radio_configured = 1;
613 ao_radio_set_len(uint8_t len)
615 static uint8_t last_len;
617 if (len != last_len) {
618 ao_radio_reg_write(CC1120_PKT_LEN, len);
624 ao_radio_get(uint8_t len)
626 static uint32_t last_radio_setting;
628 ao_mutex_get(&ao_radio_mutex);
630 if (!ao_radio_configured)
632 if (ao_config.radio_setting != last_radio_setting) {
633 ao_radio_reg_write(CC1120_FREQ2, ao_config.radio_setting >> 16);
634 ao_radio_reg_write(CC1120_FREQ1, ao_config.radio_setting >> 8);
635 ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting);
636 last_radio_setting = ao_config.radio_setting;
638 ao_radio_set_len(len);
641 #define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
644 ao_rdf_start(uint8_t len)
649 ao_radio_set_mode(AO_RADIO_MODE_RDF);
659 ao_arch_block_interrupts();
660 while (!ao_radio_wake && !ao_radio_abort && !ao_radio_mcu_wake)
661 ao_sleep(&ao_radio_wake);
662 ao_arch_release_interrupts();
663 if (ao_radio_mcu_wake)
664 ao_radio_check_marc_status();
673 ao_rdf_start(AO_RADIO_RDF_LEN);
675 ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN);
681 ao_radio_continuity(uint8_t c)
686 ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN);
688 status = ao_radio_fifo_write_start();
689 for (i = 0; i < 3; i++) {
690 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
692 ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN);
694 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN);
696 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
697 status = ao_radio_fifo_write_stop(status);
703 ao_radio_rdf_abort(void)
706 ao_wakeup(&ao_radio_wake);
710 ao_radio_test_cmd(void)
713 static uint8_t radio_on;
715 if (ao_cmd_lex_c != '\n') {
717 mode = (uint8_t) ao_cmd_lex_u32;
720 if ((mode & 2) && !radio_on) {
722 ao_monitor_disable();
725 ao_packet_slave_stop();
728 ao_radio_set_mode(AO_RADIO_MODE_TEST);
729 ao_radio_strobe(CC1120_STX);
732 for (t = 0; t < 10; t++) {
733 printf ("status: %02x\n", ao_radio_status());
734 ao_delay(AO_MS_TO_TICKS(100));
741 printf ("Hit a character to stop..."); flush();
745 if ((mode & 1) && radio_on) {
756 ao_radio_wait_isr(uint16_t timeout)
760 ao_arch_block_interrupts();
761 while (!ao_radio_wake && !ao_radio_mcu_wake && !ao_radio_abort)
762 if (ao_sleep(&ao_radio_wake))
764 ao_arch_release_interrupts();
767 if (ao_radio_mcu_wake)
768 ao_radio_check_marc_status();
772 ao_radio_wait_tx(uint8_t wait_fifo)
774 uint8_t fifo_space = 0;
777 ao_radio_wait_isr(0);
780 fifo_space = ao_radio_tx_fifo_space();
781 } while (!fifo_space && !ao_radio_abort);
785 static uint8_t tx_data[(AO_RADIO_MAX_SEND + 4) * 2];
788 ao_radio_send(const void *d, uint8_t size)
791 uint8_t *e = tx_data;
798 encode_len = ao_fec_encode(d, size, tx_data);
800 ao_radio_get(encode_len);
804 /* Flush any pending TX bytes */
805 ao_radio_strobe(CC1120_SFTX);
808 fifo_space = CC1120_FIFO_SIZE;
810 this_len = encode_len;
813 if (this_len > fifo_space) {
814 this_len = fifo_space;
815 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_BUF);
817 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_FINISH);
820 ao_radio_fifo_write(e, this_len);
822 encode_len -= this_len;
828 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
831 fifo_space = ao_radio_wait_tx(encode_len != 0);
832 if (ao_radio_abort) {
837 while (started && !ao_radio_abort && !ao_radio_tx_finished)
838 ao_radio_wait_isr(0);
842 #define AO_RADIO_LOTS 64
845 ao_radio_send_aprs(ao_radio_fill_func fill)
847 uint8_t buf[AO_RADIO_LOTS], *b;
855 fifo_space = CC1120_FIFO_SIZE;
857 cnt = (*fill)(buf, sizeof(buf));
864 /* At the last buffer, set the total length */
866 ao_radio_set_len(total & 0xff);
870 uint8_t this_len = cnt;
872 /* Wait for some space in the fifo */
873 while (!ao_radio_abort && (fifo_space = ao_radio_tx_fifo_space()) == 0) {
875 ao_radio_wait_isr(0);
879 if (this_len > fifo_space)
880 this_len = fifo_space;
886 ao_radio_set_mode(AO_RADIO_MODE_APRS_LAST_BUF);
888 ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
890 ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
892 ao_radio_fifo_write(b, this_len);
899 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
901 if (ao_radio_abort) {
905 /* Wait for the transmitter to go idle */
907 ao_radio_wait_isr(0);
912 static uint8_t rx_data[(AO_RADIO_MAX_RECV + 4) * 2 * 8];
913 static uint16_t rx_data_count;
914 static uint16_t rx_data_consumed;
915 static uint16_t rx_data_cur;
916 static uint8_t rx_ignore;
917 static uint8_t rx_waiting;
920 static uint32_t rx_start_tick, rx_packet_tick, rx_done_tick, rx_last_done_tick;
922 uint32_t ao_rx_start_tick, ao_rx_packet_tick, ao_rx_done_tick, ao_rx_last_done_tick;
924 #include <ao_profile.h>
928 ao_radio_rx_isr(void)
932 d = AO_CC1120_SPI.dr;
933 AO_CC1120_SPI.dr = 0;
934 if (rx_ignore == 0) {
935 if (rx_data_cur >= rx_data_count)
936 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
938 rx_data[rx_data_cur++] = d;
939 if (rx_waiting && rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) {
942 rx_packet_tick = ao_profile_tick();
943 if (rx_data_cur < rx_data_count)
947 ao_wakeup(&ao_radio_wake);
955 ao_radio_rx_wait(void)
958 if (ao_radio_mcu_wake)
959 ao_radio_check_marc_status();
960 ao_alarm(AO_MS_TO_TICKS(100));
961 ao_arch_block_interrupts();
963 while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&
967 if (ao_sleep(&ao_radio_wake))
971 ao_arch_release_interrupts();
973 } while (ao_radio_mcu_wake);
976 rx_data_consumed += AO_FEC_DECODE_BLOCK;
978 return rx_data_cur - rx_data_consumed;
980 return AO_FEC_DECODE_BLOCK;
984 ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout)
988 uint8_t radio_rssi = 0;
991 static int been_here = 0;
993 size -= 2; /* status bytes */
994 if (size > AO_RADIO_MAX_RECV) {
995 ao_delay(AO_SEC_TO_TICKS(1));
999 rx_start_tick = ao_profile_tick();
1002 len = size + 2; /* CRC bytes */
1003 len += 1 + ~(len & 1); /* 1 or two pad bytes */
1004 len *= 2; /* 1/2 rate convolution */
1005 rx_data_count = len * 8; /* bytes to bits */
1007 rx_data_consumed = 0;
1010 /* Must be set before changing the frequency; any abort
1011 * after the frequency is set needs to terminate the read
1012 * so that the registers can be reprogrammed
1016 /* configure interrupt pin */
1018 ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
1021 ao_radio_mcu_wake = 0;
1023 AO_CC1120_SPI.cr2 = 0;
1025 /* clear any RXNE */
1026 (void) AO_CC1120_SPI.dr;
1028 /* Have the radio signal when the preamble quality goes high */
1029 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_PQT_REACHED);
1030 ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1031 AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_HIGH);
1032 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr);
1033 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
1034 ao_exti_enable(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN);
1036 ao_radio_strobe(CC1120_SRX);
1038 /* Wait for the preamble to appear */
1039 ao_radio_wait_isr(timeout);
1040 if (ao_radio_abort) {
1045 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT);
1046 ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1047 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
1049 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
1050 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
1052 ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
1054 ret = ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait);
1056 ao_radio_burst_read_stop();
1059 /* Convert from 'real' rssi to cc1111-style values */
1061 rssi0 = ao_radio_reg_read(CC1120_RSSI0);
1063 int8_t rssi = ao_radio_reg_read(CC1120_RSSI1);
1064 ao_radio_rssi = rssi;
1066 /* Bound it to the representable range */
1069 radio_rssi = AO_RADIO_FROM_RSSI (rssi);
1072 ao_radio_strobe(CC1120_SIDLE);
1076 /* Store the received RSSI value; the crc-OK byte is already done */
1078 ((uint8_t *) d)[size] = radio_rssi;
1081 rx_last_done_tick = rx_done_tick;
1082 rx_done_tick = ao_profile_tick();
1084 ao_rx_start_tick = rx_start_tick;
1085 ao_rx_packet_tick = rx_packet_tick;
1086 ao_rx_done_tick = rx_done_tick;
1087 ao_rx_last_done_tick = rx_last_done_tick;
1095 static char *cc1120_state_name[] = {
1096 [CC1120_STATUS_STATE_IDLE] = "IDLE",
1097 [CC1120_STATUS_STATE_RX] = "RX",
1098 [CC1120_STATUS_STATE_TX] = "TX",
1099 [CC1120_STATUS_STATE_FSTXON] = "FSTXON",
1100 [CC1120_STATUS_STATE_CALIBRATE] = "CALIBRATE",
1101 [CC1120_STATUS_STATE_SETTLING] = "SETTLING",
1102 [CC1120_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
1103 [CC1120_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
1106 struct ao_cc1120_reg {
1111 const static struct ao_cc1120_reg ao_cc1120_reg[] = {
1112 { .addr = CC1120_IOCFG3, .name = "IOCFG3" },
1113 { .addr = CC1120_IOCFG2, .name = "IOCFG2" },
1114 { .addr = CC1120_IOCFG1, .name = "IOCFG1" },
1115 { .addr = CC1120_IOCFG0, .name = "IOCFG0" },
1116 { .addr = CC1120_SYNC3, .name = "SYNC3" },
1117 { .addr = CC1120_SYNC2, .name = "SYNC2" },
1118 { .addr = CC1120_SYNC1, .name = "SYNC1" },
1119 { .addr = CC1120_SYNC0, .name = "SYNC0" },
1120 { .addr = CC1120_SYNC_CFG1, .name = "SYNC_CFG1" },
1121 { .addr = CC1120_SYNC_CFG0, .name = "SYNC_CFG0" },
1122 { .addr = CC1120_DEVIATION_M, .name = "DEVIATION_M" },
1123 { .addr = CC1120_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
1124 { .addr = CC1120_DCFILT_CFG, .name = "DCFILT_CFG" },
1125 { .addr = CC1120_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
1126 { .addr = CC1120_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
1127 { .addr = CC1120_FREQ_IF_CFG, .name = "FREQ_IF_CFG" },
1128 { .addr = CC1120_IQIC, .name = "IQIC" },
1129 { .addr = CC1120_CHAN_BW, .name = "CHAN_BW" },
1130 { .addr = CC1120_MDMCFG1, .name = "MDMCFG1" },
1131 { .addr = CC1120_MDMCFG0, .name = "MDMCFG0" },
1132 { .addr = CC1120_DRATE2, .name = "DRATE2" },
1133 { .addr = CC1120_DRATE1, .name = "DRATE1" },
1134 { .addr = CC1120_DRATE0, .name = "DRATE0" },
1135 { .addr = CC1120_AGC_REF, .name = "AGC_REF" },
1136 { .addr = CC1120_AGC_CS_THR, .name = "AGC_CS_THR" },
1137 { .addr = CC1120_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
1138 { .addr = CC1120_AGC_CFG3, .name = "AGC_CFG3" },
1139 { .addr = CC1120_AGC_CFG2, .name = "AGC_CFG2" },
1140 { .addr = CC1120_AGC_CFG1, .name = "AGC_CFG1" },
1141 { .addr = CC1120_AGC_CFG0, .name = "AGC_CFG0" },
1142 { .addr = CC1120_FIFO_CFG, .name = "FIFO_CFG" },
1143 { .addr = CC1120_DEV_ADDR, .name = "DEV_ADDR" },
1144 { .addr = CC1120_SETTLING_CFG, .name = "SETTLING_CFG" },
1145 { .addr = CC1120_FS_CFG, .name = "FS_CFG" },
1146 { .addr = CC1120_WOR_CFG1, .name = "WOR_CFG1" },
1147 { .addr = CC1120_WOR_CFG0, .name = "WOR_CFG0" },
1148 { .addr = CC1120_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
1149 { .addr = CC1120_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
1150 { .addr = CC1120_PKT_CFG2, .name = "PKT_CFG2" },
1151 { .addr = CC1120_PKT_CFG1, .name = "PKT_CFG1" },
1152 { .addr = CC1120_PKT_CFG0, .name = "PKT_CFG0" },
1153 { .addr = CC1120_RFEND_CFG1, .name = "RFEND_CFG1" },
1154 { .addr = CC1120_RFEND_CFG0, .name = "RFEND_CFG0" },
1155 { .addr = CC1120_PA_CFG2, .name = "PA_CFG2" },
1156 { .addr = CC1120_PA_CFG1, .name = "PA_CFG1" },
1157 { .addr = CC1120_PA_CFG0, .name = "PA_CFG0" },
1158 { .addr = CC1120_PKT_LEN, .name = "PKT_LEN" },
1159 { .addr = CC1120_IF_MIX_CFG, .name = "IF_MIX_CFG" },
1160 { .addr = CC1120_FREQOFF_CFG, .name = "FREQOFF_CFG" },
1161 { .addr = CC1120_TOC_CFG, .name = "TOC_CFG" },
1162 { .addr = CC1120_MARC_SPARE, .name = "MARC_SPARE" },
1163 { .addr = CC1120_ECG_CFG, .name = "ECG_CFG" },
1164 { .addr = CC1120_SOFT_TX_DATA_CFG, .name = "SOFT_TX_DATA_CFG" },
1165 { .addr = CC1120_EXT_CTRL, .name = "EXT_CTRL" },
1166 { .addr = CC1120_RCCAL_FINE, .name = "RCCAL_FINE" },
1167 { .addr = CC1120_RCCAL_COARSE, .name = "RCCAL_COARSE" },
1168 { .addr = CC1120_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
1169 { .addr = CC1120_FREQOFF1, .name = "FREQOFF1" },
1170 { .addr = CC1120_FREQOFF0, .name = "FREQOFF0" },
1171 { .addr = CC1120_FREQ2, .name = "FREQ2" },
1172 { .addr = CC1120_FREQ1, .name = "FREQ1" },
1173 { .addr = CC1120_FREQ0, .name = "FREQ0" },
1174 { .addr = CC1120_IF_ADC2, .name = "IF_ADC2" },
1175 { .addr = CC1120_IF_ADC1, .name = "IF_ADC1" },
1176 { .addr = CC1120_IF_ADC0, .name = "IF_ADC0" },
1177 { .addr = CC1120_FS_DIG1, .name = "FS_DIG1" },
1178 { .addr = CC1120_FS_DIG0, .name = "FS_DIG0" },
1179 { .addr = CC1120_FS_CAL3, .name = "FS_CAL3" },
1180 { .addr = CC1120_FS_CAL2, .name = "FS_CAL2" },
1181 { .addr = CC1120_FS_CAL1, .name = "FS_CAL1" },
1182 { .addr = CC1120_FS_CAL0, .name = "FS_CAL0" },
1183 { .addr = CC1120_FS_CHP, .name = "FS_CHP" },
1184 { .addr = CC1120_FS_DIVTWO, .name = "FS_DIVTWO" },
1185 { .addr = CC1120_FS_DSM1, .name = "FS_DSM1" },
1186 { .addr = CC1120_FS_DSM0, .name = "FS_DSM0" },
1187 { .addr = CC1120_FS_DVC1, .name = "FS_DVC1" },
1188 { .addr = CC1120_FS_DVC0, .name = "FS_DVC0" },
1189 { .addr = CC1120_FS_LBI, .name = "FS_LBI" },
1190 { .addr = CC1120_FS_PFD, .name = "FS_PFD" },
1191 { .addr = CC1120_FS_PRE, .name = "FS_PRE" },
1192 { .addr = CC1120_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
1193 { .addr = CC1120_FS_SPARE, .name = "FS_SPARE" },
1194 { .addr = CC1120_FS_VCO4, .name = "FS_VCO4" },
1195 { .addr = CC1120_FS_VCO3, .name = "FS_VCO3" },
1196 { .addr = CC1120_FS_VCO2, .name = "FS_VCO2" },
1197 { .addr = CC1120_FS_VCO1, .name = "FS_VCO1" },
1198 { .addr = CC1120_FS_VCO0, .name = "FS_VCO0" },
1199 { .addr = CC1120_GBIAS6, .name = "GBIAS6" },
1200 { .addr = CC1120_GBIAS5, .name = "GBIAS5" },
1201 { .addr = CC1120_GBIAS4, .name = "GBIAS4" },
1202 { .addr = CC1120_GBIAS3, .name = "GBIAS3" },
1203 { .addr = CC1120_GBIAS2, .name = "GBIAS2" },
1204 { .addr = CC1120_GBIAS1, .name = "GBIAS1" },
1205 { .addr = CC1120_GBIAS0, .name = "GBIAS0" },
1206 { .addr = CC1120_IFAMP, .name = "IFAMP" },
1207 { .addr = CC1120_LNA, .name = "LNA" },
1208 { .addr = CC1120_RXMIX, .name = "RXMIX" },
1209 { .addr = CC1120_XOSC5, .name = "XOSC5" },
1210 { .addr = CC1120_XOSC4, .name = "XOSC4" },
1211 { .addr = CC1120_XOSC3, .name = "XOSC3" },
1212 { .addr = CC1120_XOSC2, .name = "XOSC2" },
1213 { .addr = CC1120_XOSC1, .name = "XOSC1" },
1214 { .addr = CC1120_XOSC0, .name = "XOSC0" },
1215 { .addr = CC1120_ANALOG_SPARE, .name = "ANALOG_SPARE" },
1216 { .addr = CC1120_PA_CFG3, .name = "PA_CFG3" },
1217 { .addr = CC1120_WOR_TIME1, .name = "WOR_TIME1" },
1218 { .addr = CC1120_WOR_TIME0, .name = "WOR_TIME0" },
1219 { .addr = CC1120_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
1220 { .addr = CC1120_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
1221 { .addr = CC1120_BIST, .name = "BIST" },
1222 { .addr = CC1120_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
1223 { .addr = CC1120_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
1224 { .addr = CC1120_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
1225 { .addr = CC1120_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
1226 { .addr = CC1120_IQIE_I1, .name = "IQIE_I1" },
1227 { .addr = CC1120_IQIE_I0, .name = "IQIE_I0" },
1228 { .addr = CC1120_IQIE_Q1, .name = "IQIE_Q1" },
1229 { .addr = CC1120_IQIE_Q0, .name = "IQIE_Q0" },
1230 { .addr = CC1120_RSSI1, .name = "RSSI1" },
1231 { .addr = CC1120_RSSI0, .name = "RSSI0" },
1232 { .addr = CC1120_MARCSTATE, .name = "MARCSTATE" },
1233 { .addr = CC1120_LQI_VAL, .name = "LQI_VAL" },
1234 { .addr = CC1120_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
1235 { .addr = CC1120_DEM_STATUS, .name = "DEM_STATUS" },
1236 { .addr = CC1120_FREQOFF_EST1, .name = "FREQOFF_EST1" },
1237 { .addr = CC1120_FREQOFF_EST0, .name = "FREQOFF_EST0" },
1238 { .addr = CC1120_AGC_GAIN3, .name = "AGC_GAIN3" },
1239 { .addr = CC1120_AGC_GAIN2, .name = "AGC_GAIN2" },
1240 { .addr = CC1120_AGC_GAIN1, .name = "AGC_GAIN1" },
1241 { .addr = CC1120_AGC_GAIN0, .name = "AGC_GAIN0" },
1242 { .addr = CC1120_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
1243 { .addr = CC1120_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
1244 { .addr = CC1120_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
1245 { .addr = CC1120_RNDGEN, .name = "RNDGEN" },
1246 { .addr = CC1120_MAGN2, .name = "MAGN2" },
1247 { .addr = CC1120_MAGN1, .name = "MAGN1" },
1248 { .addr = CC1120_MAGN0, .name = "MAGN0" },
1249 { .addr = CC1120_ANG1, .name = "ANG1" },
1250 { .addr = CC1120_ANG0, .name = "ANG0" },
1251 { .addr = CC1120_CHFILT_I2, .name = "CHFILT_I2" },
1252 { .addr = CC1120_CHFILT_I1, .name = "CHFILT_I1" },
1253 { .addr = CC1120_CHFILT_I0, .name = "CHFILT_I0" },
1254 { .addr = CC1120_CHFILT_Q2, .name = "CHFILT_Q2" },
1255 { .addr = CC1120_CHFILT_Q1, .name = "CHFILT_Q1" },
1256 { .addr = CC1120_CHFILT_Q0, .name = "CHFILT_Q0" },
1257 { .addr = CC1120_GPIO_STATUS, .name = "GPIO_STATUS" },
1258 { .addr = CC1120_FSCAL_CTRL, .name = "FSCAL_CTRL" },
1259 { .addr = CC1120_PHASE_ADJUST, .name = "PHASE_ADJUST" },
1260 { .addr = CC1120_PARTNUMBER, .name = "PARTNUMBER" },
1261 { .addr = CC1120_PARTVERSION, .name = "PARTVERSION" },
1262 { .addr = CC1120_SERIAL_STATUS, .name = "SERIAL_STATUS" },
1263 { .addr = CC1120_RX_STATUS, .name = "RX_STATUS" },
1264 { .addr = CC1120_TX_STATUS, .name = "TX_STATUS" },
1265 { .addr = CC1120_MARC_STATUS1, .name = "MARC_STATUS1" },
1266 { .addr = CC1120_MARC_STATUS0, .name = "MARC_STATUS0" },
1267 { .addr = CC1120_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
1268 { .addr = CC1120_FSRF_TEST, .name = "FSRF_TEST" },
1269 { .addr = CC1120_PRE_TEST, .name = "PRE_TEST" },
1270 { .addr = CC1120_PRE_OVR, .name = "PRE_OVR" },
1271 { .addr = CC1120_ADC_TEST, .name = "ADC_TEST" },
1272 { .addr = CC1120_DVC_TEST, .name = "DVC_TEST" },
1273 { .addr = CC1120_ATEST, .name = "ATEST" },
1274 { .addr = CC1120_ATEST_LVDS, .name = "ATEST_LVDS" },
1275 { .addr = CC1120_ATEST_MODE, .name = "ATEST_MODE" },
1276 { .addr = CC1120_XOSC_TEST1, .name = "XOSC_TEST1" },
1277 { .addr = CC1120_XOSC_TEST0, .name = "XOSC_TEST0" },
1278 { .addr = CC1120_RXFIRST, .name = "RXFIRST" },
1279 { .addr = CC1120_TXFIRST, .name = "TXFIRST" },
1280 { .addr = CC1120_RXLAST, .name = "RXLAST" },
1281 { .addr = CC1120_TXLAST, .name = "TXLAST" },
1282 { .addr = CC1120_NUM_TXBYTES, .name = "NUM_TXBYTES" },
1283 { .addr = CC1120_NUM_RXBYTES, .name = "NUM_RXBYTES" },
1284 { .addr = CC1120_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
1285 { .addr = CC1120_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
1288 #define AO_NUM_CC1120_REG (sizeof ao_cc1120_reg / sizeof ao_cc1120_reg[0])
1290 static void ao_radio_show(void) {
1291 uint8_t status = ao_radio_status();
1295 status = ao_radio_status();
1296 printf ("Status: %02x\n", status);
1297 printf ("CHIP_RDY: %d\n", (status >> CC1120_STATUS_CHIP_RDY) & 1);
1298 printf ("STATE: %s\n", cc1120_state_name[(status >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK]);
1299 printf ("MARC: %02x\n", ao_radio_get_marc_status());
1301 for (i = 0; i < AO_NUM_CC1120_REG; i++)
1302 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name);
1306 static void ao_radio_beep(void) {
1310 static void ao_radio_packet(void) {
1311 static const uint8_t packet[] = {
1313 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1314 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1315 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1316 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1322 ao_radio_send(packet, sizeof (packet));
1326 ao_radio_test_recv()
1331 if (ao_radio_recv(bytes, 34)) {
1332 if (bytes[33] & 0x80)
1336 printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32]));
1337 for (b = 0; b < 32; b++)
1338 printf (" %02x", bytes[b]);
1344 #include <ao_aprs.h>
1349 ao_packet_slave_stop();
1356 static const struct ao_cmds ao_radio_cmds[] = {
1357 { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
1360 { ao_radio_aprs, "G\0Send APRS packet" },
1362 { ao_radio_show, "R\0Show CC1120 status" },
1363 { ao_radio_beep, "b\0Emit an RDF beacon" },
1364 { ao_radio_packet, "p\0Send a test packet" },
1365 { ao_radio_test_recv, "q\0Recv a test packet" },
1375 ao_radio_configured = 0;
1376 ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN));
1379 AO_CC1120_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN));
1380 for (i = 0; i < 10000; i++) {
1381 if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0)
1384 AO_CC1120_SPI_CS_PORT->bsrr = (1 << AO_CC1120_SPI_CS_PIN);
1386 ao_panic(AO_PANIC_SELF_TEST_CC1120);
1389 /* Enable the EXTI interrupt for the appropriate pin */
1390 ao_enable_port(AO_CC1120_INT_PORT);
1391 ao_exti_setup(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1392 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
1395 /* Enable the hacked up GPIO3 pin */
1396 ao_enable_port(AO_CC1120_MCU_WAKEUP_PORT);
1397 ao_exti_setup(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN,
1398 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED,
1399 ao_radio_mcu_wakeup_isr);
1401 ao_cmd_register(&ao_radio_cmds[0]);