2 * Copyright © 2013 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_cc115l.h>
21 #include <ao_telemetry.h>
24 #define AO_RADIO_MAX_SEND sizeof (struct ao_telemetry_generic)
26 static uint8_t ao_radio_mutex;
28 static uint8_t ao_radio_wake; /* radio ready. Also used as sleep address */
29 static uint8_t ao_radio_abort; /* radio operation should abort */
30 static uint8_t ao_radio_mcu_wake; /* MARC status change */
31 static uint8_t ao_radio_marcstate; /* Last read MARC state value */
33 #define CC115L_DEBUG 1
34 #define CC115L_TRACE 1
38 #define ao_radio_select() ao_spi_get_mask(AO_CC115L_SPI_CS_PORT,(1 << AO_CC115L_SPI_CS_PIN),AO_CC115L_SPI_BUS,AO_SPI_SPEED_1MHz)
39 #define ao_radio_deselect() ao_spi_put_mask(AO_CC115L_SPI_CS_PORT,(1 << AO_CC115L_SPI_CS_PIN),AO_CC115L_SPI_BUS)
40 #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC115L_SPI_BUS)
41 #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC115L_SPI_BUS)
42 #define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC115L_SPI_BUS)
43 #define ao_radio_duplex(o,i,l) ao_spi_duplex((o), (i), (l), AO_CC115L_SPI_BUS)
46 ao_radio_reg_read(uint16_t addr)
52 printf("\t\tao_radio_reg_read (%04x): ", addr); flush();
54 data[0] = ((1 << CC115L_READ) |
58 ao_radio_spi_send(data, 1);
59 ao_radio_spi_recv(data, 1);
62 printf (" %02x\n", data[0]);
68 ao_radio_reg_write(uint16_t addr, uint8_t value)
74 printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value);
76 data[0] = ((0 << CC115L_READ) |
81 ao_radio_spi_send(data, 2);
86 ao_radio_burst_read_start (uint16_t addr)
91 data[0] = ((1 << CC115L_READ) |
95 ao_radio_spi_send(data, 1);
99 ao_radio_burst_read_stop (void)
106 ao_radio_strobe(uint8_t addr)
111 printf("\t\tao_radio_strobe (%02x): ", addr); flush();
114 ao_radio_duplex(&addr, &in, 1);
117 printf("%02x\n", in); flush();
123 ao_radio_fifo_write_start(void)
125 uint8_t addr = ((0 << CC115L_READ) |
126 (1 << CC115L_BURST) |
131 ao_radio_duplex(&addr, &status, 1);
135 static inline uint8_t ao_radio_fifo_write_stop(uint8_t status) {
141 ao_radio_fifo_write(uint8_t *data, uint8_t len)
143 uint8_t status = ao_radio_fifo_write_start();
145 printf ("fifo_write %d\n", len);
147 ao_radio_spi_send(data, len);
148 return ao_radio_fifo_write_stop(status);
152 ao_radio_fifo_write_fixed(uint8_t data, uint8_t len)
154 uint8_t status = ao_radio_fifo_write_start();
157 printf ("fifo_write_fixed %02x %d\n", data, len);
159 ao_radio_spi_send_fixed(data, len);
160 return ao_radio_fifo_write_stop(status);
164 ao_radio_tx_fifo_space(void)
166 return CC115L_FIFO_SIZE - (ao_radio_reg_read(CC115L_TXBYTES) & CC115L_TXBYTES_NUM_TX_BYTES_MASK);
170 ao_radio_status(void)
172 return ao_radio_strobe (CC115L_SNOP);
175 #define ao_radio_rdf_value 0x55
178 ao_radio_get_marcstate(void)
180 return ao_radio_reg_read(CC115L_MARCSTATE) & CC115L_MARCSTATE_MASK;
184 ao_radio_mcu_wakeup_isr(void)
186 ao_radio_mcu_wake = 1;
187 ao_wakeup(&ao_radio_wake);
192 ao_radio_check_marcstate(void)
194 ao_radio_mcu_wake = 0;
195 ao_radio_marcstate = ao_radio_get_marcstate();
197 /* Anyt other than 'tx finished' means an error occurred */
198 if (ao_radio_marcstate != CC115L_MARCSTATE_TX_END)
205 ao_exti_disable(AO_CC115L_INT_PORT, AO_CC115L_INT_PIN);
207 ao_wakeup(&ao_radio_wake);
211 ao_radio_start_tx(void)
214 ao_exti_set_callback(AO_CC115L_INT_PORT, AO_CC115L_INT_PIN, ao_radio_isr);
215 ao_exti_enable(AO_CC115L_INT_PORT, AO_CC115L_INT_PIN);
216 ao_exti_enable(AO_CC115L_MCU_WAKEUP_PORT, AO_CC115L_MCU_WAKEUP_PIN);
217 ao_radio_strobe(CC115L_STX);
225 uint8_t state = ao_radio_strobe(CC115L_SIDLE);
226 if ((state >> CC115L_STATUS_STATE) == CC115L_STATUS_STATE_IDLE)
229 /* Flush any pending TX bytes */
230 ao_radio_strobe(CC115L_SFTX);
234 * Packet deviation is 20.5kHz
236 * fdev = fosc >> 17 * (8 + dev_m) << dev_e
238 * 26e6 / (2 ** 17) * (8 + 5) * (2 ** 3) = 20630Hz
241 #define PACKET_DEV_E 3
242 #define PACKET_DEV_M 5
245 * For our packet data, set the symbol rate to 38400 Baud
247 * (256 + DATARATE_M) * 2 ** DATARATE_E
248 * Rdata = -------------------------------------- * fosc
251 * (256 + 131) * (2 ** 10) / (2**28) * 26e6 = 38383
256 #define PACKET_DRATE_E 10
257 #define PACKET_DRATE_M 131
259 static const uint16_t packet_setup[] = {
260 CC115L_DEVIATN, ((PACKET_DEV_E << CC115L_DEVIATN_DEVIATION_E) |
261 (PACKET_DEV_M << CC115L_DEVIATN_DEVIATION_M)),
262 CC115L_MDMCFG4, ((0xf << 4) |
263 (PACKET_DRATE_E << CC115L_MDMCFG4_DRATE_E)),
264 CC115L_MDMCFG3, (PACKET_DRATE_M),
269 * RDF deviation is 5kHz
271 * fdev = fosc >> 17 * (8 + dev_m) << dev_e
273 * 26e6 / (2 ** 17) * (8 + 4) * (2 ** 1) = 4761Hz
280 * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
282 * (256 + DATARATE_M) * 2 ** DATARATE_E
283 * Rdata = -------------------------------------- * fosc
286 * (256 + 67) * (2 ** 6) / (2**28) * 26e6 = 2002
291 * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
293 #define RDF_DRATE_E 6
294 #define RDF_DRATE_M 67
295 #define RDF_PACKET_LEN 50
297 static const uint16_t rdf_setup[] = {
298 CC115L_DEVIATN, ((RDF_DEV_E << CC115L_DEVIATN_DEVIATION_E) |
299 (RDF_DEV_M << CC115L_DEVIATN_DEVIATION_M)),
300 CC115L_MDMCFG4, ((0xf << 4) |
301 (RDF_DRATE_E << CC115L_MDMCFG4_DRATE_E)),
302 CC115L_MDMCFG3, (RDF_DRATE_M),
306 * APRS deviation is the same as RDF
309 #define APRS_DEV_E RDF_DEV_E
310 #define APRS_DEV_M RDF_DEV_E
313 * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate)
315 * (256 + DATARATE_M) * 2 ** DATARATE_E
316 * Rdata = -------------------------------------- * fosc
319 * (256 + 131) * (2 ** 8) / (2**28) * 26e6 = 9596
325 #define APRS_DRATE_E 8
326 #define APRS_DRATE_M 131
328 static const uint16_t aprs_setup[] = {
329 CC115L_DEVIATN, ((APRS_DEV_E << CC115L_DEVIATN_DEVIATION_E) |
330 (APRS_DEV_M << CC115L_DEVIATN_DEVIATION_M)),
331 CC115L_MDMCFG4, ((0xf << 4) |
332 (APRS_DRATE_E << CC115L_MDMCFG4_DRATE_E)),
333 CC115L_MDMCFG3, (APRS_DRATE_M),
336 #define AO_PKTCTRL0_INFINITE ((CC115L_PKTCTRL0_PKT_FORMAT_NORMAL << CC115L_PKTCTRL0_PKT_FORMAT) | \
337 (0 << CC115L_PKTCTRL0_PKT_CRC_EN) | \
338 (CC115L_PKTCTRL0_PKT_LENGTH_CONFIG_INFINITE << CC115L_PKTCTRL0_PKT_LENGTH_CONFIG))
339 #define AO_PKTCTRL0_FIXED ((CC115L_PKTCTRL0_PKT_FORMAT_NORMAL << CC115L_PKTCTRL0_PKT_FORMAT) | \
340 (0 << CC115L_PKTCTRL0_PKT_CRC_EN) | \
341 (CC115L_PKTCTRL0_PKT_LENGTH_CONFIG_FIXED << CC115L_PKTCTRL0_PKT_LENGTH_CONFIG))
343 static uint16_t ao_radio_mode;
345 #define AO_RADIO_MODE_BITS_PACKET_TX 1
346 #define AO_RADIO_MODE_BITS_TX_BUF 2
347 #define AO_RADIO_MODE_BITS_TX_FINISH 4
348 #define AO_RADIO_MODE_BITS_RDF 8
349 #define AO_RADIO_MODE_BITS_APRS 16
350 #define AO_RADIO_MODE_BITS_INFINITE 32
351 #define AO_RADIO_MODE_BITS_FIXED 64
353 #define AO_RADIO_MODE_NONE 0
354 #define AO_RADIO_MODE_PACKET_TX_BUF (AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_BUF)
355 #define AO_RADIO_MODE_PACKET_TX_FINISH (AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_FINISH)
356 #define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_TX_FINISH)
357 #define AO_RADIO_MODE_APRS_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
358 #define AO_RADIO_MODE_APRS_LAST_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_BUF)
359 #define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
362 ao_radio_set_mode(uint16_t new_mode)
367 if (new_mode == ao_radio_mode)
370 changes = new_mode & (~ao_radio_mode);
371 if (changes & AO_RADIO_MODE_BITS_PACKET_TX)
372 for (i = 0; i < sizeof (packet_setup) / sizeof (packet_setup[0]); i += 2)
373 ao_radio_reg_write(packet_setup[i], packet_setup[i+1]);
375 if (changes & AO_RADIO_MODE_BITS_TX_BUF)
376 ao_radio_reg_write(AO_CC115L_INT_GPIO_IOCFG, CC115L_IOCFG_GPIO_CFG_TXFIFO_THR);
378 if (changes & AO_RADIO_MODE_BITS_TX_FINISH)
379 ao_radio_reg_write(AO_CC115L_INT_GPIO_IOCFG, CC115L_IOCFG_GPIO_CFG_PKT_SYNC_TX | (1 << CC115L_IOCFG_GPIO_INV));
381 if (changes & AO_RADIO_MODE_BITS_RDF)
382 for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2)
383 ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]);
385 if (changes & AO_RADIO_MODE_BITS_APRS)
386 for (i = 0; i < sizeof (aprs_setup) / sizeof (aprs_setup[0]); i += 2)
387 ao_radio_reg_write(aprs_setup[i], aprs_setup[i+1]);
389 if (changes & AO_RADIO_MODE_BITS_INFINITE)
390 ao_radio_reg_write(CC115L_PKTCTRL0, AO_PKTCTRL0_INFINITE);
392 if (changes & AO_RADIO_MODE_BITS_FIXED)
393 ao_radio_reg_write(CC115L_PKTCTRL0, AO_PKTCTRL0_FIXED);
395 ao_radio_mode = new_mode;
398 static const uint16_t radio_setup[] = {
399 #include "ao_rf_cc115l.h"
402 static uint8_t ao_radio_configured = 0;
410 ao_gpio_set(AO_CC115L_SPI_CS_PORT, AO_CC115L_SPI_CS_PIN, AO_CC115L_SPI_CS, 0);
411 for (i = 0; i < 10000; i++) {
412 if (ao_gpio_get(SPI_2_PORT, SPI_2_MISO_PIN, SPI_2_MISO) == 0) {
413 printf ("Chip clock alive\n");
417 ao_gpio_set(AO_CC115L_SPI_CS_PORT, AO_CC115L_SPI_CS_PIN, AO_CC115L_SPI_CS, 1);
419 printf ("Chip clock not alive\n");
422 ao_radio_strobe(CC115L_SRES);
423 ao_delay(AO_MS_TO_TICKS(10));
425 printf ("Part %x\n", ao_radio_reg_read(CC115L_PARTNUM));
426 printf ("Version %x\n", ao_radio_reg_read(CC115L_VERSION));
428 for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2) {
429 ao_radio_reg_write(radio_setup[i], radio_setup[i+1]);
430 ao_radio_reg_read(radio_setup[i]);
437 ao_radio_configured = 1;
441 ao_radio_set_len(uint8_t len)
443 static uint8_t last_len;
445 if (len != last_len) {
446 ao_radio_reg_write(CC115L_PKTLEN, len);
452 ao_radio_get(uint8_t len)
454 static uint32_t last_radio_setting;
455 static uint8_t last_power_setting;
457 ao_mutex_get(&ao_radio_mutex);
458 if (!ao_radio_configured)
460 if (ao_config.radio_setting != last_radio_setting) {
461 ao_radio_reg_write(CC115L_FREQ2, ao_config.radio_setting >> 16);
462 ao_radio_reg_write(CC115L_FREQ1, ao_config.radio_setting >> 8);
463 ao_radio_reg_write(CC115L_FREQ0, ao_config.radio_setting);
464 last_radio_setting = ao_config.radio_setting;
466 if (ao_config.radio_power != last_power_setting) {
467 ao_radio_reg_write(CC115L_PA, ao_config.radio_power);
468 last_power_setting = ao_config.radio_power;
470 ao_radio_set_len(len);
473 #define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
476 ao_rdf_start(uint8_t len)
481 ao_radio_set_mode(AO_RADIO_MODE_RDF);
491 ao_arch_block_interrupts();
492 while (!ao_radio_wake && !ao_radio_abort && !ao_radio_mcu_wake)
493 ao_sleep(&ao_radio_wake);
494 ao_arch_release_interrupts();
495 if (ao_radio_mcu_wake)
496 ao_radio_check_marcstate();
506 ao_rdf_start(AO_RADIO_RDF_LEN);
508 ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN);
514 ao_radio_continuity(uint8_t c)
519 ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN);
521 status = ao_radio_fifo_write_start();
522 for (i = 0; i < 3; i++) {
523 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
525 ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN);
527 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN);
529 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
530 status = ao_radio_fifo_write_stop(status);
536 ao_radio_rdf_abort(void)
539 ao_wakeup(&ao_radio_wake);
543 ao_radio_test_cmd(void)
546 static uint8_t radio_on;
548 if (ao_cmd_lex_c != '\n') {
550 mode = (uint8_t) ao_cmd_lex_u32;
553 if ((mode & 2) && !radio_on) {
555 ao_monitor_disable();
558 ao_packet_slave_stop();
562 ao_radio_strobe(CC115L_STX);
565 for (t = 0; t < 10; t++) {
566 printf ("status: %02x\n", ao_radio_status());
567 ao_delay(AO_MS_TO_TICKS(100));
574 printf ("Hit a character to stop..."); flush();
578 if ((mode & 1) && radio_on) {
589 ao_radio_wait_isr(void)
591 ao_arch_block_interrupts();
592 while (!ao_radio_wake && !ao_radio_mcu_wake && !ao_radio_abort)
593 ao_sleep(&ao_radio_wake);
594 ao_arch_release_interrupts();
595 if (ao_radio_mcu_wake)
596 ao_radio_check_marcstate();
600 ao_radio_wait_tx(uint8_t wait_fifo)
602 uint8_t fifo_space = 0;
608 fifo_space = ao_radio_tx_fifo_space();
609 } while (!fifo_space && !ao_radio_abort);
613 static uint8_t tx_data[(AO_RADIO_MAX_SEND + 4) * 2];
616 ao_radio_send(const void *d, uint8_t size)
619 uint8_t *e = tx_data;
625 encode_len = ao_fec_encode(d, size, tx_data);
627 ao_radio_get(encode_len);
630 fifo_space = CC115L_FIFO_SIZE;
632 this_len = encode_len;
635 if (this_len > fifo_space) {
636 this_len = fifo_space;
637 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_BUF);
639 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_FINISH);
642 ao_radio_fifo_write(e, this_len);
644 encode_len -= this_len;
650 ao_exti_enable(AO_CC115L_INT_PORT, AO_CC115L_INT_PIN);
653 fifo_space = ao_radio_wait_tx(encode_len != 0);
654 if (ao_radio_abort) {
663 #define AO_RADIO_LOTS 64
666 ao_radio_send_lots(ao_radio_fill_func fill)
668 uint8_t buf[AO_RADIO_LOTS], *b;
676 fifo_space = CC115L_FIFO_SIZE;
678 cnt = (*fill)(buf, sizeof(buf));
685 /* At the last buffer, set the total length */
687 ao_radio_set_len(total & 0xff);
691 uint8_t this_len = cnt;
693 /* Wait for some space in the fifo */
694 while (!ao_radio_abort && (fifo_space = ao_radio_tx_fifo_space()) == 0) {
700 if (this_len > fifo_space)
701 this_len = fifo_space;
707 ao_radio_set_mode(AO_RADIO_MODE_APRS_LAST_BUF);
709 ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
711 ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
713 ao_radio_fifo_write(b, this_len);
720 ao_exti_enable(AO_CC115L_INT_PORT, AO_CC115L_INT_PIN);
722 if (ao_radio_abort) {
726 /* Wait for the transmitter to go idle */
734 static char *cc115l_state_name[] = {
735 [CC115L_STATUS_STATE_IDLE] = "IDLE",
736 [CC115L_STATUS_STATE_TX] = "TX",
737 [CC115L_STATUS_STATE_FSTXON] = "FSTXON",
738 [CC115L_STATUS_STATE_CALIBRATE] = "CALIBRATE",
739 [CC115L_STATUS_STATE_SETTLING] = "SETTLING",
740 [CC115L_STATUS_STATE_TX_FIFO_UNDERFLOW] = "TX_FIFO_UNDERFLOW",
743 struct ao_cc115l_reg {
748 const static struct ao_cc115l_reg ao_cc115l_reg[] = {
749 { .addr = CC115L_IOCFG2, .name = "IOCFG2" },
750 { .addr = CC115L_IOCFG1, .name = "IOCFG1" },
751 { .addr = CC115L_IOCFG0, .name = "IOCFG0" },
752 { .addr = CC115L_FIFOTHR, .name = "FIFOTHR" },
753 { .addr = CC115L_SYNC1, .name = "SYNC1" },
754 { .addr = CC115L_SYNC0, .name = "SYNC0" },
755 { .addr = CC115L_PKTLEN, .name = "PKTLEN" },
756 { .addr = CC115L_PKTCTRL0, .name = "PKTCTRL0" },
757 { .addr = CC115L_CHANNR, .name = "CHANNR" },
758 { .addr = CC115L_FSCTRL0, .name = "FSCTRL0" },
759 { .addr = CC115L_FREQ2, .name = "FREQ2" },
760 { .addr = CC115L_FREQ1, .name = "FREQ1" },
761 { .addr = CC115L_FREQ0, .name = "FREQ0" },
762 { .addr = CC115L_MDMCFG4, .name = "MDMCFG4" },
763 { .addr = CC115L_MDMCFG3, .name = "MDMCFG3" },
764 { .addr = CC115L_MDMCFG2, .name = "MDMCFG2" },
765 { .addr = CC115L_MDMCFG1, .name = "MDMCFG1" },
766 { .addr = CC115L_MDMCFG0, .name = "MDMCFG0" },
767 { .addr = CC115L_DEVIATN, .name = "DEVIATN" },
768 { .addr = CC115L_MCSM1, .name = "MCSM1" },
769 { .addr = CC115L_MCSM0, .name = "MCSM0" },
770 { .addr = CC115L_RESERVED_0X20, .name = "RESERVED_0X20" },
771 { .addr = CC115L_FREND0, .name = "FREND0" },
772 { .addr = CC115L_FSCAL3, .name = "FSCAL3" },
773 { .addr = CC115L_FSCAL2, .name = "FSCAL2" },
774 { .addr = CC115L_FSCAL1, .name = "FSCAL1" },
775 { .addr = CC115L_FSCAL0, .name = "FSCAL0" },
776 { .addr = CC115L_RESERVED_0X29, .name = "RESERVED_0X29" },
777 { .addr = CC115L_RESERVED_0X2A, .name = "RESERVED_0X2A" },
778 { .addr = CC115L_RESERVED_0X2B, .name = "RESERVED_0X2B" },
779 { .addr = CC115L_TEST2, .name = "TEST2" },
780 { .addr = CC115L_TEST1, .name = "TEST1" },
781 { .addr = CC115L_TEST0, .name = "TEST0" },
782 { .addr = CC115L_PARTNUM, .name = "PARTNUM" },
783 { .addr = CC115L_VERSION, .name = "VERSION" },
784 { .addr = CC115L_MARCSTATE, .name = "MARCSTATE" },
785 { .addr = CC115L_PKTSTATUS, .name = "PKTSTATUS" },
786 { .addr = CC115L_TXBYTES, .name = "TXBYTES" },
787 { .addr = CC115L_PA, .name = "PA" },
790 #define AO_NUM_CC115L_REG (sizeof ao_cc115l_reg / sizeof ao_cc115l_reg[0])
792 static void ao_radio_show(void) {
793 uint8_t status = ao_radio_status();
797 status = ao_radio_status();
798 printf ("Status: %02x\n", status);
799 printf ("CHIP_RDY: %d\n", (status >> CC115L_STATUS_CHIP_RDY) & 1);
800 printf ("STATE: %s\n", cc115l_state_name[(status >> CC115L_STATUS_STATE) & CC115L_STATUS_STATE_MASK]);
801 printf ("MARC: %02x\n", ao_radio_get_marcstate());
803 for (i = 0; i < AO_NUM_CC115L_REG; i++)
804 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc115l_reg[i].addr), ao_cc115l_reg[i].name);
808 static void ao_radio_beep(void) {
812 static void ao_radio_packet(void) {
813 static const uint8_t packet[] = {
815 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
816 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
817 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
818 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
824 ao_radio_send(packet, sizeof (packet));
834 ao_packet_slave_stop();
840 static const struct ao_cmds ao_radio_cmds[] = {
841 { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
844 { ao_radio_aprs, "G\0Send APRS packet" },
846 { ao_radio_show, "R\0Show CC115L status" },
847 { ao_radio_beep, "b\0Emit an RDF beacon" },
848 { ao_radio_packet, "p\0Send a test packet" },
858 ao_radio_configured = 0;
859 ao_spi_init_cs (AO_CC115L_SPI_CS_PORT, (1 << AO_CC115L_SPI_CS_PIN));
862 AO_CC115L_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC115L_SPI_CS_PIN));
863 for (i = 0; i < 10000; i++) {
864 if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0)
867 AO_CC115L_SPI_CS_PORT->bsrr = (1 << AO_CC115L_SPI_CS_PIN);
869 ao_panic(AO_PANIC_SELF_TEST_CC115L);
872 /* Enable the EXTI interrupt for the appropriate pin */
873 ao_enable_port(AO_CC115L_INT_PORT);
874 ao_exti_setup(AO_CC115L_INT_PORT, AO_CC115L_INT_PIN,
875 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
878 /* Enable the hacked up GPIO3 pin */
879 ao_enable_port(AO_CC115L_MCU_WAKEUP_PORT);
880 ao_exti_setup(AO_CC115L_MCU_WAKEUP_PORT, AO_CC115L_MCU_WAKEUP_PIN,
881 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED,
882 ao_radio_mcu_wakeup_isr);
886 ao_cmd_register(&ao_radio_cmds[0]);