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);
295 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
297 * Deviation for 38400 baud should be 20.5kHz:
299 * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz
301 * Deviation for 9600 baud should be 5.125kHz:
303 * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 3) = 5127Hz
305 * Deviation for 2400 baud should be 1.28125kHz, but cc1111 and
306 * cc115l can't do that, so we'll use 1.5kHz instead:
308 * 32e6Hz / (2 ** 24) * (256 + 137) * (2 ** 1) = 1499Hz
311 #define PACKET_DEV_M_384 80
312 #define PACKET_DEV_E_384 5
314 #define PACKET_DEV_M_96 80
315 #define PACKET_DEV_E_96 3
317 #define PACKET_DEV_M_24 137
318 #define PACKET_DEV_E_24 1
321 * For our packet data
323 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
324 * Rdata = -------------------------------------- * fosc
327 * Given the bit period of the baseband, T, the bandwidth of the
328 * baseband signal is B = 1/(2T). The overall bandwidth of the
329 * modulated signal is then Channel bandwidth = 2Δf + 2B.
331 * 38400 -- 2 * 20500 + 38400 = 79.4 kHz
332 * 9600 -- 2 * 5.125 + 9600 = 19.9 kHz
333 * 2400 -- 2 * 1.5 + 2400 = 5.4 khz
335 * Symbol rate 38400 Baud:
337 * DATARATE_M = 239914
339 * CHANBW = 79.4 (round to 100)
341 * Symbol rate 9600 Baud:
343 * DATARATE_M = 239914
345 * CHANBW = 19.9 (round to 20)
347 * Symbol rate 2400 Baud:
349 * DATARATE_M = 239914
351 * CHANBW = 5.0 (round to 8.0)
354 #define PACKET_DRATE_M 239914
356 #define PACKET_DRATE_E_384 9
359 #define PACKET_CHAN_BW_384 ((0 << CC1120_CHAN_BW_CHFILT_BYPASS) | \
360 (CC1120_CHAN_BW_ADC_CIC_DECFACT_20 << CC1120_CHAN_BW_ADC_CIC_DECFACT) | \
361 (2 << CC1120_CHAN_BW_BB_CIC_DECFACT))
363 #define PACKET_DRATE_E_96 7
365 #define PACKET_CHAN_BW_96 ((0 << CC1120_CHAN_BW_CHFILT_BYPASS) | \
366 (CC1120_CHAN_BW_ADC_CIC_DECFACT_20 << CC1120_CHAN_BW_ADC_CIC_DECFACT) | \
367 (10 << CC1120_CHAN_BW_BB_CIC_DECFACT))
369 #define PACKET_DRATE_E_24 5
371 #define PACKET_CHAN_BW_24 ((0 << CC1120_CHAN_BW_CHFILT_BYPASS) | \
372 (CC1120_CHAN_BW_ADC_CIC_DECFACT_20 << CC1120_CHAN_BW_ADC_CIC_DECFACT) | \
373 (25 << CC1120_CHAN_BW_BB_CIC_DECFACT))
375 static const uint16_t packet_setup[] = {
376 CC1120_DRATE1, ((PACKET_DRATE_M >> 8) & 0xff),
377 CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff),
378 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
379 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
380 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
381 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
382 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
383 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
384 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
385 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
386 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
387 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
388 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
389 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
390 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
391 AO_CC1120_MARC_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP,
394 static const uint16_t packet_setup_384[] = {
395 CC1120_DEVIATION_M, PACKET_DEV_M_384,
396 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
397 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
398 (PACKET_DEV_E_384 << CC1120_MODCFG_DEV_E_DEV_E)),
399 CC1120_DRATE2, ((PACKET_DRATE_E_384 << CC1120_DRATE2_DATARATE_E) |
400 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
401 CC1120_CHAN_BW, PACKET_CHAN_BW_384,
402 CC1120_PA_CFG0, 0x7b,
405 static const uint16_t packet_setup_96[] = {
406 CC1120_DEVIATION_M, PACKET_DEV_M_96,
407 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
408 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
409 (PACKET_DEV_E_96 << CC1120_MODCFG_DEV_E_DEV_E)),
410 CC1120_DRATE2, ((PACKET_DRATE_E_96 << CC1120_DRATE2_DATARATE_E) |
411 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
412 CC1120_CHAN_BW, PACKET_CHAN_BW_96,
413 CC1120_PA_CFG0, 0x7d,
416 static const uint16_t packet_setup_24[] = {
417 CC1120_DEVIATION_M, PACKET_DEV_M_24,
418 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
419 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
420 (PACKET_DEV_E_24 << CC1120_MODCFG_DEV_E_DEV_E)),
421 CC1120_DRATE2, ((PACKET_DRATE_E_24 << CC1120_DRATE2_DATARATE_E) |
422 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
423 CC1120_CHAN_BW, PACKET_CHAN_BW_24,
424 CC1120_PA_CFG0, 0x7e,
427 static const uint16_t packet_tx_setup[] = {
428 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
429 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
430 AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG,
433 static const uint16_t packet_rx_setup[] = {
434 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
435 (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT)),
436 AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT,
440 * RDF deviation is 5kHz
442 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
444 * 32e6Hz / (2 ** 24) * (256 + 71) * (2 ** 3) = 4989
449 #define RDF_PACKET_LEN 50
452 * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
454 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
455 * Rdata = -------------------------------------- * fosc
461 * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
463 #define RDF_DRATE_E 5
464 #define RDF_DRATE_M 25166
465 #define RDF_PACKET_LEN 50
467 static const uint16_t rdf_setup[] = {
468 CC1120_DEVIATION_M, RDF_DEV_M,
469 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
470 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
471 (RDF_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
472 CC1120_DRATE2, ((RDF_DRATE_E << CC1120_DRATE2_DATARATE_E) |
473 (((RDF_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
474 CC1120_DRATE1, ((RDF_DRATE_M >> 8) & 0xff),
475 CC1120_DRATE0, ((RDF_DRATE_M >> 0) & 0xff),
476 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
477 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
478 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
479 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
480 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
481 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
482 CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) |
483 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) |
484 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) |
485 (0 << CC1120_PKT_CFG0_UART_MODE_EN) |
486 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
487 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
488 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
489 CC1120_PA_CFG0, 0x7e,
493 * APRS deviation is 3kHz
495 * fdev = fosc >> 24 * (256 + dev_m) << dev_e
497 * 32e6Hz / (2 ** 24) * (256 + 137) * (2 ** 2) = 2998Hz
501 #define APRS_DEV_M 137
504 * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate)
506 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
507 * Rdata = -------------------------------------- * fosc
510 * DATARATE_M = 239914
513 * Rdata = 9599.998593330383301
516 #define APRS_DRATE_E 7
517 #define APRS_DRATE_M 239914
519 static const uint16_t aprs_setup[] = {
520 CC1120_DEVIATION_M, APRS_DEV_M,
521 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
522 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
523 (APRS_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
524 CC1120_DRATE2, ((APRS_DRATE_E << CC1120_DRATE2_DATARATE_E) |
525 (((APRS_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
526 CC1120_DRATE1, ((APRS_DRATE_M >> 8) & 0xff),
527 CC1120_DRATE0, ((APRS_DRATE_M >> 0) & 0xff),
528 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
529 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
530 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
531 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
532 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
533 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
534 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
535 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
536 CC1120_PA_CFG0, 0x7d,
540 * For Test mode, we want an unmodulated carrier. To do that, we
541 * set the deviation to zero and enable a preamble so that the radio
542 * turns on before we send any data
545 static const uint16_t test_setup[] = {
546 CC1120_DEVIATION_M, 0,
547 CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
548 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
549 (0 << CC1120_MODCFG_DEV_E_DEV_E)),
550 CC1120_DRATE2, ((APRS_DRATE_E << CC1120_DRATE2_DATARATE_E) |
551 (((APRS_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
552 CC1120_DRATE1, ((APRS_DRATE_M >> 8) & 0xff),
553 CC1120_DRATE0, ((APRS_DRATE_M >> 0) & 0xff),
554 CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
555 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
556 CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) |
557 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |
558 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |
559 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),
560 CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
561 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
564 #define AO_PKT_CFG0_INFINITE ((0 << CC1120_PKT_CFG0_RESERVED7) | \
565 (CC1120_PKT_CFG0_LENGTH_CONFIG_INFINITE << CC1120_PKT_CFG0_LENGTH_CONFIG) | \
566 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | \
567 (0 << CC1120_PKT_CFG0_UART_MODE_EN) | \
568 (0 << CC1120_PKT_CFG0_UART_SWAP_EN))
570 #define AO_PKT_CFG0_FIXED ((0 << CC1120_PKT_CFG0_RESERVED7) | \
571 (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) | \
572 (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | \
573 (0 << CC1120_PKT_CFG0_UART_MODE_EN) | \
574 (0 << CC1120_PKT_CFG0_UART_SWAP_EN))
576 static uint16_t ao_radio_mode;
578 #define AO_RADIO_MODE_BITS_PACKET 1
579 #define AO_RADIO_MODE_BITS_PACKET_TX 2
580 #define AO_RADIO_MODE_BITS_TX_BUF 4
581 #define AO_RADIO_MODE_BITS_TX_FINISH 8
582 #define AO_RADIO_MODE_BITS_PACKET_RX 16
583 #define AO_RADIO_MODE_BITS_RDF 32
584 #define AO_RADIO_MODE_BITS_APRS 64
585 #define AO_RADIO_MODE_BITS_TEST 128
586 #define AO_RADIO_MODE_BITS_INFINITE 256
587 #define AO_RADIO_MODE_BITS_FIXED 512
589 #define AO_RADIO_MODE_NONE 0
590 #define AO_RADIO_MODE_PACKET_TX_BUF (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_BUF)
591 #define AO_RADIO_MODE_PACKET_TX_FINISH (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_FINISH)
592 #define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_RX)
593 #define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_TX_FINISH)
594 #define AO_RADIO_MODE_APRS_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
595 #define AO_RADIO_MODE_APRS_LAST_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_BUF)
596 #define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
597 #define AO_RADIO_MODE_TEST (AO_RADIO_MODE_BITS_TEST | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
600 _ao_radio_set_regs(const uint16_t *regs, int nreg)
604 for (i = 0; i < nreg; i++) {
605 ao_radio_reg_write(regs[0], regs[1]);
610 #define ao_radio_set_regs(setup) _ao_radio_set_regs(setup, (sizeof (setup) / sizeof(setup[0])) >> 1)
613 ao_radio_set_mode(uint16_t new_mode)
617 if (new_mode == ao_radio_mode)
620 changes = new_mode & (~ao_radio_mode);
622 if (changes & AO_RADIO_MODE_BITS_PACKET) {
623 ao_radio_set_regs(packet_setup);
625 switch (ao_config.radio_rate) {
627 case AO_RADIO_RATE_38400:
628 ao_radio_set_regs(packet_setup_384);
630 case AO_RADIO_RATE_9600:
631 ao_radio_set_regs(packet_setup_96);
633 case AO_RADIO_RATE_2400:
634 ao_radio_set_regs(packet_setup_24);
639 if (changes & AO_RADIO_MODE_BITS_PACKET_TX)
640 ao_radio_set_regs(packet_tx_setup);
642 if (changes & AO_RADIO_MODE_BITS_TX_BUF)
643 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_TXFIFO_THR);
645 if (changes & AO_RADIO_MODE_BITS_TX_FINISH)
646 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG);
648 if (changes & AO_RADIO_MODE_BITS_PACKET_RX)
649 ao_radio_set_regs(packet_rx_setup);
651 if (changes & AO_RADIO_MODE_BITS_RDF)
652 ao_radio_set_regs(rdf_setup);
654 if (changes & AO_RADIO_MODE_BITS_APRS)
655 ao_radio_set_regs(aprs_setup);
657 if (changes & AO_RADIO_MODE_BITS_TEST)
658 ao_radio_set_regs(test_setup);
660 if (changes & AO_RADIO_MODE_BITS_INFINITE)
661 ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_INFINITE);
663 if (changes & AO_RADIO_MODE_BITS_FIXED)
664 ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_FIXED);
666 ao_radio_mode = new_mode;
669 static const uint16_t radio_setup[] = {
670 #include "ao_cc1120_CC1120.h"
673 static uint8_t ao_radio_configured = 0;
678 ao_radio_strobe(CC1120_SRES);
680 ao_radio_set_regs(radio_setup);
686 ao_radio_configured = 1;
690 ao_radio_set_len(uint8_t len)
692 static uint8_t last_len;
694 if (len != last_len) {
695 ao_radio_reg_write(CC1120_PKT_LEN, len);
701 ao_radio_get(uint8_t len)
703 static uint32_t last_radio_setting;
704 static uint8_t last_radio_rate;
706 ao_mutex_get(&ao_radio_mutex);
708 if (!ao_radio_configured)
710 if (ao_config.radio_setting != last_radio_setting) {
711 ao_radio_reg_write(CC1120_FREQ2, ao_config.radio_setting >> 16);
712 ao_radio_reg_write(CC1120_FREQ1, ao_config.radio_setting >> 8);
713 ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting);
714 last_radio_setting = ao_config.radio_setting;
716 if (ao_config.radio_rate != last_radio_rate) {
717 ao_radio_mode &= ~AO_RADIO_MODE_BITS_PACKET;
718 last_radio_rate = ao_config.radio_rate;
720 ao_radio_set_len(len);
723 #define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
726 ao_rdf_start(uint8_t len)
731 ao_radio_set_mode(AO_RADIO_MODE_RDF);
741 ao_arch_block_interrupts();
742 while (!ao_radio_wake && !ao_radio_abort && !ao_radio_mcu_wake)
743 ao_sleep(&ao_radio_wake);
744 ao_arch_release_interrupts();
745 if (ao_radio_mcu_wake)
746 ao_radio_check_marc_status();
755 ao_rdf_start(AO_RADIO_RDF_LEN);
757 ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN);
763 ao_radio_continuity(uint8_t c)
768 ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN);
770 status = ao_radio_fifo_write_start();
771 for (i = 0; i < 3; i++) {
772 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
774 ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN);
776 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN);
778 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
779 status = ao_radio_fifo_write_stop(status);
785 ao_radio_rdf_abort(void)
788 ao_wakeup(&ao_radio_wake);
792 ao_radio_test_cmd(void)
795 static uint8_t radio_on;
797 if (ao_cmd_lex_c != '\n') {
799 mode = (uint8_t) ao_cmd_lex_u32;
802 if ((mode & 2) && !radio_on) {
804 ao_monitor_disable();
807 ao_packet_slave_stop();
810 ao_radio_set_mode(AO_RADIO_MODE_TEST);
811 ao_radio_strobe(CC1120_STX);
814 for (t = 0; t < 10; t++) {
815 printf ("status: %02x\n", ao_radio_status());
816 ao_delay(AO_MS_TO_TICKS(100));
823 printf ("Hit a character to stop..."); flush();
827 if ((mode & 1) && radio_on) {
838 ao_radio_wait_isr(uint16_t timeout)
842 ao_arch_block_interrupts();
843 while (!ao_radio_wake && !ao_radio_mcu_wake && !ao_radio_abort)
844 if (ao_sleep(&ao_radio_wake))
846 ao_arch_release_interrupts();
849 if (ao_radio_mcu_wake)
850 ao_radio_check_marc_status();
854 ao_radio_wait_tx(uint8_t wait_fifo)
856 uint8_t fifo_space = 0;
859 ao_radio_wait_isr(0);
862 fifo_space = ao_radio_tx_fifo_space();
863 } while (!fifo_space && !ao_radio_abort);
867 static uint8_t tx_data[(AO_RADIO_MAX_SEND + 4) * 2];
870 ao_radio_send(const void *d, uint8_t size)
872 uint8_t *e = tx_data;
878 encode_len = ao_fec_encode(d, size, tx_data);
880 ao_radio_get(encode_len);
884 /* Flush any pending TX bytes */
885 ao_radio_strobe(CC1120_SFTX);
888 fifo_space = CC1120_FIFO_SIZE;
890 this_len = encode_len;
893 if (this_len > fifo_space) {
894 this_len = fifo_space;
895 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_BUF);
897 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_FINISH);
900 ao_radio_fifo_write(e, this_len);
902 encode_len -= this_len;
908 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
911 fifo_space = ao_radio_wait_tx(encode_len != 0);
912 if (ao_radio_abort) {
917 while (started && !ao_radio_abort && !ao_radio_tx_finished)
918 ao_radio_wait_isr(0);
922 #define AO_RADIO_LOTS 64
925 ao_radio_send_aprs(ao_radio_fill_func fill)
927 uint8_t buf[AO_RADIO_LOTS], *b;
935 fifo_space = CC1120_FIFO_SIZE;
937 cnt = (*fill)(buf, sizeof(buf));
944 /* At the last buffer, set the total length */
946 ao_radio_set_len(total & 0xff);
950 uint8_t this_len = cnt;
952 /* Wait for some space in the fifo */
953 while (!ao_radio_abort && (fifo_space = ao_radio_tx_fifo_space()) == 0) {
955 ao_radio_wait_isr(0);
959 if (this_len > fifo_space)
960 this_len = fifo_space;
966 ao_radio_set_mode(AO_RADIO_MODE_APRS_LAST_BUF);
968 ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
970 ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
972 ao_radio_fifo_write(b, this_len);
979 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
981 if (ao_radio_abort) {
985 /* Wait for the transmitter to go idle */
987 ao_radio_wait_isr(0);
992 static uint8_t rx_data[(AO_RADIO_MAX_RECV + 4) * 2 * 8];
993 static uint16_t rx_data_count;
994 static uint16_t rx_data_consumed;
995 static uint16_t rx_data_cur;
996 static uint8_t rx_ignore;
997 static uint8_t rx_waiting;
998 static uint8_t rx_starting;
999 static uint8_t rx_task_id;
1000 static uint32_t rx_fast_start;
1001 static uint32_t rx_slow_start;
1002 static uint32_t rx_missed;
1005 static uint32_t rx_start_tick, rx_packet_tick, rx_done_tick, rx_last_done_tick;
1007 uint32_t ao_rx_start_tick, ao_rx_packet_tick, ao_rx_done_tick, ao_rx_last_done_tick;
1009 #include <ao_profile.h>
1013 ao_radio_rx_isr(void)
1018 if (ao_radio_try_select(rx_task_id)) {
1021 _ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
1034 ao_wakeup(&ao_radio_wake);
1036 d = AO_CC1120_SPI.dr;
1037 AO_CC1120_SPI.dr = 0;
1038 if (rx_ignore == 0) {
1039 if (rx_data_cur < rx_data_count)
1040 rx_data[rx_data_cur++] = d;
1041 if (rx_data_cur >= rx_data_count) {
1042 ao_spi_clr_cs(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN));
1043 ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
1045 if (rx_waiting && rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) {
1047 if (!rx_packet_tick)
1048 rx_packet_tick = ao_profile_tick();
1049 if (rx_data_cur < rx_data_count)
1053 ao_wakeup(&ao_radio_wake);
1061 ao_radio_rx_wait(void)
1063 ao_alarm(AO_MS_TO_TICKS(100));
1064 ao_arch_block_interrupts();
1066 while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&
1070 if (ao_sleep(&ao_radio_wake))
1074 ao_arch_release_interrupts();
1076 if (ao_radio_abort || ao_radio_mcu_wake)
1078 rx_data_consumed += AO_FEC_DECODE_BLOCK;
1080 return rx_data_cur - rx_data_consumed;
1082 return AO_FEC_DECODE_BLOCK;
1086 ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout)
1089 uint8_t radio_rssi = 0;
1093 size -= 2; /* status bytes */
1094 if (size > AO_RADIO_MAX_RECV) {
1095 ao_delay(AO_SEC_TO_TICKS(1));
1099 rx_start_tick = ao_profile_tick();
1102 len = size + 2; /* CRC bytes */
1103 len += 1 + ~(len & 1); /* 1 or two pad bytes */
1104 len *= 2; /* 1/2 rate convolution */
1105 rx_data_count = len * 8; /* bytes to bits */
1107 rx_data_consumed = 0;
1110 /* Must be set before changing the frequency; any abort
1111 * after the frequency is set needs to terminate the read
1112 * so that the registers can be reprogrammed
1119 ao_radio_mcu_wake = 0;
1121 ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
1123 /* configure interrupt pin */
1124 ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT);
1125 ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1126 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
1129 rx_task_id = ao_cur_task->task_id;
1131 ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
1132 ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
1134 ao_radio_strobe(CC1120_SRX);
1138 ao_arch_block_interrupts();
1139 while (rx_starting && !ao_radio_abort) {
1140 if (ao_sleep(&ao_radio_wake))
1143 uint8_t rx_task_id_save = rx_task_id;
1146 ao_arch_release_interrupts();
1150 if (ao_radio_abort) {
1151 if (rx_task_id_save == 0)
1152 ao_radio_burst_read_stop();
1157 if (rx_task_id_save) {
1160 _ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
1162 uint8_t ignore = AO_CC1120_SPI.dr;
1164 AO_CC1120_SPI.dr = 0;
1169 ret = ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait);
1171 ao_radio_burst_read_stop();
1173 if (ao_radio_mcu_wake)
1174 ao_radio_check_marc_status();
1179 /* Convert from 'real' rssi to cc1111-style values */
1181 rssi0 = ao_radio_reg_read(CC1120_RSSI0);
1183 int8_t rssi = ao_radio_reg_read(CC1120_RSSI1);
1184 ao_radio_rssi = rssi;
1186 /* Bound it to the representable range */
1189 radio_rssi = AO_RADIO_FROM_RSSI (rssi);
1196 /* Store the received RSSI value; the crc-OK byte is already done */
1198 ((uint8_t *) d)[size] = radio_rssi;
1201 rx_last_done_tick = rx_done_tick;
1202 rx_done_tick = ao_profile_tick();
1204 ao_rx_start_tick = rx_start_tick;
1205 ao_rx_packet_tick = rx_packet_tick;
1206 ao_rx_done_tick = rx_done_tick;
1207 ao_rx_last_done_tick = rx_last_done_tick;
1215 static char *cc1120_state_name[] = {
1216 [CC1120_STATUS_STATE_IDLE] = "IDLE",
1217 [CC1120_STATUS_STATE_RX] = "RX",
1218 [CC1120_STATUS_STATE_TX] = "TX",
1219 [CC1120_STATUS_STATE_FSTXON] = "FSTXON",
1220 [CC1120_STATUS_STATE_CALIBRATE] = "CALIBRATE",
1221 [CC1120_STATUS_STATE_SETTLING] = "SETTLING",
1222 [CC1120_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
1223 [CC1120_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
1226 struct ao_cc1120_reg {
1231 static const struct ao_cc1120_reg ao_cc1120_reg[] = {
1232 { .addr = CC1120_IOCFG3, .name = "IOCFG3" },
1233 { .addr = CC1120_IOCFG2, .name = "IOCFG2" },
1234 { .addr = CC1120_IOCFG1, .name = "IOCFG1" },
1235 { .addr = CC1120_IOCFG0, .name = "IOCFG0" },
1236 { .addr = CC1120_SYNC3, .name = "SYNC3" },
1237 { .addr = CC1120_SYNC2, .name = "SYNC2" },
1238 { .addr = CC1120_SYNC1, .name = "SYNC1" },
1239 { .addr = CC1120_SYNC0, .name = "SYNC0" },
1240 { .addr = CC1120_SYNC_CFG1, .name = "SYNC_CFG1" },
1241 { .addr = CC1120_SYNC_CFG0, .name = "SYNC_CFG0" },
1242 { .addr = CC1120_DEVIATION_M, .name = "DEVIATION_M" },
1243 { .addr = CC1120_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
1244 { .addr = CC1120_DCFILT_CFG, .name = "DCFILT_CFG" },
1245 { .addr = CC1120_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
1246 { .addr = CC1120_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
1247 { .addr = CC1120_FREQ_IF_CFG, .name = "FREQ_IF_CFG" },
1248 { .addr = CC1120_IQIC, .name = "IQIC" },
1249 { .addr = CC1120_CHAN_BW, .name = "CHAN_BW" },
1250 { .addr = CC1120_MDMCFG1, .name = "MDMCFG1" },
1251 { .addr = CC1120_MDMCFG0, .name = "MDMCFG0" },
1252 { .addr = CC1120_DRATE2, .name = "DRATE2" },
1253 { .addr = CC1120_DRATE1, .name = "DRATE1" },
1254 { .addr = CC1120_DRATE0, .name = "DRATE0" },
1255 { .addr = CC1120_AGC_REF, .name = "AGC_REF" },
1256 { .addr = CC1120_AGC_CS_THR, .name = "AGC_CS_THR" },
1257 { .addr = CC1120_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
1258 { .addr = CC1120_AGC_CFG3, .name = "AGC_CFG3" },
1259 { .addr = CC1120_AGC_CFG2, .name = "AGC_CFG2" },
1260 { .addr = CC1120_AGC_CFG1, .name = "AGC_CFG1" },
1261 { .addr = CC1120_AGC_CFG0, .name = "AGC_CFG0" },
1262 { .addr = CC1120_FIFO_CFG, .name = "FIFO_CFG" },
1263 { .addr = CC1120_DEV_ADDR, .name = "DEV_ADDR" },
1264 { .addr = CC1120_SETTLING_CFG, .name = "SETTLING_CFG" },
1265 { .addr = CC1120_FS_CFG, .name = "FS_CFG" },
1266 { .addr = CC1120_WOR_CFG1, .name = "WOR_CFG1" },
1267 { .addr = CC1120_WOR_CFG0, .name = "WOR_CFG0" },
1268 { .addr = CC1120_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
1269 { .addr = CC1120_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
1270 { .addr = CC1120_PKT_CFG2, .name = "PKT_CFG2" },
1271 { .addr = CC1120_PKT_CFG1, .name = "PKT_CFG1" },
1272 { .addr = CC1120_PKT_CFG0, .name = "PKT_CFG0" },
1273 { .addr = CC1120_RFEND_CFG1, .name = "RFEND_CFG1" },
1274 { .addr = CC1120_RFEND_CFG0, .name = "RFEND_CFG0" },
1275 { .addr = CC1120_PA_CFG2, .name = "PA_CFG2" },
1276 { .addr = CC1120_PA_CFG1, .name = "PA_CFG1" },
1277 { .addr = CC1120_PA_CFG0, .name = "PA_CFG0" },
1278 { .addr = CC1120_PKT_LEN, .name = "PKT_LEN" },
1279 { .addr = CC1120_IF_MIX_CFG, .name = "IF_MIX_CFG" },
1280 { .addr = CC1120_FREQOFF_CFG, .name = "FREQOFF_CFG" },
1281 { .addr = CC1120_TOC_CFG, .name = "TOC_CFG" },
1282 { .addr = CC1120_MARC_SPARE, .name = "MARC_SPARE" },
1283 { .addr = CC1120_ECG_CFG, .name = "ECG_CFG" },
1284 { .addr = CC1120_SOFT_TX_DATA_CFG, .name = "SOFT_TX_DATA_CFG" },
1285 { .addr = CC1120_EXT_CTRL, .name = "EXT_CTRL" },
1286 { .addr = CC1120_RCCAL_FINE, .name = "RCCAL_FINE" },
1287 { .addr = CC1120_RCCAL_COARSE, .name = "RCCAL_COARSE" },
1288 { .addr = CC1120_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
1289 { .addr = CC1120_FREQOFF1, .name = "FREQOFF1" },
1290 { .addr = CC1120_FREQOFF0, .name = "FREQOFF0" },
1291 { .addr = CC1120_FREQ2, .name = "FREQ2" },
1292 { .addr = CC1120_FREQ1, .name = "FREQ1" },
1293 { .addr = CC1120_FREQ0, .name = "FREQ0" },
1294 { .addr = CC1120_IF_ADC2, .name = "IF_ADC2" },
1295 { .addr = CC1120_IF_ADC1, .name = "IF_ADC1" },
1296 { .addr = CC1120_IF_ADC0, .name = "IF_ADC0" },
1297 { .addr = CC1120_FS_DIG1, .name = "FS_DIG1" },
1298 { .addr = CC1120_FS_DIG0, .name = "FS_DIG0" },
1299 { .addr = CC1120_FS_CAL3, .name = "FS_CAL3" },
1300 { .addr = CC1120_FS_CAL2, .name = "FS_CAL2" },
1301 { .addr = CC1120_FS_CAL1, .name = "FS_CAL1" },
1302 { .addr = CC1120_FS_CAL0, .name = "FS_CAL0" },
1303 { .addr = CC1120_FS_CHP, .name = "FS_CHP" },
1304 { .addr = CC1120_FS_DIVTWO, .name = "FS_DIVTWO" },
1305 { .addr = CC1120_FS_DSM1, .name = "FS_DSM1" },
1306 { .addr = CC1120_FS_DSM0, .name = "FS_DSM0" },
1307 { .addr = CC1120_FS_DVC1, .name = "FS_DVC1" },
1308 { .addr = CC1120_FS_DVC0, .name = "FS_DVC0" },
1309 { .addr = CC1120_FS_LBI, .name = "FS_LBI" },
1310 { .addr = CC1120_FS_PFD, .name = "FS_PFD" },
1311 { .addr = CC1120_FS_PRE, .name = "FS_PRE" },
1312 { .addr = CC1120_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
1313 { .addr = CC1120_FS_SPARE, .name = "FS_SPARE" },
1314 { .addr = CC1120_FS_VCO4, .name = "FS_VCO4" },
1315 { .addr = CC1120_FS_VCO3, .name = "FS_VCO3" },
1316 { .addr = CC1120_FS_VCO2, .name = "FS_VCO2" },
1317 { .addr = CC1120_FS_VCO1, .name = "FS_VCO1" },
1318 { .addr = CC1120_FS_VCO0, .name = "FS_VCO0" },
1319 { .addr = CC1120_GBIAS6, .name = "GBIAS6" },
1320 { .addr = CC1120_GBIAS5, .name = "GBIAS5" },
1321 { .addr = CC1120_GBIAS4, .name = "GBIAS4" },
1322 { .addr = CC1120_GBIAS3, .name = "GBIAS3" },
1323 { .addr = CC1120_GBIAS2, .name = "GBIAS2" },
1324 { .addr = CC1120_GBIAS1, .name = "GBIAS1" },
1325 { .addr = CC1120_GBIAS0, .name = "GBIAS0" },
1326 { .addr = CC1120_IFAMP, .name = "IFAMP" },
1327 { .addr = CC1120_LNA, .name = "LNA" },
1328 { .addr = CC1120_RXMIX, .name = "RXMIX" },
1329 { .addr = CC1120_XOSC5, .name = "XOSC5" },
1330 { .addr = CC1120_XOSC4, .name = "XOSC4" },
1331 { .addr = CC1120_XOSC3, .name = "XOSC3" },
1332 { .addr = CC1120_XOSC2, .name = "XOSC2" },
1333 { .addr = CC1120_XOSC1, .name = "XOSC1" },
1334 { .addr = CC1120_XOSC0, .name = "XOSC0" },
1335 { .addr = CC1120_ANALOG_SPARE, .name = "ANALOG_SPARE" },
1336 { .addr = CC1120_PA_CFG3, .name = "PA_CFG3" },
1337 { .addr = CC1120_WOR_TIME1, .name = "WOR_TIME1" },
1338 { .addr = CC1120_WOR_TIME0, .name = "WOR_TIME0" },
1339 { .addr = CC1120_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
1340 { .addr = CC1120_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
1341 { .addr = CC1120_BIST, .name = "BIST" },
1342 { .addr = CC1120_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
1343 { .addr = CC1120_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
1344 { .addr = CC1120_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
1345 { .addr = CC1120_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
1346 { .addr = CC1120_IQIE_I1, .name = "IQIE_I1" },
1347 { .addr = CC1120_IQIE_I0, .name = "IQIE_I0" },
1348 { .addr = CC1120_IQIE_Q1, .name = "IQIE_Q1" },
1349 { .addr = CC1120_IQIE_Q0, .name = "IQIE_Q0" },
1350 { .addr = CC1120_RSSI1, .name = "RSSI1" },
1351 { .addr = CC1120_RSSI0, .name = "RSSI0" },
1352 { .addr = CC1120_MARCSTATE, .name = "MARCSTATE" },
1353 { .addr = CC1120_LQI_VAL, .name = "LQI_VAL" },
1354 { .addr = CC1120_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
1355 { .addr = CC1120_DEM_STATUS, .name = "DEM_STATUS" },
1356 { .addr = CC1120_FREQOFF_EST1, .name = "FREQOFF_EST1" },
1357 { .addr = CC1120_FREQOFF_EST0, .name = "FREQOFF_EST0" },
1358 { .addr = CC1120_AGC_GAIN3, .name = "AGC_GAIN3" },
1359 { .addr = CC1120_AGC_GAIN2, .name = "AGC_GAIN2" },
1360 { .addr = CC1120_AGC_GAIN1, .name = "AGC_GAIN1" },
1361 { .addr = CC1120_AGC_GAIN0, .name = "AGC_GAIN0" },
1362 { .addr = CC1120_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
1363 { .addr = CC1120_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
1364 { .addr = CC1120_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
1365 { .addr = CC1120_RNDGEN, .name = "RNDGEN" },
1366 { .addr = CC1120_MAGN2, .name = "MAGN2" },
1367 { .addr = CC1120_MAGN1, .name = "MAGN1" },
1368 { .addr = CC1120_MAGN0, .name = "MAGN0" },
1369 { .addr = CC1120_ANG1, .name = "ANG1" },
1370 { .addr = CC1120_ANG0, .name = "ANG0" },
1371 { .addr = CC1120_CHFILT_I2, .name = "CHFILT_I2" },
1372 { .addr = CC1120_CHFILT_I1, .name = "CHFILT_I1" },
1373 { .addr = CC1120_CHFILT_I0, .name = "CHFILT_I0" },
1374 { .addr = CC1120_CHFILT_Q2, .name = "CHFILT_Q2" },
1375 { .addr = CC1120_CHFILT_Q1, .name = "CHFILT_Q1" },
1376 { .addr = CC1120_CHFILT_Q0, .name = "CHFILT_Q0" },
1377 { .addr = CC1120_GPIO_STATUS, .name = "GPIO_STATUS" },
1378 { .addr = CC1120_FSCAL_CTRL, .name = "FSCAL_CTRL" },
1379 { .addr = CC1120_PHASE_ADJUST, .name = "PHASE_ADJUST" },
1380 { .addr = CC1120_PARTNUMBER, .name = "PARTNUMBER" },
1381 { .addr = CC1120_PARTVERSION, .name = "PARTVERSION" },
1382 { .addr = CC1120_SERIAL_STATUS, .name = "SERIAL_STATUS" },
1383 { .addr = CC1120_RX_STATUS, .name = "RX_STATUS" },
1384 { .addr = CC1120_TX_STATUS, .name = "TX_STATUS" },
1385 { .addr = CC1120_MARC_STATUS1, .name = "MARC_STATUS1" },
1386 { .addr = CC1120_MARC_STATUS0, .name = "MARC_STATUS0" },
1387 { .addr = CC1120_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
1388 { .addr = CC1120_FSRF_TEST, .name = "FSRF_TEST" },
1389 { .addr = CC1120_PRE_TEST, .name = "PRE_TEST" },
1390 { .addr = CC1120_PRE_OVR, .name = "PRE_OVR" },
1391 { .addr = CC1120_ADC_TEST, .name = "ADC_TEST" },
1392 { .addr = CC1120_DVC_TEST, .name = "DVC_TEST" },
1393 { .addr = CC1120_ATEST, .name = "ATEST" },
1394 { .addr = CC1120_ATEST_LVDS, .name = "ATEST_LVDS" },
1395 { .addr = CC1120_ATEST_MODE, .name = "ATEST_MODE" },
1396 { .addr = CC1120_XOSC_TEST1, .name = "XOSC_TEST1" },
1397 { .addr = CC1120_XOSC_TEST0, .name = "XOSC_TEST0" },
1398 { .addr = CC1120_RXFIRST, .name = "RXFIRST" },
1399 { .addr = CC1120_TXFIRST, .name = "TXFIRST" },
1400 { .addr = CC1120_RXLAST, .name = "RXLAST" },
1401 { .addr = CC1120_TXLAST, .name = "TXLAST" },
1402 { .addr = CC1120_NUM_TXBYTES, .name = "NUM_TXBYTES" },
1403 { .addr = CC1120_NUM_RXBYTES, .name = "NUM_RXBYTES" },
1404 { .addr = CC1120_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
1405 { .addr = CC1120_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
1408 #define AO_NUM_CC1120_REG (sizeof ao_cc1120_reg / sizeof ao_cc1120_reg[0])
1410 static void ao_radio_show(void) {
1411 uint8_t status = ao_radio_status();
1415 status = ao_radio_status();
1416 printf ("Status: %02x\n", status);
1417 printf ("CHIP_RDY: %d\n", (status >> CC1120_STATUS_CHIP_RDY) & 1);
1418 printf ("STATE: %s\n", cc1120_state_name[(status >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK]);
1419 printf ("MARC: %02x\n", ao_radio_get_marc_status());
1421 for (i = 0; i < AO_NUM_CC1120_REG; i++)
1422 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name);
1424 printf("RX fast start: %u\n", rx_fast_start);
1425 printf("RX slow start: %u\n", rx_slow_start);
1426 printf("RX missed: %u\n", rx_missed);
1430 static void ao_radio_beep(void) {
1434 static void ao_radio_packet(void) {
1435 static const uint8_t packet[] = {
1437 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1438 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1439 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1440 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1446 ao_radio_send(packet, sizeof (packet));
1450 ao_radio_test_recv(void)
1455 if (ao_radio_recv(bytes, 34, 0)) {
1456 if (bytes[33] & 0x80)
1460 printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32]));
1461 for (b = 0; b < 32; b++)
1462 printf (" %02x", bytes[b]);
1468 #include <ao_aprs.h>
1473 ao_packet_slave_stop();
1479 static const struct ao_cmds ao_radio_cmds[] = {
1480 { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
1483 { ao_radio_aprs, "G\0Send APRS packet" },
1485 { ao_radio_show, "R\0Show CC1120 status" },
1486 { ao_radio_beep, "b\0Emit an RDF beacon" },
1487 { ao_radio_packet, "p\0Send a test packet" },
1488 { ao_radio_test_recv, "q\0Recv a test packet" },
1496 ao_radio_configured = 0;
1497 ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN));
1500 AO_CC1120_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN));
1501 for (i = 0; i < 10000; i++) {
1502 if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0)
1505 AO_CC1120_SPI_CS_PORT->bsrr = (1 << AO_CC1120_SPI_CS_PIN);
1507 ao_panic(AO_PANIC_SELF_TEST_CC1120);
1510 /* Enable the EXTI interrupt for the appropriate pin */
1511 ao_enable_port(AO_CC1120_INT_PORT);
1512 ao_exti_setup(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
1513 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
1516 /* Enable the hacked up GPIO3 pin */
1517 ao_enable_port(AO_CC1120_MCU_WAKEUP_PORT);
1518 ao_exti_setup(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN,
1519 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED,
1520 ao_radio_mcu_wakeup_isr);
1522 ao_cmd_register(&ao_radio_cmds[0]);