+++ /dev/null
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-__xdata struct ao_packet_recv ao_rx_packet;
-__xdata struct ao_packet ao_tx_packet;
-__pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used;
-
-static __xdata char tx_data[AO_PACKET_MAX];
-static __xdata char rx_data[AO_PACKET_MAX];
-static __pdata uint8_t rx_seq;
-
-__xdata struct ao_task ao_packet_task;
-__xdata uint8_t ao_packet_enable;
-__xdata uint8_t ao_packet_master_sleeping;
-
-void
-ao_packet_send(void)
-{
-#ifdef AO_LED_RED
- ao_led_on(AO_LED_RED);
-#endif
- /* If any tx data is pending then copy it into the tx packet */
- if (ao_packet_tx_used && ao_tx_packet.len == 0) {
- ao_xmemcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used);
- ao_tx_packet.len = ao_packet_tx_used;
- ao_tx_packet.seq++;
- ao_packet_tx_used = 0;
- ao_wakeup(&tx_data);
- }
- ao_radio_send(&ao_tx_packet, sizeof (ao_tx_packet));
-#ifdef AO_LED_RED
- ao_led_off(AO_LED_RED);
-#endif
-}
-
-uint8_t
-ao_packet_recv(void)
-{
- uint8_t dma_done;
-
-#ifdef AO_LED_GREEN
- ao_led_on(AO_LED_GREEN);
-#endif
- dma_done = ao_radio_recv(&ao_rx_packet, sizeof (struct ao_packet_recv));
-#ifdef AO_LED_GREEN
- ao_led_off(AO_LED_GREEN);
-#endif
-
- /* Check to see if we got a valid packet */
- if (!dma_done)
- return 0;
- if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK))
- return 0;
-
- /* Accept packets with matching call signs, or any packet if
- * our callsign hasn't been configured
- */
- if (ao_xmemcmp(ao_rx_packet.packet.callsign,
- ao_config.callsign,
- AO_MAX_CALLSIGN) != 0 &&
- ao_xmemcmp(ao_config.callsign, CODE_TO_XDATA("N0CALL"), 7) != 0)
- return 0;
-
- /* SYN packets carry no data */
- if (ao_rx_packet.packet.len == AO_PACKET_SYN) {
- rx_seq = ao_rx_packet.packet.seq;
- ao_tx_packet.seq = ao_rx_packet.packet.ack;
- ao_tx_packet.ack = rx_seq;
- } else if (ao_rx_packet.packet.len) {
-
- /* Check for incoming data at the next sequence and
- * for an empty data buffer
- */
- if (ao_rx_packet.packet.seq == (uint8_t) (rx_seq + (uint8_t) 1) &&
- ao_packet_rx_used == ao_packet_rx_len) {
-
- /* Copy data to the receive data buffer and set up the
- * offsets
- */
- ao_xmemcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len);
- ao_packet_rx_used = 0;
- ao_packet_rx_len = ao_rx_packet.packet.len;
-
- /* Mark the sequence that we've received to
- * let the sender know when we return a packet
- */
- rx_seq = ao_rx_packet.packet.seq;
- ao_tx_packet.ack = rx_seq;
-
- /* Poke anyone looking for received data */
- ao_wakeup(&ao_stdin_ready);
- }
- }
-
- /* If the other side has seen the latest data we queued,
- * wake up any task waiting to send data and let them go again
- */
- if (ao_rx_packet.packet.ack == ao_tx_packet.seq) {
- ao_tx_packet.len = 0;
- ao_wakeup(&ao_tx_packet);
- }
- return 1;
-}
-
-#ifndef PACKET_HAS_MASTER
-#define PACKET_HAS_MASTER 1
-#endif
-
-#if PACKET_HAS_MASTER
-void
-ao_packet_flush(void)
-{
- /* If there is data to send, and this is the master,
- * then poke the master to send all queued data
- */
- if (ao_packet_tx_used && ao_packet_master_sleeping)
- ao_wakeup(&ao_packet_master_sleeping);
-}
-#endif /* PACKET_HAS_MASTER */
-
-void
-ao_packet_putchar(char c) __reentrant
-{
- while (ao_packet_tx_used == AO_PACKET_MAX && ao_packet_enable) {
-#if PACKET_HAS_MASTER
- ao_packet_flush();
-#endif
- ao_sleep(&tx_data);
- }
-
- if (ao_packet_enable)
- tx_data[ao_packet_tx_used++] = c;
-}
-
-char
-ao_packet_pollchar(void) __critical
-{
- if (!ao_packet_enable)
- return AO_READ_AGAIN;
-
- if (ao_packet_rx_used == ao_packet_rx_len)
- return AO_READ_AGAIN;
-
- return rx_data[ao_packet_rx_used++];
-}
+++ /dev/null
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-static char
-ao_packet_getchar(void) __critical
-{
- char c;
- while ((c = ao_packet_pollchar()) == AO_READ_AGAIN) {
- if (!ao_packet_enable)
- break;
- if (ao_packet_master_sleeping)
- ao_wakeup(&ao_packet_master_sleeping);
- flush();
- ao_sleep(&ao_stdin_ready);
- }
- return c;
-}
-
-static void
-ao_packet_echo(void) __reentrant
-{
- char c;
- while (ao_packet_enable) {
- c = ao_packet_getchar();
- if (c != AO_READ_AGAIN)
- putchar(c);
- }
- ao_exit();
-}
-
-static __xdata struct ao_task ao_packet_echo_task;
-static __xdata uint16_t ao_packet_master_delay;
-static __xdata uint16_t ao_packet_master_time;
-
-#define AO_PACKET_MASTER_DELAY_SHORT AO_MS_TO_TICKS(100)
-#define AO_PACKET_MASTER_DELAY_LONG AO_MS_TO_TICKS(1000)
-#define AO_PACKET_MASTER_DELAY_TIMEOUT AO_MS_TO_TICKS(2000)
-
-static void
-ao_packet_master_busy(void)
-{
- ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT;
- ao_packet_master_time = ao_time();
-}
-
-static void
-ao_packet_master_check_busy(void)
-{
- int16_t idle;
- if (ao_packet_master_delay != AO_PACKET_MASTER_DELAY_SHORT)
- return;
- idle = (int16_t) (ao_time() - ao_packet_master_time);
-
- if (idle > AO_PACKET_MASTER_DELAY_TIMEOUT)
- ao_packet_master_delay = AO_PACKET_MASTER_DELAY_LONG;
-}
-
-void
-ao_packet_master(void)
-{
- ao_config_get();
- ao_tx_packet.addr = ao_serial_number;
- ao_tx_packet.len = AO_PACKET_SYN;
- ao_packet_master_time = ao_time();
- ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT;
- while (ao_packet_enable) {
- uint8_t r;
- ao_xmemcpy(ao_tx_packet.callsign, ao_config.callsign, AO_MAX_CALLSIGN);
- ao_packet_send();
- if (ao_tx_packet.len)
- ao_packet_master_busy();
- ao_packet_master_check_busy();
- ao_alarm(ao_packet_master_delay);
- r = ao_packet_recv();
- ao_clear_alarm();
- if (r) {
- /* if we can transmit data, do so */
- if (ao_packet_tx_used && ao_tx_packet.len == 0)
- continue;
- if (ao_rx_packet.packet.len)
- ao_packet_master_busy();
- ao_packet_master_sleeping = 1;
- ao_alarm(ao_packet_master_delay);
- ao_sleep(&ao_packet_master_sleeping);
- ao_clear_alarm();
- ao_packet_master_sleeping = 0;
- }
- }
- ao_exit();
-}
-
-static void
-ao_packet_forward(void) __reentrant
-{
- char c;
- ao_packet_enable = 1;
- ao_cmd_white();
-
- flush();
-#if HAS_MONITOR
- ao_monitor_disable();
-#endif
- ao_add_task(&ao_packet_task, ao_packet_master, "master");
- ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo");
- while ((c = getchar()) != '~') {
- if (c == '\r') c = '\n';
- ao_packet_putchar(c);
- }
-
- /* Wait for a second if there is any pending data */
- for (c = 0; (ao_packet_tx_used || ao_tx_packet.len) && c < 10; c++)
- ao_delay(AO_MS_TO_TICKS(100));
- ao_packet_enable = 0;
- while (ao_packet_echo_task.wchan || ao_packet_task.wchan) {
- ao_radio_recv_abort();
- ao_wakeup(&ao_stdin_ready);
- ao_delay(AO_MS_TO_TICKS(10));
- }
-#if HAS_MONITOR
- ao_monitor_enable();
-#endif
-}
-
-
-
-__code struct ao_cmds ao_packet_master_cmds[] = {
- { ao_packet_forward, "p\0Remote packet link." },
- { 0, NULL },
-};
-
-void
-ao_packet_master_init(void)
-{
- ao_cmd_register(&ao_packet_master_cmds[0]);
-}
+++ /dev/null
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-void
-ao_packet_slave(void)
-{
- ao_tx_packet.addr = ao_serial_number;
- ao_tx_packet.len = AO_PACKET_SYN;
- while (ao_packet_enable) {
- if (ao_packet_recv()) {
- ao_xmemcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN);
-#if HAS_FLIGHT
- ao_flight_force_idle = TRUE;
-#endif
- ao_packet_send();
- }
- }
- ao_exit();
-}
-
-void
-ao_packet_slave_start(void)
-{
- if (!ao_packet_enable) {
- ao_packet_enable = 1;
- ao_add_task(&ao_packet_task, ao_packet_slave, "slave");
- }
-}
-
-void
-ao_packet_slave_stop(void)
-{
- if (ao_packet_enable) {
- ao_packet_enable = 0;
- while (ao_packet_task.wchan) {
- ao_radio_recv_abort();
- ao_delay(AO_MS_TO_TICKS(10));
- }
- }
-}
-
-void
-ao_packet_slave_init(uint8_t enable)
-{
- ao_add_stdio(ao_packet_pollchar,
- ao_packet_putchar,
- NULL);
- if (enable)
- ao_packet_slave_start();
-}
*/
#include <ao.h>
+#include <ao_cc1120.h>
+#include <ao_exti.h>
+
+uint8_t ao_radio_done;
+uint8_t ao_radio_mutex;
+uint8_t ao_radio_abort;
+
+#define CC1120_DEBUG 1
uint32_t ao_radio_cal = 1186611;
+#define ao_radio_select() ao_spi_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS)
+#define ao_radio_deselect() ao_spi_put_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS)
+#define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1120_SPI_BUS)
+#define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1120_SPI_BUS)
+#define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1120_SPI_BUS)
+#define ao_radio_duplex(o,i,l) ao_spi_duplex((o), (i), (l), AO_CC1120_SPI_BUS)
+
+static uint8_t
+ao_radio_reg_read(uint16_t addr)
+{
+ uint8_t data[2];
+ uint8_t d;
+
+#if CC1120_DEBUG
+ printf("ao_radio_reg_read (%04x): ", addr); flush();
+#endif
+ if (CC1120_IS_EXTENDED(addr)) {
+ data[0] = ((1 << CC1120_READ) |
+ (0 << CC1120_BURST) |
+ CC1120_EXTENDED);
+ data[1] = addr;
+ d = 2;
+ } else {
+ data[0] = ((1 << CC1120_READ) |
+ (0 << CC1120_BURST) |
+ addr);
+ d = 1;
+ }
+ ao_radio_select();
+ ao_radio_spi_send(data, d);
+ ao_radio_spi_recv(data, 1);
+ ao_radio_deselect();
+#if CC1120_DEBUG
+ printf (" %02x\n", data[0]);
+#endif
+ return data[0];
+}
+
+static void
+ao_radio_reg_write(uint16_t addr, uint8_t value)
+{
+ uint8_t data[3];
+ uint8_t d;
+
+#if CC1120_DEBUG
+ printf("ao_radio_reg_write (%04x): %02x\n", addr, value);
+#endif
+ if (CC1120_IS_EXTENDED(addr)) {
+ data[0] = ((1 << CC1120_READ) |
+ (0 << CC1120_BURST) |
+ CC1120_EXTENDED);
+ data[1] = addr;
+ d = 2;
+ } else {
+ data[0] = ((1 << CC1120_READ) |
+ (0 << CC1120_BURST) |
+ addr);
+ d = 1;
+ }
+ data[d] = value;
+ ao_radio_select();
+ ao_radio_spi_send(data, d+1);
+ ao_radio_deselect();
+}
+
+static uint8_t
+ao_radio_strobe(uint8_t addr)
+{
+ uint8_t in;
+
+ ao_radio_select();
+ ao_radio_duplex(&addr, &in, 1);
+ ao_radio_deselect();
+ return in;
+}
+
+static uint8_t
+ao_radio_fifo_read(uint8_t *data, uint8_t len)
+{
+ uint8_t addr = ((1 << CC1120_READ) |
+ (1 << CC1120_BURST) |
+ CC1120_FIFO);
+ uint8_t status;
+
+ ao_radio_select();
+ ao_radio_duplex(&addr, &status, 1);
+ ao_radio_spi_recv(data, len);
+ ao_radio_deselect();
+ return status;
+}
+
+static uint8_t
+ao_radio_fifo_write(uint8_t *data, uint8_t len)
+{
+ uint8_t addr = ((0 << CC1120_READ) |
+ (1 << CC1120_BURST) |
+ CC1120_FIFO);
+ uint8_t status;
+
+ ao_radio_select();
+ ao_radio_duplex(&addr, &status, 1);
+ ao_radio_spi_send(data, len);
+ ao_radio_deselect();
+ return status;
+}
+
+static uint8_t
+ao_radio_fifo_write_fixed(uint8_t data, uint8_t len)
+{
+ uint8_t addr = ((0 << CC1120_READ) |
+ (1 << CC1120_BURST) |
+ CC1120_FIFO);
+ uint8_t status;
+
+ ao_radio_select();
+ ao_radio_duplex(&addr, &status, 1);
+ ao_radio_spi_send_fixed(data, len);
+ ao_radio_deselect();
+ return status;
+}
+
+static uint8_t
+ao_radio_status(void)
+{
+ return ao_radio_strobe (CC1120_SNOP);
+}
+
void
ao_radio_recv_abort(void)
{
+ ao_radio_abort = 1;
+ ao_wakeup(&ao_radio_done);
+}
+
+#define ao_radio_rdf_value 0x55
+
+static const uint16_t rdf_setup[] = {
+};
+
+void
+ao_radio_rdf(uint8_t len)
+{
+ int i;
+
+ ao_radio_abort = 0;
+ ao_radio_get(len);
+ ao_radio_done = 0;
+ for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2)
+ ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]);
+ ao_radio_fifo_write_fixed(ao_radio_rdf_value, len);
+ ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG);
+ ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
+ ao_radio_strobe(CC1120_STX);
+ cli();
+ while (!ao_radio_done)
+ ao_sleep(&ao_radio_done);
+ sei();
+ ao_radio_set_packet();
+ ao_radio_put();
+}
+
+void
+ao_radio_rdf_abort(void)
+{
+}
+
+static void
+ao_radio_test(void)
+{
+ uint8_t mode = 2;
+ uint8_t radio_on;
+ ao_cmd_white();
+ if (ao_cmd_lex_c != '\n') {
+ ao_cmd_decimal();
+ mode = (uint8_t) ao_cmd_lex_u32;
+ }
+ mode++;
+ if ((mode & 2) && !radio_on) {
+#if HAS_MONITOR
+ ao_monitor_disable();
+#endif
+#if PACKET_HAS_SLAVE
+ ao_packet_slave_stop();
+#endif
+ ao_radio_get(0xff);
+ ao_radio_strobe(CC1120_STX);
+ radio_on = 1;
+ }
+ if (mode == 3) {
+ printf ("Hit a character to stop..."); flush();
+ getchar();
+ putchar('\n');
+ }
+ if ((mode & 1) && radio_on) {
+ ao_radio_idle();
+ ao_radio_put();
+ radio_on = 0;
+#if HAS_MONITOR
+ ao_monitor_enable();
+#endif
+ }
+}
+
+void
+ao_radio_send(void *d, uint8_t size)
+{
+ ao_radio_get(size);
+ ao_radio_done = 0;
+ ao_radio_fifo_write(d, size);
+ ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG);
+ ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
+ ao_radio_strobe(CC1120_STX);
+ cli();
+ while (!ao_radio_done)
+ ao_sleep(&ao_radio_done);
+ sei();
+ ao_radio_put();
+}
+
+uint8_t
+ao_radio_recv(__xdata void *d, uint8_t size)
+{
+ /* configure interrupt pin */
+ ao_radio_get(size);
+ ao_radio_done = 0;
+ ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RXFIFO_THR_PKT);
+ ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
+ ao_radio_strobe(CC1120_SRX);
+ cli();
+ while (!ao_radio_done && !ao_radio_abort)
+ ao_sleep(&ao_radio_done);
+ sei();
+ if (ao_radio_done)
+ ao_radio_fifo_read(d, size);
+ ao_radio_put();
+ return 0;
+}
+
+static const uint16_t packet_setup[] = {
+};
+
+void
+ao_radio_set_packet(void)
+{
+ int i;
+
+ for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2)
+ ao_radio_reg_write(packet_setup[i], packet_setup[i+1]);
+}
+
+void
+ao_radio_idle(void)
+{
+ for (;;) {
+ uint8_t state = ao_radio_strobe(CC1120_SIDLE);
+ if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_IDLE)
+ break;
+ }
+}
+
+static const uint16_t radio_setup[] = {
+#include "ao_cc1120_CC1120.h"
+};
+
+static uint8_t ao_radio_configured = 0;
+
+static void
+ao_radio_isr(void)
+{
+ ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
+ ao_radio_done = 1;
+ ao_wakeup(&ao_radio_done);
+}
+
+static void
+ao_radio_setup(void)
+{
+ int i;
+
+ for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2)
+ ao_radio_reg_write(radio_setup[i], radio_setup[i+1]);
+
+ /* Disable GPIO2 pin (radio_int) */
+ ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_HIGHZ);
+
+ /* Enable the EXTI interrupt for the appropriate pin */
+ ao_enable_port(AO_CC1120_INT_PORT);
+ ao_exti_setup(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_EXTI_MODE_RISING, ao_radio_isr);
+
+ ao_radio_set_packet();
+ ao_radio_configured = 1;
+}
+
+void
+ao_radio_get(uint8_t len)
+{
+ ao_mutex_get(&ao_radio_mutex);
+ if (!ao_radio_configured)
+ ao_radio_setup();
+ ao_radio_reg_write(CC1120_PKT_LEN, len);
+}
+
+#if CC1120_DEBUG
+static char *cc1120_state_name[] = {
+ [CC1120_STATUS_STATE_IDLE] = "IDLE",
+ [CC1120_STATUS_STATE_RX] = "RX",
+ [CC1120_STATUS_STATE_TX] = "TX",
+ [CC1120_STATUS_STATE_FSTXON] = "FSTXON",
+ [CC1120_STATUS_STATE_CALIBRATE] = "CALIBRATE",
+ [CC1120_STATUS_STATE_SETTLING] = "SETTLING",
+ [CC1120_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
+ [CC1120_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
+};
+
+struct ao_cc1120_reg {
+ uint16_t addr;
+ char *name;
+};
+
+const static struct ao_cc1120_reg ao_cc1120_reg[] = {
+ { .addr = CC1120_IOCFG3, .name = "IOCFG3" },
+ { .addr = CC1120_IOCFG2, .name = "IOCFG2" },
+ { .addr = CC1120_IOCFG1, .name = "IOCFG1" },
+ { .addr = CC1120_IOCFG0, .name = "IOCFG0" },
+ { .addr = CC1120_SYNC3, .name = "SYNC3" },
+ { .addr = CC1120_SYNC2, .name = "SYNC2" },
+ { .addr = CC1120_SYNC1, .name = "SYNC1" },
+ { .addr = CC1120_SYNC0, .name = "SYNC0" },
+ { .addr = CC1120_SYNC_CFG1, .name = "SYNC_CFG1" },
+ { .addr = CC1120_SYNC_CFG0, .name = "SYNC_CFG0" },
+ { .addr = CC1120_DEVIATION_M, .name = "DEVIATION_M" },
+ { .addr = CC1120_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
+ { .addr = CC1120_DCFILT_CFG, .name = "DCFILT_CFG" },
+ { .addr = CC1120_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
+ { .addr = CC1120_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
+ { .addr = CC1120_FREQ_IF_CFG, .name = "FREQ_IF_CFG" },
+ { .addr = CC1120_IQIC, .name = "IQIC" },
+ { .addr = CC1120_CHAN_BW, .name = "CHAN_BW" },
+ { .addr = CC1120_MDMCFG1, .name = "MDMCFG1" },
+ { .addr = CC1120_MDMCFG0, .name = "MDMCFG0" },
+ { .addr = CC1120_DRATE2, .name = "DRATE2" },
+ { .addr = CC1120_DRATE1, .name = "DRATE1" },
+ { .addr = CC1120_DRATE0, .name = "DRATE0" },
+ { .addr = CC1120_AGC_REF, .name = "AGC_REF" },
+ { .addr = CC1120_AGC_CS_THR, .name = "AGC_CS_THR" },
+ { .addr = CC1120_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
+ { .addr = CC1120_AGC_CFG3, .name = "AGC_CFG3" },
+ { .addr = CC1120_AGC_CFG2, .name = "AGC_CFG2" },
+ { .addr = CC1120_AGC_CFG1, .name = "AGC_CFG1" },
+ { .addr = CC1120_AGC_CFG0, .name = "AGC_CFG0" },
+ { .addr = CC1120_FIFO_CFG, .name = "FIFO_CFG" },
+ { .addr = CC1120_DEV_ADDR, .name = "DEV_ADDR" },
+ { .addr = CC1120_SETTLING_CFG, .name = "SETTLING_CFG" },
+ { .addr = CC1120_FS_CFG, .name = "FS_CFG" },
+ { .addr = CC1120_WOR_CFG1, .name = "WOR_CFG1" },
+ { .addr = CC1120_WOR_CFG0, .name = "WOR_CFG0" },
+ { .addr = CC1120_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
+ { .addr = CC1120_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
+ { .addr = CC1120_PKT_CFG2, .name = "PKT_CFG2" },
+ { .addr = CC1120_PKT_CFG1, .name = "PKT_CFG1" },
+ { .addr = CC1120_PKT_CFG0, .name = "PKT_CFG0" },
+ { .addr = CC1120_RFEND_CFG1, .name = "RFEND_CFG1" },
+ { .addr = CC1120_RFEND_CFG0, .name = "RFEND_CFG0" },
+ { .addr = CC1120_PA_CFG2, .name = "PA_CFG2" },
+ { .addr = CC1120_PA_CFG1, .name = "PA_CFG1" },
+ { .addr = CC1120_PA_CFG0, .name = "PA_CFG0" },
+ { .addr = CC1120_PKT_LEN, .name = "PKT_LEN" },
+ { .addr = CC1120_IF_MIX_CFG, .name = "IF_MIX_CFG" },
+ { .addr = CC1120_FREQOFF_CFG, .name = "FREQOFF_CFG" },
+ { .addr = CC1120_TOC_CFG, .name = "TOC_CFG" },
+ { .addr = CC1120_MARC_SPARE, .name = "MARC_SPARE" },
+ { .addr = CC1120_ECG_CFG, .name = "ECG_CFG" },
+ { .addr = CC1120_SOFT_TX_DATA_CFG, .name = "SOFT_TX_DATA_CFG" },
+ { .addr = CC1120_EXT_CTRL, .name = "EXT_CTRL" },
+ { .addr = CC1120_RCCAL_FINE, .name = "RCCAL_FINE" },
+ { .addr = CC1120_RCCAL_COARSE, .name = "RCCAL_COARSE" },
+ { .addr = CC1120_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
+ { .addr = CC1120_FREQOFF1, .name = "FREQOFF1" },
+ { .addr = CC1120_FREQOFF0, .name = "FREQOFF0" },
+ { .addr = CC1120_FREQ2, .name = "FREQ2" },
+ { .addr = CC1120_FREQ1, .name = "FREQ1" },
+ { .addr = CC1120_FREQ0, .name = "FREQ0" },
+ { .addr = CC1120_IF_ADC2, .name = "IF_ADC2" },
+ { .addr = CC1120_IF_ADC1, .name = "IF_ADC1" },
+ { .addr = CC1120_IF_ADC0, .name = "IF_ADC0" },
+ { .addr = CC1120_FS_DIG1, .name = "FS_DIG1" },
+ { .addr = CC1120_FS_DIG0, .name = "FS_DIG0" },
+ { .addr = CC1120_FS_CAL3, .name = "FS_CAL3" },
+ { .addr = CC1120_FS_CAL2, .name = "FS_CAL2" },
+ { .addr = CC1120_FS_CAL1, .name = "FS_CAL1" },
+ { .addr = CC1120_FS_CAL0, .name = "FS_CAL0" },
+ { .addr = CC1120_FS_CHP, .name = "FS_CHP" },
+ { .addr = CC1120_FS_DIVTWO, .name = "FS_DIVTWO" },
+ { .addr = CC1120_FS_DSM1, .name = "FS_DSM1" },
+ { .addr = CC1120_FS_DSM0, .name = "FS_DSM0" },
+ { .addr = CC1120_FS_DVC1, .name = "FS_DVC1" },
+ { .addr = CC1120_FS_DVC0, .name = "FS_DVC0" },
+ { .addr = CC1120_FS_LBI, .name = "FS_LBI" },
+ { .addr = CC1120_FS_PFD, .name = "FS_PFD" },
+ { .addr = CC1120_FS_PRE, .name = "FS_PRE" },
+ { .addr = CC1120_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
+ { .addr = CC1120_FS_SPARE, .name = "FS_SPARE" },
+ { .addr = CC1120_FS_VCO4, .name = "FS_VCO4" },
+ { .addr = CC1120_FS_VCO3, .name = "FS_VCO3" },
+ { .addr = CC1120_FS_VCO2, .name = "FS_VCO2" },
+ { .addr = CC1120_FS_VCO1, .name = "FS_VCO1" },
+ { .addr = CC1120_FS_VCO0, .name = "FS_VCO0" },
+ { .addr = CC1120_GBIAS6, .name = "GBIAS6" },
+ { .addr = CC1120_GBIAS5, .name = "GBIAS5" },
+ { .addr = CC1120_GBIAS4, .name = "GBIAS4" },
+ { .addr = CC1120_GBIAS3, .name = "GBIAS3" },
+ { .addr = CC1120_GBIAS2, .name = "GBIAS2" },
+ { .addr = CC1120_GBIAS1, .name = "GBIAS1" },
+ { .addr = CC1120_GBIAS0, .name = "GBIAS0" },
+ { .addr = CC1120_IFAMP, .name = "IFAMP" },
+ { .addr = CC1120_LNA, .name = "LNA" },
+ { .addr = CC1120_RXMIX, .name = "RXMIX" },
+ { .addr = CC1120_XOSC5, .name = "XOSC5" },
+ { .addr = CC1120_XOSC4, .name = "XOSC4" },
+ { .addr = CC1120_XOSC3, .name = "XOSC3" },
+ { .addr = CC1120_XOSC2, .name = "XOSC2" },
+ { .addr = CC1120_XOSC1, .name = "XOSC1" },
+ { .addr = CC1120_XOSC0, .name = "XOSC0" },
+ { .addr = CC1120_ANALOG_SPARE, .name = "ANALOG_SPARE" },
+ { .addr = CC1120_PA_CFG3, .name = "PA_CFG3" },
+ { .addr = CC1120_WOR_TIME1, .name = "WOR_TIME1" },
+ { .addr = CC1120_WOR_TIME0, .name = "WOR_TIME0" },
+ { .addr = CC1120_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
+ { .addr = CC1120_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
+ { .addr = CC1120_BIST, .name = "BIST" },
+ { .addr = CC1120_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
+ { .addr = CC1120_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
+ { .addr = CC1120_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
+ { .addr = CC1120_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
+ { .addr = CC1120_IQIE_I1, .name = "IQIE_I1" },
+ { .addr = CC1120_IQIE_I0, .name = "IQIE_I0" },
+ { .addr = CC1120_IQIE_Q1, .name = "IQIE_Q1" },
+ { .addr = CC1120_IQIE_Q0, .name = "IQIE_Q0" },
+ { .addr = CC1120_RSSI1, .name = "RSSI1" },
+ { .addr = CC1120_RSSI0, .name = "RSSI0" },
+ { .addr = CC1120_MARCSTATE, .name = "MARCSTATE" },
+ { .addr = CC1120_LQI_VAL, .name = "LQI_VAL" },
+ { .addr = CC1120_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
+ { .addr = CC1120_DEM_STATUS, .name = "DEM_STATUS" },
+ { .addr = CC1120_FREQOFF_EST1, .name = "FREQOFF_EST1" },
+ { .addr = CC1120_FREQOFF_EST0, .name = "FREQOFF_EST0" },
+ { .addr = CC1120_AGC_GAIN3, .name = "AGC_GAIN3" },
+ { .addr = CC1120_AGC_GAIN2, .name = "AGC_GAIN2" },
+ { .addr = CC1120_AGC_GAIN1, .name = "AGC_GAIN1" },
+ { .addr = CC1120_AGC_GAIN0, .name = "AGC_GAIN0" },
+ { .addr = CC1120_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
+ { .addr = CC1120_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
+ { .addr = CC1120_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
+ { .addr = CC1120_RNDGEN, .name = "RNDGEN" },
+ { .addr = CC1120_MAGN2, .name = "MAGN2" },
+ { .addr = CC1120_MAGN1, .name = "MAGN1" },
+ { .addr = CC1120_MAGN0, .name = "MAGN0" },
+ { .addr = CC1120_ANG1, .name = "ANG1" },
+ { .addr = CC1120_ANG0, .name = "ANG0" },
+ { .addr = CC1120_CHFILT_I2, .name = "CHFILT_I2" },
+ { .addr = CC1120_CHFILT_I1, .name = "CHFILT_I1" },
+ { .addr = CC1120_CHFILT_I0, .name = "CHFILT_I0" },
+ { .addr = CC1120_CHFILT_Q2, .name = "CHFILT_Q2" },
+ { .addr = CC1120_CHFILT_Q1, .name = "CHFILT_Q1" },
+ { .addr = CC1120_CHFILT_Q0, .name = "CHFILT_Q0" },
+ { .addr = CC1120_GPIO_STATUS, .name = "GPIO_STATUS" },
+ { .addr = CC1120_FSCAL_CTRL, .name = "FSCAL_CTRL" },
+ { .addr = CC1120_PHASE_ADJUST, .name = "PHASE_ADJUST" },
+ { .addr = CC1120_PARTNUMBER, .name = "PARTNUMBER" },
+ { .addr = CC1120_PARTVERSION, .name = "PARTVERSION" },
+ { .addr = CC1120_SERIAL_STATUS, .name = "SERIAL_STATUS" },
+ { .addr = CC1120_RX_STATUS, .name = "RX_STATUS" },
+ { .addr = CC1120_TX_STATUS, .name = "TX_STATUS" },
+ { .addr = CC1120_MARC_STATUS1, .name = "MARC_STATUS1" },
+ { .addr = CC1120_MARC_STATUS0, .name = "MARC_STATUS0" },
+ { .addr = CC1120_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
+ { .addr = CC1120_FSRF_TEST, .name = "FSRF_TEST" },
+ { .addr = CC1120_PRE_TEST, .name = "PRE_TEST" },
+ { .addr = CC1120_PRE_OVR, .name = "PRE_OVR" },
+ { .addr = CC1120_ADC_TEST, .name = "ADC_TEST" },
+ { .addr = CC1120_DVC_TEST, .name = "DVC_TEST" },
+ { .addr = CC1120_ATEST, .name = "ATEST" },
+ { .addr = CC1120_ATEST_LVDS, .name = "ATEST_LVDS" },
+ { .addr = CC1120_ATEST_MODE, .name = "ATEST_MODE" },
+ { .addr = CC1120_XOSC_TEST1, .name = "XOSC_TEST1" },
+ { .addr = CC1120_XOSC_TEST0, .name = "XOSC_TEST0" },
+ { .addr = CC1120_RXFIRST, .name = "RXFIRST" },
+ { .addr = CC1120_TXFIRST, .name = "TXFIRST" },
+ { .addr = CC1120_RXLAST, .name = "RXLAST" },
+ { .addr = CC1120_TXLAST, .name = "TXLAST" },
+ { .addr = CC1120_NUM_TXBYTES, .name = "NUM_TXBYTES" },
+ { .addr = CC1120_NUM_RXBYTES, .name = "NUM_RXBYTES" },
+ { .addr = CC1120_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
+ { .addr = CC1120_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
+};
+
+#define AO_NUM_CC1120_REG (sizeof ao_cc1120_reg / sizeof ao_cc1120_reg[0])
+
+static void ao_radio_show(void) {
+ uint8_t status = ao_radio_status();
+ int i;
+
+ ao_radio_get(0xff);
+ status = ao_radio_status();
+ printf ("Status: %02x\n", status);
+ printf ("CHIP_RDY: %d\n", (status >> CC1120_STATUS_CHIP_RDY) & 1);
+ printf ("STATE: %s\n", cc1120_state_name[(status >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK]);
+
+ for (i = 0; i < AO_NUM_CC1120_REG; i++)
+ printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name);
+ ao_radio_put();
+}
+#endif
+
+static const struct ao_cmds ao_radio_cmds[] = {
+ { ao_radio_test, "C <1 start, 0 stop, none both>\0Radio carrier test" },
+#if CC1120_DEBUG
+ { ao_radio_show, "R\0Show CC1120 status" },
+#endif
+ { 0, NULL }
+};
+
+void
+ao_radio_init(void)
+{
+ ao_radio_configured = 0;
+ ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN));
+
+ ao_cmd_register(&ao_radio_cmds[0]);
}
--- /dev/null
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_CC1120_H_
+#define _AO_CC1120_H_
+
+#define CC1120_READ (7)
+#define CC1120_BURST (6)
+
+/* Register space */
+#define CC1120_IOCFG3 0x00
+#define CC1120_IOCFG_GPIO_ATRAN 7
+#define CC1120_IOCFG_GPIO_INV 6
+#define CC1120_IOCFG_GPIO_CFG 0
+#define CC1120_IOCFG_GPIO_CFG_RXFIFO_THR 0
+#define CC1120_IOCFG_GPIO_CFG_RXFIFO_THR_PKT 1
+#define CC1120_IOCFG_GPIO_CFG_TXFIFO_THR 2
+#define CC1120_IOCFG_GPIO_CFG_TXFIFO_THR_PKT 3
+#define CC1120_IOCFG_GPIO_CFG_RXFIFO_OVERFLOW 4
+#define CC1120_IOCFG_GPIO_CFG_TXFIFO_UNDERFLOW 5
+#define CC1120_IOCFG_GPIO_CFG_PKT_SYNC_RXTX 6
+#define CC1120_IOCFG_GPIO_CFG_CRC_OK 7
+#define CC1120_IOCFG_GPIO_CFG_SERIAL_CLK 8
+#define CC1120_IOCFG_GPIO_CFG_SERIAL_RX 9
+#define CC1120_IOCFG_GPIO_CFG_PQT_REACHED 11
+#define CC1120_IOCFG_GPIO_CFG_PQT_VALID 12
+#define CC1120_IOCFG_GPIO_CFG_RSSI_VALID 13
+#define CC1120_IOCFG_GPIO3_CFG_RSSI_UPDATE 14
+#define CC1120_IOCFG_GPIO2_CFG_RSSI_UPDATE 14
+#define CC1120_IOCFG_GPIO1_CFG_AGC_HOLD 14
+#define CC1120_IOCFG_GPIO0_CFG_AGC_UPDATE 14
+#define CC1120_IOCFG_GPIO3_CFG_CGA_STATUS 15
+#define CC1120_IOCFG_GPIO2_CFG_TXONCCA_DONE 15
+#define CC1120_IOCFG_GPIO1_CFG_CCA_STATUS 15
+#define CC1120_IOCFG_GPIO0_CFG_TXONCCA_FAILED 15
+#define CC1120_IOCFG_GPIO_CFG_CARRIER_SENSE_VALID 16
+#define CC1120_IOCFG_GPIO_CFG_CARRIER_SENSE 17
+#define CC1120_IOCFG_GPIO3_CFG_DSSS_CLK 18
+#define CC1120_IOCFG_GPIO2_CFG_DSSS_DATA0 18
+#define CC1120_IOCFG_GPIO1_CFG_DSSS_CLK 18
+#define CC1120_IOCFG_GPIO0_CFG_DSSS_DATA1 18
+#define CC1120_IOCFG_GPIO_CFG_PKT_CRC_OK 19
+#define CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP 20
+#define CC1120_IOCFG_GPIO_CFG_SYNC_LOW0_HIGH1 21
+#define CC1120_IOCFG_GPIO_CFG_LNA_PA_REG_PD 23
+#define CC1120_IOCFG_GPIO_CFG_LNA_PD 24
+#define CC1120_IOCFG_GPIO_CFG_PA_RD 25
+#define CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG 26
+#define CC1120_IOCFG_GPIO_CFG_IMAGE_FOUND 28
+#define CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT 29
+#define CC1120_IOCFG_GPIO_CFG_SOFT_TX_DATA_CLK 30
+#define CC1120_IOCFG_GPIO_CFG_RSSI_STEP_FOUND 33
+#define CC1120_IOCFG_GPIO_CFG_RSSI_STEP_EVENT 34
+#define CC1120_IOCFG_GPIO_CFG_ANTENNA_SELECT 36
+#define CC1120_IOCFG_GPIO_CFG_MARC_2PIN_STATUS1 37
+#define CC1120_IOCFG_GPIO_CFG_MARC_2PIN_STATUS0 38
+#define CC1120_IOCFG_GPIO2_CFG_TXFIFO_OVERFLOW 39
+#define CC1120_IOCFG_GPIO0_CFG_RXFIFO_UNDERFLOW 39
+#define CC1120_IOCFG_GPIO3_CFG_MAGN_VALID 40
+#define CC1120_IOCFG_GPIO2_CFG_CHFILT_VALID 40
+#define CC1120_IOCFG_GPIO1_CFG_RCC_CAL_VALID 40
+#define CC1120_IOCFG_GPIO0_CFG_CHFILTER_STARTUP_VALID 40
+#define CC1120_IOCFG_GPIO3_CFG_COLLISION_FOUND 41
+#define CC1120_IOCFG_GPIO2_CFG_SYNC_EVENT 41
+#define CC1120_IOCFG_GPIO1_CFG_COLLISION_FOUND 41
+#define CC1120_IOCFG_GPIO0_CFG_COLLISION_EVENT 41
+#define CC1120_IOCFG_GPIO_CFG_PA_RAMP_UP 42
+#define CC1120_IOCFG_GPIO3_CFG_CRC_FAILED 43
+#define CC1120_IOCFG_GPIO2_CFG_LENGTH_FAILED 43
+#define CC1120_IOCFG_GPIO1_CFG_ADDR_FAILED 43
+#define CC1120_IOCFG_GPIO0_CFG_UART_FRAMING_ERROR 43
+#define CC1120_IOCFG_GPIO_CFG_AGC_STABLE_GAIN 44
+#define CC1120_IOCFG_GPIO_CFG_AGC_UPDATE 45
+#define CC1120_IOCFG_GPIO3_CFG_ADC_CLOCK 46
+#define CC1120_IOCFG_GPIO2_CFG_ADC_Q_DATA_SAMPLE 46
+#define CC1120_IOCFG_GPIO1_CFG_ADC_CLOCK 46
+#define CC1120_IOCFG_GPIO0_CFG_ADC_I_DATA_SAMPLE 46
+#define CC1120_IOCFG_GPIO_CFG_HIGHZ 48
+#define CC1120_IOCFG_GPIO_CFG_EXT_CLOCK 49
+#define CC1120_IOCFG_GPIO_CFG_CHIP_RDY 50
+#define CC1120_IOCFG_GPIO_CFG_HW0 51
+#define CC1120_IOCFG_GPIO_CFG_CLOCK_32K 54
+#define CC1120_IOCFG_GPIO_CFG_WOR_EVENT0 55
+#define CC1120_IOCFG_GPIO_CFG_WOR_EVENT1 56
+#define CC1120_IOCFG_GPIO_CFG_WOR_EVENT2 57
+#define CC1120_IOCFG_GPIO_CFG_XOSC_STABLE 59
+#define CC1120_IOCFG_GPIO_CFG_EXT_OSC_EN 60
+#define CC1120_IOCFG_GPIO_CFG_MASK 0x3f
+
+#define CC1120_IOCFG3 0x00
+#define CC1120_IOCFG2 0x01
+#define CC1120_IOCFG1 0x02
+#define CC1120_IOCFG0 0x03
+#define CC1120_SYNC3 0x04
+#define CC1120_SYNC2 0x05
+#define CC1120_SYNC1 0x06
+#define CC1120_SYNC0 0x07
+#define CC1120_SYNC_CFG1 0x08
+#define CC1120_SYNC_CFG0 0x09
+#define CC1120_DEVIATION_M 0x0a
+#define CC1120_MODCFG_DEV_E 0x0b
+#define CC1120_DCFILT_CFG 0x0c
+#define CC1120_PREAMBLE_CFG1 0x0d
+#define CC1120_PREAMBLE_CFG0 0x0e
+#define CC1120_FREQ_IF_CFG 0x0f
+#define CC1120_IQIC 0x10
+#define CC1120_CHAN_BW 0x11
+#define CC1120_MDMCFG1 0x12
+#define CC1120_MDMCFG0 0x13
+#define CC1120_DRATE2 0x14
+#define CC1120_DRATE1 0x15
+#define CC1120_DRATE0 0x16
+#define CC1120_AGC_REF 0x17
+#define CC1120_AGC_CS_THR 0x18
+#define CC1120_AGC_GAIN_ADJUST 0x19
+#define CC1120_AGC_CFG3 0x1a
+#define CC1120_AGC_CFG2 0x1b
+#define CC1120_AGC_CFG1 0x1c
+#define CC1120_AGC_CFG0 0x1d
+#define CC1120_FIFO_CFG 0x1e
+#define CC1120_DEV_ADDR 0x1f
+#define CC1120_SETTLING_CFG 0x20
+#define CC1120_FS_CFG 0x21
+#define CC1120_WOR_CFG1 0x22
+#define CC1120_WOR_CFG0 0x23
+#define CC1120_WOR_EVENT0_MSB 0x24
+#define CC1120_WOR_EVENT0_LSB 0x25
+#define CC1120_PKT_CFG2 0x26
+#define CC1120_PKT_CFG1 0x27
+#define CC1120_PKT_CFG0 0x28
+#define CC1120_RFEND_CFG1 0x29
+#define CC1120_RFEND_CFG0 0x2a
+#define CC1120_PA_CFG2 0x2b
+#define CC1120_PA_CFG1 0x2c
+#define CC1120_PA_CFG0 0x2d
+#define CC1120_PKT_LEN 0x2e
+
+#define CC1120_EXTENDED 0x2f
+
+/* Command strobes */
+#define CC1120_SRES 0x30
+#define CC1120_SFSTXON 0x31
+#define CC1120_SXOFF 0x32
+#define CC1120_SCAL 0x33
+#define CC1120_SRX 0x34
+#define CC1120_STX 0x35
+#define CC1120_SIDLE 0x36
+#define CC1120_SAFC 0x37
+#define CC1120_SWOR 0x38
+#define CC1120_SPWD 0x39
+#define CC1120_SFRX 0x3a
+#define CC1120_SFTX 0x3b
+#define CC1120_SWORRST 0x3c
+#define CC1120_SNOP 0x3d
+
+#define CC1120_DIRECT_FIFO 0x3e
+#define CC1120_FIFO 0x3f
+
+/* Extended register space */
+
+#define CC1120_EXTENDED_BIT 0x8000
+
+#define CC1120_IS_EXTENDED(r) ((r) & CC1120_EXTENDED_BIT)
+
+#define CC1120_IF_MIX_CFG (CC1120_EXTENDED_BIT | 0x00)
+#define CC1120_FREQOFF_CFG (CC1120_EXTENDED_BIT | 0x01)
+#define CC1120_TOC_CFG (CC1120_EXTENDED_BIT | 0x02)
+#define CC1120_MARC_SPARE (CC1120_EXTENDED_BIT | 0x03)
+#define CC1120_ECG_CFG (CC1120_EXTENDED_BIT | 0x04)
+#define CC1120_SOFT_TX_DATA_CFG (CC1120_EXTENDED_BIT | 0x05)
+#define CC1120_EXT_CTRL (CC1120_EXTENDED_BIT | 0x06)
+#define CC1120_RCCAL_FINE (CC1120_EXTENDED_BIT | 0x07)
+#define CC1120_RCCAL_COARSE (CC1120_EXTENDED_BIT | 0x08)
+#define CC1120_RCCAL_OFFSET (CC1120_EXTENDED_BIT | 0x09)
+#define CC1120_FREQOFF1 (CC1120_EXTENDED_BIT | 0x0A)
+#define CC1120_FREQOFF0 (CC1120_EXTENDED_BIT | 0x0B)
+#define CC1120_FREQ2 (CC1120_EXTENDED_BIT | 0x0C)
+#define CC1120_FREQ1 (CC1120_EXTENDED_BIT | 0x0D)
+#define CC1120_FREQ0 (CC1120_EXTENDED_BIT | 0x0E)
+#define CC1120_IF_ADC2 (CC1120_EXTENDED_BIT | 0x0F)
+#define CC1120_IF_ADC1 (CC1120_EXTENDED_BIT | 0x10)
+#define CC1120_IF_ADC0 (CC1120_EXTENDED_BIT | 0x11)
+#define CC1120_FS_DIG1 (CC1120_EXTENDED_BIT | 0x12)
+#define CC1120_FS_DIG0 (CC1120_EXTENDED_BIT | 0x13)
+#define CC1120_FS_CAL3 (CC1120_EXTENDED_BIT | 0x14)
+#define CC1120_FS_CAL2 (CC1120_EXTENDED_BIT | 0x15)
+#define CC1120_FS_CAL1 (CC1120_EXTENDED_BIT | 0x16)
+#define CC1120_FS_CAL0 (CC1120_EXTENDED_BIT | 0x17)
+#define CC1120_FS_CHP (CC1120_EXTENDED_BIT | 0x18)
+#define CC1120_FS_DIVTWO (CC1120_EXTENDED_BIT | 0x19)
+#define CC1120_FS_DSM1 (CC1120_EXTENDED_BIT | 0x1A)
+#define CC1120_FS_DSM0 (CC1120_EXTENDED_BIT | 0x1B)
+#define CC1120_FS_DVC1 (CC1120_EXTENDED_BIT | 0x1C)
+#define CC1120_FS_DVC0 (CC1120_EXTENDED_BIT | 0x1D)
+#define CC1120_FS_LBI (CC1120_EXTENDED_BIT | 0x1E)
+#define CC1120_FS_PFD (CC1120_EXTENDED_BIT | 0x1F)
+#define CC1120_FS_PRE (CC1120_EXTENDED_BIT | 0x20)
+#define CC1120_FS_REG_DIV_CML (CC1120_EXTENDED_BIT | 0x21)
+#define CC1120_FS_SPARE (CC1120_EXTENDED_BIT | 0x22)
+#define CC1120_FS_VCO4 (CC1120_EXTENDED_BIT | 0x23)
+#define CC1120_FS_VCO3 (CC1120_EXTENDED_BIT | 0x24)
+#define CC1120_FS_VCO2 (CC1120_EXTENDED_BIT | 0x25)
+#define CC1120_FS_VCO1 (CC1120_EXTENDED_BIT | 0x26)
+#define CC1120_FS_VCO0 (CC1120_EXTENDED_BIT | 0x27)
+#define CC1120_GBIAS6 (CC1120_EXTENDED_BIT | 0x28)
+#define CC1120_GBIAS5 (CC1120_EXTENDED_BIT | 0x29)
+#define CC1120_GBIAS4 (CC1120_EXTENDED_BIT | 0x2A)
+#define CC1120_GBIAS3 (CC1120_EXTENDED_BIT | 0x2B)
+#define CC1120_GBIAS2 (CC1120_EXTENDED_BIT | 0x2C)
+#define CC1120_GBIAS1 (CC1120_EXTENDED_BIT | 0x2D)
+#define CC1120_GBIAS0 (CC1120_EXTENDED_BIT | 0x2E)
+#define CC1120_IFAMP (CC1120_EXTENDED_BIT | 0x2F)
+#define CC1120_LNA (CC1120_EXTENDED_BIT | 0x30)
+#define CC1120_RXMIX (CC1120_EXTENDED_BIT | 0x31)
+#define CC1120_XOSC5 (CC1120_EXTENDED_BIT | 0x32)
+#define CC1120_XOSC4 (CC1120_EXTENDED_BIT | 0x33)
+#define CC1120_XOSC3 (CC1120_EXTENDED_BIT | 0x34)
+#define CC1120_XOSC2 (CC1120_EXTENDED_BIT | 0x35)
+#define CC1120_XOSC1 (CC1120_EXTENDED_BIT | 0x36)
+#define CC1120_XOSC0 (CC1120_EXTENDED_BIT | 0x37)
+#define CC1120_ANALOG_SPARE (CC1120_EXTENDED_BIT | 0x38)
+#define CC1120_PA_CFG3 (CC1120_EXTENDED_BIT | 0x39)
+#define CC1120_WOR_TIME1 (CC1120_EXTENDED_BIT | 0x64)
+#define CC1120_WOR_TIME0 (CC1120_EXTENDED_BIT | 0x65)
+#define CC1120_WOR_CAPTURE1 (CC1120_EXTENDED_BIT | 0x66)
+#define CC1120_WOR_CAPTURE0 (CC1120_EXTENDED_BIT | 0x67)
+#define CC1120_BIST (CC1120_EXTENDED_BIT | 0x68)
+#define CC1120_DCFILTOFFSET_I1 (CC1120_EXTENDED_BIT | 0x69)
+#define CC1120_DCFILTOFFSET_I0 (CC1120_EXTENDED_BIT | 0x6A)
+#define CC1120_DCFILTOFFSET_Q1 (CC1120_EXTENDED_BIT | 0x6B)
+#define CC1120_DCFILTOFFSET_Q0 (CC1120_EXTENDED_BIT | 0x6C)
+#define CC1120_IQIE_I1 (CC1120_EXTENDED_BIT | 0x6D)
+#define CC1120_IQIE_I0 (CC1120_EXTENDED_BIT | 0x6E)
+#define CC1120_IQIE_Q1 (CC1120_EXTENDED_BIT | 0x6f)
+#define CC1120_IQIE_Q0 (CC1120_EXTENDED_BIT | 0x70)
+#define CC1120_RSSI1 (CC1120_EXTENDED_BIT | 0x71)
+#define CC1120_RSSI0 (CC1120_EXTENDED_BIT | 0x72)
+#define CC1120_MARCSTATE (CC1120_EXTENDED_BIT | 0x73)
+#define CC1120_LQI_VAL (CC1120_EXTENDED_BIT | 0x74)
+#define CC1120_PQT_SYNC_ERR (CC1120_EXTENDED_BIT | 0x75)
+#define CC1120_DEM_STATUS (CC1120_EXTENDED_BIT | 0x76)
+#define CC1120_FREQOFF_EST1 (CC1120_EXTENDED_BIT | 0x77)
+#define CC1120_FREQOFF_EST0 (CC1120_EXTENDED_BIT | 0x78)
+#define CC1120_AGC_GAIN3 (CC1120_EXTENDED_BIT | 0x79)
+#define CC1120_AGC_GAIN2 (CC1120_EXTENDED_BIT | 0x7a)
+#define CC1120_AGC_GAIN1 (CC1120_EXTENDED_BIT | 0x7b)
+#define CC1120_AGC_GAIN0 (CC1120_EXTENDED_BIT | 0x7c)
+#define CC1120_SOFT_RX_DATA_OUT (CC1120_EXTENDED_BIT | 0x7d)
+#define CC1120_SOFT_TX_DATA_IN (CC1120_EXTENDED_BIT | 0x7e)
+#define CC1120_ASK_SOFT_RX_DATA (CC1120_EXTENDED_BIT | 0x7f)
+#define CC1120_RNDGEN (CC1120_EXTENDED_BIT | 0x80)
+#define CC1120_MAGN2 (CC1120_EXTENDED_BIT | 0x81)
+#define CC1120_MAGN1 (CC1120_EXTENDED_BIT | 0x82)
+#define CC1120_MAGN0 (CC1120_EXTENDED_BIT | 0x83)
+#define CC1120_ANG1 (CC1120_EXTENDED_BIT | 0x84)
+#define CC1120_ANG0 (CC1120_EXTENDED_BIT | 0x85)
+#define CC1120_CHFILT_I2 (CC1120_EXTENDED_BIT | 0x86)
+#define CC1120_CHFILT_I1 (CC1120_EXTENDED_BIT | 0x87)
+#define CC1120_CHFILT_I0 (CC1120_EXTENDED_BIT | 0x88)
+#define CC1120_CHFILT_Q2 (CC1120_EXTENDED_BIT | 0x89)
+#define CC1120_CHFILT_Q1 (CC1120_EXTENDED_BIT | 0x8a)
+#define CC1120_CHFILT_Q0 (CC1120_EXTENDED_BIT | 0x8b)
+#define CC1120_GPIO_STATUS (CC1120_EXTENDED_BIT | 0x8c)
+#define CC1120_FSCAL_CTRL (CC1120_EXTENDED_BIT | 0x8d)
+#define CC1120_PHASE_ADJUST (CC1120_EXTENDED_BIT | 0x8e)
+#define CC1120_PARTNUMBER (CC1120_EXTENDED_BIT | 0x8f)
+#define CC1120_PARTVERSION (CC1120_EXTENDED_BIT | 0x90)
+#define CC1120_SERIAL_STATUS (CC1120_EXTENDED_BIT | 0x91)
+#define CC1120_RX_STATUS (CC1120_EXTENDED_BIT | 0x92)
+#define CC1120_TX_STATUS (CC1120_EXTENDED_BIT | 0x93)
+#define CC1120_MARC_STATUS1 (CC1120_EXTENDED_BIT | 0x94)
+#define CC1120_MARC_STATUS0 (CC1120_EXTENDED_BIT | 0x95)
+#define CC1120_PA_IFAMP_TEST (CC1120_EXTENDED_BIT | 0x96)
+#define CC1120_FSRF_TEST (CC1120_EXTENDED_BIT | 0x97)
+#define CC1120_PRE_TEST (CC1120_EXTENDED_BIT | 0x98)
+#define CC1120_PRE_OVR (CC1120_EXTENDED_BIT | 0x99)
+#define CC1120_ADC_TEST (CC1120_EXTENDED_BIT | 0x9a)
+#define CC1120_DVC_TEST (CC1120_EXTENDED_BIT | 0x9b)
+#define CC1120_ATEST (CC1120_EXTENDED_BIT | 0x9c)
+#define CC1120_ATEST_LVDS (CC1120_EXTENDED_BIT | 0x9d)
+#define CC1120_ATEST_MODE (CC1120_EXTENDED_BIT | 0x9e)
+#define CC1120_XOSC_TEST1 (CC1120_EXTENDED_BIT | 0x9f)
+#define CC1120_XOSC_TEST0 (CC1120_EXTENDED_BIT | 0xa0)
+#define CC1120_RXFIRST (CC1120_EXTENDED_BIT | 0xd2)
+#define CC1120_TXFIRST (CC1120_EXTENDED_BIT | 0xd3)
+#define CC1120_RXLAST (CC1120_EXTENDED_BIT | 0xd4)
+#define CC1120_TXLAST (CC1120_EXTENDED_BIT | 0xd5)
+#define CC1120_NUM_TXBYTES (CC1120_EXTENDED_BIT | 0xd6)
+#define CC1120_NUM_RXBYTES (CC1120_EXTENDED_BIT | 0xd7)
+#define CC1120_FIFO_NUM_TXBYTES (CC1120_EXTENDED_BIT | 0xd8)
+#define CC1120_FIFO_NUM_RXBYTES (CC1120_EXTENDED_BIT | 0xd9)
+
+/* Status byte */
+#define CC1120_STATUS_CHIP_RDY 7
+#define CC1120_STATUS_STATE 4
+#define CC1120_STATUS_STATE_IDLE 0
+#define CC1120_STATUS_STATE_RX 1
+#define CC1120_STATUS_STATE_TX 2
+#define CC1120_STATUS_STATE_FSTXON 3
+#define CC1120_STATUS_STATE_CALIBRATE 4
+#define CC1120_STATUS_STATE_SETTLING 5
+#define CC1120_STATUS_STATE_RX_FIFO_ERROR 6
+#define CC1120_STATUS_STATE_TX_FIFO_ERROR 7
+#define CC1120_STATUS_STATE_MASK 7
+
+#endif /* _AO_CC1120_H_ */
--- /dev/null
+/* RX filter BW = 100.000000 */\r
+/* Address config = No address check */\r
+/* Packet length = 255 */\r
+/* Symbol rate = 38.3606 */\r
+/* PA ramping = false */\r
+/* Carrier frequency = 434.549988 */\r
+/* Bit rate = 38.3606 */\r
+/* Whitening = true */\r
+/* Manchester enable = false */\r
+/* Modulation format = 2-GFSK */\r
+/* Packet length mode = Variable */\r
+/* Device address = 0 */\r
+/* TX power = 15 */\r
+/* Deviation = 20.507812 */\r
+/***************************************************************\r
+ * SmartRF Studio(tm) Export\r
+ *\r
+ * Radio register settings specifed with address, value\r
+ *\r
+ * RF device: CC1120\r
+ *\r
+ ***************************************************************/\r
+\r
+\r
+ CC1120_SYNC3, 0x93, /* Sync Word Configuration [31:24] */\r
+ CC1120_SYNC2, 0x0b, /* Sync Word Configuration [23:16] */\r
+ CC1120_SYNC1, 0x51, /* Sync Word Configuration [15:8] */\r
+ CC1120_SYNC0, 0xde, /* Sync Word Configuration [7:0] */\r
+ CC1120_SYNC_CFG1, 0x08, /* Sync Word Detection Configuration */\r
+ CC1120_SYNC_CFG0, 0x17, /* Sync Word Length Configuration */\r
+ CC1120_DEVIATION_M, 0x50, /* Frequency Deviation Configuration */\r
+ CC1120_MODCFG_DEV_E, 0x0d, /* Modulation Format and Frequency Deviation Configuration */\r
+ CC1120_DCFILT_CFG, 0x1c, /* Digital DC Removal Configuration */\r
+ CC1120_PREAMBLE_CFG1, 0x18, /* Preamble Length Configuration */\r
+ CC1120_PREAMBLE_CFG0, 0x2a, /* */\r
+ CC1120_FREQ_IF_CFG, 0x40, /* RX Mixer Frequency Configuration */\r
+ CC1120_IQIC, 0x46, /* Digital Image Channel Compensation Configuration */\r
+ CC1120_CHAN_BW, 0x02, /* Channel Filter Configuration */\r
+ CC1120_MDMCFG1, 0x46, /* General Modem Parameter Configuration */\r
+ CC1120_MDMCFG0, 0x05, /* General Modem Parameter Configuration */\r
+ CC1120_DRATE2, 0x93, /* Data Rate Configuration Exponent and Mantissa [19:16] */\r
+ CC1120_DRATE1, 0xa4, /* Data Rate Configuration Mantissa [15:8] */\r
+ CC1120_DRATE0, 0x00, /* Data Rate Configuration Mantissa [7:0] */\r
+ CC1120_AGC_REF, 0x20, /* AGC Reference Level Configuration */\r
+ CC1120_AGC_CS_THR, 0x19, /* Carrier Sense Threshold Configuration */\r
+ CC1120_AGC_GAIN_ADJUST, 0x00, /* RSSI Offset Configuration */\r
+ CC1120_AGC_CFG3, 0x91, /* AGC Configuration */\r
+ CC1120_AGC_CFG2, 0x20, /* AGC Configuration */\r
+ CC1120_AGC_CFG1, 0xa9, /* AGC Configuration */\r
+ CC1120_AGC_CFG0, 0xcf, /* AGC Configuration */\r
+ CC1120_FIFO_CFG, 0x00, /* FIFO Configuration */\r
+ CC1120_DEV_ADDR, 0x00, /* Device Address Configuration */\r
+ CC1120_SETTLING_CFG, 0x03, /* Frequency Synthesizer Calibration and Settling Configuration */\r
+ CC1120_FS_CFG, 0x14, /* Frequency Synthesizer Configuration */\r
+ CC1120_WOR_CFG1, 0x08, /* eWOR Configuration, Reg 1 */\r
+ CC1120_WOR_CFG0, 0x21, /* eWOR Configuration, Reg 0 */\r
+ CC1120_WOR_EVENT0_MSB, 0x00, /* Event 0 Configuration */\r
+ CC1120_WOR_EVENT0_LSB, 0x00, /* Event 0 Configuration */\r
+ CC1120_PKT_CFG2, 0x04, /* Packet Configuration, Reg 2 */\r
+ CC1120_PKT_CFG1, 0x45, /* Packet Configuration, Reg 1 */\r
+ CC1120_PKT_CFG0, 0x20, /* Packet Configuration, Reg 0 */\r
+ CC1120_RFEND_CFG1, 0x0f, /* RFEND Configuration, Reg 1 */\r
+ CC1120_RFEND_CFG0, 0x00, /* RFEND Configuration, Reg 0 */\r
+ CC1120_PA_CFG2, 0x3f, /* Power Amplifier Configuration, Reg 2 */\r
+ CC1120_PA_CFG1, 0x56, /* Power Amplifier Configuration, Reg 1 */\r
+ CC1120_PA_CFG0, 0x7b, /* Power Amplifier Configuration, Reg 0 */\r
+ CC1120_PKT_LEN, 0xff, /* Packet Length Configuration */\r
+ CC1120_IF_MIX_CFG, 0x00, /* IF Mix Configuration */\r
+ CC1120_FREQOFF_CFG, 0x22, /* Frequency Offset Correction Configuration */\r
+ CC1120_TOC_CFG, 0x0b, /* Timing Offset Correction Configuration */\r
+ CC1120_MARC_SPARE, 0x00, /* MARC Spare */\r
+ CC1120_ECG_CFG, 0x00, /* External Clock Frequency Configuration */\r
+ CC1120_SOFT_TX_DATA_CFG, 0x00, /* Soft TX Data Configuration */\r
+ CC1120_EXT_CTRL, 0x01, /* External Control Configuration */\r
+ CC1120_RCCAL_FINE, 0x00, /* RC Oscillator Calibration (fine) */\r
+ CC1120_RCCAL_COARSE, 0x00, /* RC Oscillator Calibration (coarse) */\r
+ CC1120_RCCAL_OFFSET, 0x00, /* RC Oscillator Calibration Clock Offset */\r
+ CC1120_FREQOFF1, 0x00, /* Frequency Offset (MSB) */\r
+ CC1120_FREQOFF0, 0x00, /* Frequency Offset (LSB) */\r
+ CC1120_FREQ2, 0x6c, /* Frequency Configuration [23:16] */\r
+ CC1120_FREQ1, 0xa3, /* Frequency Configuration [15:8] */\r
+ CC1120_FREQ0, 0x33, /* Frequency Configuration [7:0] */\r
+ CC1120_IF_ADC2, 0x02, /* Analog to Digital Converter Configuration, Reg 2 */\r
+ CC1120_IF_ADC1, 0xa6, /* Analog to Digital Converter Configuration, Reg 1 */\r
+ CC1120_IF_ADC0, 0x04, /* Analog to Digital Converter Configuration, Reg 0 */\r
+ CC1120_FS_DIG1, 0x00, /* */\r
+ CC1120_FS_DIG0, 0x5f, /* */\r
+ CC1120_FS_CAL3, 0x00, /* */\r
+ CC1120_FS_CAL2, 0x20, /* */\r
+ CC1120_FS_CAL1, 0x40, /* */\r
+ CC1120_FS_CAL0, 0x0e, /* */\r
+ CC1120_FS_CHP, 0x28, /* Charge Pump Configuration */\r
+ CC1120_FS_DIVTWO, 0x03, /* Divide by 2 */\r
+ CC1120_FS_DSM1, 0x00, /* Digital Synthesizer Module Configuration, Reg 1 */\r
+ CC1120_FS_DSM0, 0x33, /* Digital Synthesizer Module Configuration, Reg 0 */\r
+ CC1120_FS_DVC1, 0xff, /* Divider Chain Configuration, Reg 1 */\r
+ CC1120_FS_DVC0, 0x17, /* Divider Chain Configuration, Reg 0 */\r
+ CC1120_FS_LBI, 0x00, /* Local Bias Configuration */\r
+ CC1120_FS_PFD, 0x50, /* Phase Frequency Detector Configuration */\r
+ CC1120_FS_PRE, 0x6e, /* Prescaler Configuration */\r
+ CC1120_FS_REG_DIV_CML, 0x14, /* */\r
+ CC1120_FS_SPARE, 0xac, /* */\r
+ CC1120_FS_VCO4, 0x14, /* VCO Configuration, Reg 4 */\r
+ CC1120_FS_VCO3, 0x00, /* VCO Configuration, Reg 3 */\r
+ CC1120_FS_VCO2, 0x00, /* VCO Configuration, Reg 2 */\r
+ CC1120_FS_VCO1, 0x00, /* VCO Configuration, Reg 1 */\r
+ CC1120_FS_VCO0, 0xb4, /* VCO Configuration, Reg 0 */\r
+ CC1120_GBIAS6, 0x00, /* Global Bias Configuration, Reg 6 */\r
+ CC1120_GBIAS5, 0x02, /* Global Bias Configuration, Reg 5 */\r
+ CC1120_GBIAS4, 0x00, /* Global Bias Configuration, Reg 4 */\r
+ CC1120_GBIAS3, 0x00, /* Global Bias Configuration, Reg 3 */\r
+ CC1120_GBIAS2, 0x10, /* Global Bias Configuration, Reg 2 */\r
+ CC1120_GBIAS1, 0x00, /* Global Bias Configuration, Reg 1 */\r
+ CC1120_GBIAS0, 0x00, /* Global Bias Configuration, Reg 0 */\r
+ CC1120_IFAMP, 0x01, /* Intermediate Frequency Amplifier Configuration */\r
+ CC1120_LNA, 0x01, /* Low Noise Amplifier Configuration */\r
+ CC1120_RXMIX, 0x01, /* RX Mixer Configuration */\r
+ CC1120_XOSC5, 0x0e, /* Crystal Oscillator Configuration, Reg 5 */\r
+ CC1120_XOSC4, 0xa0, /* Crystal Oscillator Configuration, Reg 4 */\r
+ CC1120_XOSC3, 0x03, /* Crystal Oscillator Configuration, Reg 3 */\r
+ CC1120_XOSC2, 0x04, /* Crystal Oscillator Configuration, Reg 2 */\r
+ CC1120_XOSC1, 0x01, /* Crystal Oscillator Configuration, Reg 1 */\r
+ CC1120_XOSC0, 0x00, /* Crystal Oscillator Configuration, Reg 0 */\r
+ CC1120_ANALOG_SPARE, 0x00, /* */\r
+ CC1120_PA_CFG3, 0x00, /* Power Amplifier Configuration, Reg 3 */\r
+ CC1120_WOR_TIME1, 0x00, /* eWOR Timer Status (MSB) */\r
+ CC1120_WOR_TIME0, 0x00, /* eWOR Timer Status (LSB) */\r
+ CC1120_WOR_CAPTURE1, 0x00, /* eWOR Timer Capture (MSB) */\r
+ CC1120_WOR_CAPTURE0, 0x00, /* eWOR Timer Capture (LSB) */\r
+ CC1120_BIST, 0x00, /* MARC BIST */\r
+ CC1120_DCFILTOFFSET_I1, 0x00, /* DC Filter Offset I (MSB) */\r
+ CC1120_DCFILTOFFSET_I0, 0x00, /* DC Filter Offset I (LSB) */\r
+ CC1120_DCFILTOFFSET_Q1, 0x00, /* DC Filter Offset Q (MSB) */\r
+ CC1120_DCFILTOFFSET_Q0, 0x00, /* DC Filter Offset Q (LSB) */\r
+ CC1120_IQIE_I1, 0x00, /* IQ Imbalance Value I (MSB) */\r
+ CC1120_IQIE_I0, 0x00, /* IQ Imbalance Value I (LSB) */\r
+ CC1120_IQIE_Q1, 0x00, /* IQ Imbalance Value Q (MSB) */\r
+ CC1120_IQIE_Q0, 0x00, /* IQ Imbalance Value Q (LSB) */\r
+ CC1120_RSSI1, 0x80, /* Received Signal Strength Indicator (MSB) */\r
+ CC1120_RSSI0, 0x00, /* Received Signal Strength Indicator (LSB) */\r
+ CC1120_MARCSTATE, 0x41, /* MARC State */\r
+ CC1120_LQI_VAL, 0x00, /* Link Quality Indicator Value */\r
+ CC1120_PQT_SYNC_ERR, 0xff, /* Preamble and Sync Word Error */\r
+ CC1120_DEM_STATUS, 0x00, /* Demodulator Status */\r
+ CC1120_FREQOFF_EST1, 0x00, /* Frequency Offset Estimate (MSB) */\r
+ CC1120_FREQOFF_EST0, 0x00, /* Frequency Offset Estimate (LSB) */\r
+ CC1120_AGC_GAIN3, 0x00, /* AGC Gain, Reg 3 */\r
+ CC1120_AGC_GAIN2, 0xd1, /* AGC Gain, Reg 2 */\r
+ CC1120_AGC_GAIN1, 0x00, /* AGC Gain, Reg 1 */\r
+ CC1120_AGC_GAIN0, 0x3f, /* AGC Gain, Reg 0 */\r
+ CC1120_SOFT_RX_DATA_OUT, 0x00, /* Soft Decision Symbol Data */\r
+ CC1120_SOFT_TX_DATA_IN, 0x00, /* Soft TX Data Input Register */\r
+ CC1120_ASK_SOFT_RX_DATA, 0x30, /* AGC ASK Soft Decision Output */\r
+ CC1120_RNDGEN, 0x7f, /* Random Number Value */\r
+ CC1120_MAGN2, 0x00, /* Signal Magnitude after CORDIC [16] */\r
+ CC1120_MAGN1, 0x00, /* Signal Magnitude after CORDIC [15:8] */\r
+ CC1120_MAGN0, 0x00, /* Signal Magnitude after CORDIC [7:0] */\r
+ CC1120_ANG1, 0x00, /* Signal Angular after CORDIC [9:8] */\r
+ CC1120_ANG0, 0x00, /* Signal Angular after CORDIC [7:0] */\r
+ CC1120_CHFILT_I2, 0x08, /* Channel Filter Data Real Part [18:16] */\r
+ CC1120_CHFILT_I1, 0x00, /* Channel Filter Data Real Part [15:8] */\r
+ CC1120_CHFILT_I0, 0x00, /* Channel Filter Data Real Part [7:0] */\r
+ CC1120_CHFILT_Q2, 0x00, /* Channel Filter Data Imaginary Part [18:16] */\r
+ CC1120_CHFILT_Q1, 0x00, /* Channel Filter Data Imaginary Part [15:8] */\r
+ CC1120_CHFILT_Q0, 0x00, /* Channel Filter Data Imaginary Part [7:0] */\r
+ CC1120_GPIO_STATUS, 0x00, /* GPIO Status */\r
+ CC1120_FSCAL_CTRL, 0x01, /* */\r
+ CC1120_PHASE_ADJUST, 0x00, /* */\r
+ CC1120_PARTNUMBER, 0x00, /* Part Number */\r
+ CC1120_PARTVERSION, 0x00, /* Part Revision */\r
+ CC1120_SERIAL_STATUS, 0x00, /* Serial Status */\r
+ CC1120_RX_STATUS, 0x01, /* RX Status */\r
+ CC1120_TX_STATUS, 0x00, /* TX Status */\r
+ CC1120_MARC_STATUS1, 0x00, /* MARC Status, Reg 1 */\r
+ CC1120_MARC_STATUS0, 0x00, /* MARC Status, Reg 0 */\r
+ CC1120_PA_IFAMP_TEST, 0x00, /* */\r
+ CC1120_FSRF_TEST, 0x00, /* */\r
+ CC1120_PRE_TEST, 0x00, /* */\r
+ CC1120_PRE_OVR, 0x00, /* */\r
+ CC1120_ADC_TEST, 0x00, /* ADC Test */\r
+ CC1120_DVC_TEST, 0x0b, /* DVC Test */\r
+ CC1120_ATEST, 0x40, /* */\r
+ CC1120_ATEST_LVDS, 0x00, /* */\r
+ CC1120_ATEST_MODE, 0x00, /* */\r
+ CC1120_XOSC_TEST1, 0x3c, /* */\r
+ CC1120_XOSC_TEST0, 0x00, /* */\r
+ CC1120_RXFIRST, 0x00, /* RX FIFO Pointer (first entry) */\r
+ CC1120_TXFIRST, 0x00, /* TX FIFO Pointer (first entry) */\r
+ CC1120_RXLAST, 0x00, /* RX FIFO Pointer (last entry) */\r
+ CC1120_TXLAST, 0x00, /* TX FIFO Pointer (last entry) */\r
+\r
--- /dev/null
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+__xdata struct ao_packet_recv ao_rx_packet;
+__xdata struct ao_packet ao_tx_packet;
+__pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used;
+
+static __xdata char tx_data[AO_PACKET_MAX];
+static __xdata char rx_data[AO_PACKET_MAX];
+static __pdata uint8_t rx_seq;
+
+__xdata struct ao_task ao_packet_task;
+__xdata uint8_t ao_packet_enable;
+__xdata uint8_t ao_packet_master_sleeping;
+
+void
+ao_packet_send(void)
+{
+#ifdef AO_LED_RED
+ ao_led_on(AO_LED_RED);
+#endif
+ /* If any tx data is pending then copy it into the tx packet */
+ if (ao_packet_tx_used && ao_tx_packet.len == 0) {
+ ao_xmemcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used);
+ ao_tx_packet.len = ao_packet_tx_used;
+ ao_tx_packet.seq++;
+ ao_packet_tx_used = 0;
+ ao_wakeup(&tx_data);
+ }
+ ao_radio_send(&ao_tx_packet, sizeof (ao_tx_packet));
+#ifdef AO_LED_RED
+ ao_led_off(AO_LED_RED);
+#endif
+}
+
+uint8_t
+ao_packet_recv(void)
+{
+ uint8_t dma_done;
+
+#ifdef AO_LED_GREEN
+ ao_led_on(AO_LED_GREEN);
+#endif
+ dma_done = ao_radio_recv(&ao_rx_packet, sizeof (struct ao_packet_recv));
+#ifdef AO_LED_GREEN
+ ao_led_off(AO_LED_GREEN);
+#endif
+
+ /* Check to see if we got a valid packet */
+ if (!dma_done)
+ return 0;
+#ifdef PKT_APPEND_STATUS_1_CRC_OK
+ if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK))
+ return 0;
+#endif
+
+ /* Accept packets with matching call signs, or any packet if
+ * our callsign hasn't been configured
+ */
+ if (ao_xmemcmp(ao_rx_packet.packet.callsign,
+ ao_config.callsign,
+ AO_MAX_CALLSIGN) != 0 &&
+ ao_xmemcmp(ao_config.callsign, CODE_TO_XDATA("N0CALL"), 7) != 0)
+ return 0;
+
+ /* SYN packets carry no data */
+ if (ao_rx_packet.packet.len == AO_PACKET_SYN) {
+ rx_seq = ao_rx_packet.packet.seq;
+ ao_tx_packet.seq = ao_rx_packet.packet.ack;
+ ao_tx_packet.ack = rx_seq;
+ } else if (ao_rx_packet.packet.len) {
+
+ /* Check for incoming data at the next sequence and
+ * for an empty data buffer
+ */
+ if (ao_rx_packet.packet.seq == (uint8_t) (rx_seq + (uint8_t) 1) &&
+ ao_packet_rx_used == ao_packet_rx_len) {
+
+ /* Copy data to the receive data buffer and set up the
+ * offsets
+ */
+ ao_xmemcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len);
+ ao_packet_rx_used = 0;
+ ao_packet_rx_len = ao_rx_packet.packet.len;
+
+ /* Mark the sequence that we've received to
+ * let the sender know when we return a packet
+ */
+ rx_seq = ao_rx_packet.packet.seq;
+ ao_tx_packet.ack = rx_seq;
+
+ /* Poke anyone looking for received data */
+ ao_wakeup(&ao_stdin_ready);
+ }
+ }
+
+ /* If the other side has seen the latest data we queued,
+ * wake up any task waiting to send data and let them go again
+ */
+ if (ao_rx_packet.packet.ack == ao_tx_packet.seq) {
+ ao_tx_packet.len = 0;
+ ao_wakeup(&ao_tx_packet);
+ }
+ return 1;
+}
+
+#ifndef PACKET_HAS_MASTER
+#define PACKET_HAS_MASTER 1
+#endif
+
+#if PACKET_HAS_MASTER
+void
+ao_packet_flush(void)
+{
+ /* If there is data to send, and this is the master,
+ * then poke the master to send all queued data
+ */
+ if (ao_packet_tx_used && ao_packet_master_sleeping)
+ ao_wakeup(&ao_packet_master_sleeping);
+}
+#endif /* PACKET_HAS_MASTER */
+
+void
+ao_packet_putchar(char c) __reentrant
+{
+ while (ao_packet_tx_used == AO_PACKET_MAX && ao_packet_enable) {
+#if PACKET_HAS_MASTER
+ ao_packet_flush();
+#endif
+ ao_sleep(&tx_data);
+ }
+
+ if (ao_packet_enable)
+ tx_data[ao_packet_tx_used++] = c;
+}
+
+char
+ao_packet_pollchar(void) __critical
+{
+ if (!ao_packet_enable)
+ return AO_READ_AGAIN;
+
+ if (ao_packet_rx_used == ao_packet_rx_len)
+ return AO_READ_AGAIN;
+
+ return rx_data[ao_packet_rx_used++];
+}
--- /dev/null
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+static char
+ao_packet_getchar(void) __critical
+{
+ char c;
+ while ((c = ao_packet_pollchar()) == AO_READ_AGAIN) {
+ if (!ao_packet_enable)
+ break;
+ if (ao_packet_master_sleeping)
+ ao_wakeup(&ao_packet_master_sleeping);
+ flush();
+ ao_sleep(&ao_stdin_ready);
+ }
+ return c;
+}
+
+static void
+ao_packet_echo(void) __reentrant
+{
+ char c;
+ while (ao_packet_enable) {
+ c = ao_packet_getchar();
+ if (c != AO_READ_AGAIN)
+ putchar(c);
+ }
+ ao_exit();
+}
+
+static __xdata struct ao_task ao_packet_echo_task;
+static __xdata uint16_t ao_packet_master_delay;
+static __xdata uint16_t ao_packet_master_time;
+
+#define AO_PACKET_MASTER_DELAY_SHORT AO_MS_TO_TICKS(100)
+#define AO_PACKET_MASTER_DELAY_LONG AO_MS_TO_TICKS(1000)
+#define AO_PACKET_MASTER_DELAY_TIMEOUT AO_MS_TO_TICKS(2000)
+
+static void
+ao_packet_master_busy(void)
+{
+ ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT;
+ ao_packet_master_time = ao_time();
+}
+
+static void
+ao_packet_master_check_busy(void)
+{
+ int16_t idle;
+ if (ao_packet_master_delay != AO_PACKET_MASTER_DELAY_SHORT)
+ return;
+ idle = (int16_t) (ao_time() - ao_packet_master_time);
+
+ if (idle > AO_PACKET_MASTER_DELAY_TIMEOUT)
+ ao_packet_master_delay = AO_PACKET_MASTER_DELAY_LONG;
+}
+
+void
+ao_packet_master(void)
+{
+ ao_config_get();
+ ao_tx_packet.addr = ao_serial_number;
+ ao_tx_packet.len = AO_PACKET_SYN;
+ ao_packet_master_time = ao_time();
+ ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT;
+ while (ao_packet_enable) {
+ uint8_t r;
+ ao_xmemcpy(ao_tx_packet.callsign, ao_config.callsign, AO_MAX_CALLSIGN);
+ ao_packet_send();
+ if (ao_tx_packet.len)
+ ao_packet_master_busy();
+ ao_packet_master_check_busy();
+ ao_alarm(ao_packet_master_delay);
+ r = ao_packet_recv();
+ ao_clear_alarm();
+ if (r) {
+ /* if we can transmit data, do so */
+ if (ao_packet_tx_used && ao_tx_packet.len == 0)
+ continue;
+ if (ao_rx_packet.packet.len)
+ ao_packet_master_busy();
+ ao_packet_master_sleeping = 1;
+ ao_alarm(ao_packet_master_delay);
+ ao_sleep(&ao_packet_master_sleeping);
+ ao_clear_alarm();
+ ao_packet_master_sleeping = 0;
+ }
+ }
+ ao_exit();
+}
+
+static void
+ao_packet_forward(void) __reentrant
+{
+ char c;
+ ao_packet_enable = 1;
+ ao_cmd_white();
+
+ flush();
+#if HAS_MONITOR
+ ao_monitor_disable();
+#endif
+ ao_add_task(&ao_packet_task, ao_packet_master, "master");
+ ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo");
+ while ((c = getchar()) != '~') {
+ if (c == '\r') c = '\n';
+ ao_packet_putchar(c);
+ }
+
+ /* Wait for a second if there is any pending data */
+ for (c = 0; (ao_packet_tx_used || ao_tx_packet.len) && c < 10; c++)
+ ao_delay(AO_MS_TO_TICKS(100));
+ ao_packet_enable = 0;
+ while (ao_packet_echo_task.wchan || ao_packet_task.wchan) {
+ ao_radio_recv_abort();
+ ao_wakeup(&ao_stdin_ready);
+ ao_delay(AO_MS_TO_TICKS(10));
+ }
+#if HAS_MONITOR
+ ao_monitor_enable();
+#endif
+}
+
+
+
+__code struct ao_cmds ao_packet_master_cmds[] = {
+ { ao_packet_forward, "p\0Remote packet link." },
+ { 0, NULL },
+};
+
+void
+ao_packet_master_init(void)
+{
+ ao_cmd_register(&ao_packet_master_cmds[0]);
+}
--- /dev/null
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+void
+ao_packet_slave(void)
+{
+ ao_tx_packet.addr = ao_serial_number;
+ ao_tx_packet.len = AO_PACKET_SYN;
+ while (ao_packet_enable) {
+ if (ao_packet_recv()) {
+ ao_xmemcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN);
+#if HAS_FLIGHT
+ ao_flight_force_idle = TRUE;
+#endif
+ ao_packet_send();
+ }
+ }
+ ao_exit();
+}
+
+void
+ao_packet_slave_start(void)
+{
+ if (!ao_packet_enable) {
+ ao_packet_enable = 1;
+ ao_add_task(&ao_packet_task, ao_packet_slave, "slave");
+ }
+}
+
+void
+ao_packet_slave_stop(void)
+{
+ if (ao_packet_enable) {
+ ao_packet_enable = 0;
+ while (ao_packet_task.wchan) {
+ ao_radio_recv_abort();
+ ao_delay(AO_MS_TO_TICKS(10));
+ }
+ }
+}
+
+void
+ao_packet_slave_init(uint8_t enable)
+{
+ ao_add_stdio(ao_packet_pollchar,
+ ao_packet_putchar,
+ NULL);
+ if (enable)
+ ao_packet_slave_start();
+}
ao_beep_stm.c \
ao_storage.c \
ao_m25.c \
- ao_usb_stm.c
+ ao_usb_stm.c \
+ ao_exti_stm.c \
+ ao_packet.c \
+ ao_packet_slave.c
PRODUCT=MegaMetrum-v0.1
PRODUCT_DEF=-DMEGAMETRUM
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#include "ao.h"
+#include <ao.h>
+#include <ao_exti.h>
void
beep(void)
ao_adc_init();
ao_storage_init();
ao_usb_init();
+ ao_exti_init();
+ ao_radio_init();
ao_cmd_register(&ao_mm_cmds[0]);
ao_start_scheduler();
#define AO_M25_SPI_CS_MASK (1 << 3)
#define AO_M25_SPI_BUS STM_SPI_INDEX(2)
+/*
+ * Radio (cc1120)
+ */
+
+#define AO_CC1120_SPI_CS_PORT stm_gpioc
+#define AO_CC1120_SPI_CS_PIN 5
+#define AO_CC1120_SPI_BUS STM_SPI_INDEX(2)
+
+#define AO_CC1120_INT_PORT stm_gpioc
+#define AO_CC1120_INT_PIN 14
+
+#define AO_CC1120_INT_GPIO 2
+
#endif /* _AO_PINS_H_ */
include ../Version
endif
-AO_CFLAGS=-I. -I../stm -I../core -I..
+AO_CFLAGS=-I. -I../stm -I../core -I../drivers -I..
STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS)
LDFLAGS=-L../stm -Wl,-Taltos.ld
void
ao_spi_send(void *block, uint16_t len, uint8_t spi_index);
+void
+ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index);
+
void
ao_spi_recv(void *block, uint16_t len, uint8_t spi_index);
+void
+ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index);
+
void
ao_spi_init(void);
ao_spi_put(bus); \
} while (0)
-#define ao_stm_enable_port(port) do { \
+#define ao_enable_port(port) do { \
if (&(port) == &stm_gpioa) \
stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); \
else if (&(port) == &stm_gpiob) \
} while (0)
-#define ao_stm_enable_cs(port,bit) do { \
+#define ao_enable_cs(port,bit) do { \
stm_gpio_set(&(port), bit, 1); \
stm_moder_set(&(port), bit, STM_MODER_OUTPUT); \
} while (0)
#define ao_spi_init_cs(port, mask) do { \
- ao_stm_enable_port(port); \
- if (mask & 0x0001) ao_stm_enable_cs(port, 0); \
- if (mask & 0x0002) ao_stm_enable_cs(port, 1); \
- if (mask & 0x0004) ao_stm_enable_cs(port, 2); \
- if (mask & 0x0008) ao_stm_enable_cs(port, 3); \
- if (mask & 0x0010) ao_stm_enable_cs(port, 4); \
- if (mask & 0x0020) ao_stm_enable_cs(port, 5); \
- if (mask & 0x0040) ao_stm_enable_cs(port, 6); \
- if (mask & 0x0080) ao_stm_enable_cs(port, 7); \
- if (mask & 0x0100) ao_stm_enable_cs(port, 8); \
- if (mask & 0x0200) ao_stm_enable_cs(port, 9); \
- if (mask & 0x0400) ao_stm_enable_cs(port, 10); \
- if (mask & 0x0800) ao_stm_enable_cs(port, 11); \
- if (mask & 0x1000) ao_stm_enable_cs(port, 12); \
- if (mask & 0x2000) ao_stm_enable_cs(port, 13); \
- if (mask & 0x4000) ao_stm_enable_cs(port, 14); \
- if (mask & 0x8000) ao_stm_enable_cs(port, 15); \
+ ao_enable_port(port); \
+ if ((mask) & 0x0001) ao_enable_cs(port, 0); \
+ if ((mask) & 0x0002) ao_enable_cs(port, 1); \
+ if ((mask) & 0x0004) ao_enable_cs(port, 2); \
+ if ((mask) & 0x0008) ao_enable_cs(port, 3); \
+ if ((mask) & 0x0010) ao_enable_cs(port, 4); \
+ if ((mask) & 0x0020) ao_enable_cs(port, 5); \
+ if ((mask) & 0x0040) ao_enable_cs(port, 6); \
+ if ((mask) & 0x0080) ao_enable_cs(port, 7); \
+ if ((mask) & 0x0100) ao_enable_cs(port, 8); \
+ if ((mask) & 0x0200) ao_enable_cs(port, 9); \
+ if ((mask) & 0x0400) ao_enable_cs(port, 10);\
+ if ((mask) & 0x0800) ao_enable_cs(port, 11);\
+ if ((mask) & 0x1000) ao_enable_cs(port, 12);\
+ if ((mask) & 0x2000) ao_enable_cs(port, 13);\
+ if ((mask) & 0x4000) ao_enable_cs(port, 14);\
+ if ((mask) & 0x8000) ao_enable_cs(port, 15);\
} while (0)
/* ao_dma_stm.c
ao_dma_abort(uint8_t index)
{
stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN);
+ ao_wakeup(&ao_dma_done[index]);
}
void
--- /dev/null
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_EXTI_H_
+#define _AO_EXTI_H_
+
+#define AO_EXTI_MODE_RISING 1
+#define AO_EXTI_MODE_FALLING 2
+#define AO_EXTI_MODE_PULL_UP 4
+#define AO_EXTI_MODE_PULL_DOWN 8
+
+void
+ao_exti_setup(struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)());
+
+void
+ao_exti_enable(struct stm_gpio *gpio, uint8_t pin);
+
+void
+ao_exti_disable(struct stm_gpio *gpio, uint8_t pin);
+
+void
+ao_exti_init(void);
+
+#endif /* _AO_EXTI_H_ */
--- /dev/null
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_exti.h>
+
+static void (*ao_exti_callback[16])(void);
+
+static void
+ao_exti_isr(void) {
+ uint32_t pending = stm_exti.pr;
+ uint8_t pin;
+
+ /* Clear pending interrupts */
+ stm_exti.pr = pending;
+ for (pin = 0; pin < 16 && pending; pin++) {
+ uint32_t mask = (1 << pin);
+
+ if (pending & mask) {
+ pending &= ~mask;
+ if (ao_exti_callback[pin])
+ (*ao_exti_callback[pin])();
+ }
+ }
+}
+
+void stm_exti0_isr(void) { ao_exti_isr(); }
+void stm_exti1_isr(void) { ao_exti_isr(); }
+void stm_exti2_isr(void) { ao_exti_isr(); }
+void stm_exti3_isr(void) { ao_exti_isr(); }
+void stm_exti4_isr(void) { ao_exti_isr(); }
+void stm_exti9_5_isr(void) { ao_exti_isr(); }
+void stm_exti15_10_isr(void) { ao_exti_isr(); }
+
+void
+ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)(void)) {
+ uint32_t mask = 1 << pin;
+ uint32_t pupdr;
+ uint8_t irq;
+
+ ao_exti_callback[pin] = callback;
+ /* configure pin as input, setting selected pull-up/down mode */
+ stm_moder_set(gpio, pin, STM_MODER_INPUT);
+ switch (mode & (AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_PULL_DOWN)) {
+ case 0:
+ default:
+ pupdr = STM_PUPDR_NONE;
+ break;
+ case AO_EXTI_MODE_PULL_UP:
+ pupdr = STM_PUPDR_PULL_UP;
+ break;
+ case AO_EXTI_MODE_PULL_DOWN:
+ pupdr = STM_PUPDR_PULL_DOWN;
+ break;
+ }
+ stm_pupdr_set(gpio, pin, pupdr);
+
+ /* Set interrupt mask and rising/falling mode */
+ stm_exti.imr &= ~mask;
+ stm_exti.rtsr |= mask;
+ if (mode & AO_EXTI_MODE_RISING)
+ stm_exti.rtsr |= mask;
+ if (mode & AO_EXTI_MODE_FALLING)
+ stm_exti.ftsr |= mask;
+
+ if (pin <= 4)
+ irq = STM_ISR_EXTI0_POS + pin;
+ else if (pin <= 9)
+ irq = STM_ISR_EXTI9_5_POS;
+ else
+ irq = STM_ISR_EXTI15_10_POS;
+ stm_nvic_set_priority(irq, 10);
+ stm_nvic_set_enable(irq);
+}
+
+void
+ao_exti_enable(struct stm_gpio *gpio, uint8_t pin) {
+ stm_exti.imr |= (1 << pin);
+}
+
+void
+ao_exti_disable(struct stm_gpio *gpio, uint8_t pin) {
+ stm_exti.imr &= ~(1 << pin);
+}
+
+void
+ao_exti_init(void)
+{
+ stm_nvic_set_priority(STM_ISR_EXTI1_POS, 10);
+ stm_nvic_set_priority(STM_ISR_EXTI2_POS, 10);
+ stm_nvic_set_priority(STM_ISR_EXTI3_POS, 10);
+ stm_nvic_set_priority(STM_ISR_EXTI4_POS, 10);
+ stm_nvic_set_priority(STM_ISR_EXTI9_5_POS, 10);
+ stm_nvic_set_priority(STM_ISR_EXTI15_10_POS, 10);
+}
ao_dma_done_transfer(miso_dma_index);
}
+void
+ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index)
+{
+ struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi;
+ uint8_t mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index;
+ uint8_t miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index;
+
+ /* Set up the transmit DMA to deliver data */
+ ao_dma_set_transfer(mosi_dma_index,
+ &stm_spi->dr,
+ &value,
+ len,
+ (0 << STM_DMA_CCR_MEM2MEM) |
+ (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+ (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+ (0 << STM_DMA_CCR_MINC) |
+ (0 << STM_DMA_CCR_PINC) |
+ (0 << STM_DMA_CCR_CIRC) |
+ (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR));
+
+ /* Clear RXNE */
+ (void) stm_spi->dr;
+
+ /* Set up the receive DMA -- when this is done, we know the SPI unit
+ * is idle. Without this, we'd have to poll waiting for the BSY bit to
+ * be cleared
+ */
+ ao_dma_set_transfer(miso_dma_index,
+ &stm_spi->dr,
+ &spi_dev_null,
+ len,
+ (0 << STM_DMA_CCR_MEM2MEM) |
+ (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+ (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+ (0 << STM_DMA_CCR_MINC) |
+ (0 << STM_DMA_CCR_PINC) |
+ (0 << STM_DMA_CCR_CIRC) |
+ (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
+ stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
+ (0 << STM_SPI_CR2_RXNEIE) |
+ (0 << STM_SPI_CR2_ERRIE) |
+ (0 << STM_SPI_CR2_SSOE) |
+ (1 << STM_SPI_CR2_TXDMAEN) |
+ (1 << STM_SPI_CR2_RXDMAEN));
+ ao_dma_start(miso_dma_index);
+ ao_dma_start(mosi_dma_index);
+ ao_arch_critical(
+ while (!ao_dma_done[miso_dma_index])
+ ao_sleep(&ao_dma_done[miso_dma_index]);
+ );
+ ao_dma_done_transfer(mosi_dma_index);
+ ao_dma_done_transfer(miso_dma_index);
+}
+
void
ao_spi_recv(void *block, uint16_t len, uint8_t spi_index)
{
ao_dma_done_transfer(miso_dma_index);
}
+void
+ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index)
+{
+ struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi;
+ uint8_t mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index;
+ uint8_t miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index;
+
+ /* Set up transmit DMA to send data */
+ ao_dma_set_transfer(mosi_dma_index,
+ &stm_spi->dr,
+ out,
+ len,
+ (0 << STM_DMA_CCR_MEM2MEM) |
+ (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+ (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+ (1 << STM_DMA_CCR_MINC) |
+ (0 << STM_DMA_CCR_PINC) |
+ (0 << STM_DMA_CCR_CIRC) |
+ (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR));
+
+ /* Clear RXNE */
+ (void) stm_spi->dr;
+
+ /* Set up the receive DMA to capture data */
+ ao_dma_set_transfer(miso_dma_index,
+ &stm_spi->dr,
+ in,
+ len,
+ (0 << STM_DMA_CCR_MEM2MEM) |
+ (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+ (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+ (1 << STM_DMA_CCR_MINC) |
+ (0 << STM_DMA_CCR_PINC) |
+ (0 << STM_DMA_CCR_CIRC) |
+ (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
+
+ stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
+ (0 << STM_SPI_CR2_RXNEIE) |
+ (0 << STM_SPI_CR2_ERRIE) |
+ (0 << STM_SPI_CR2_SSOE) |
+ (1 << STM_SPI_CR2_TXDMAEN) |
+ (1 << STM_SPI_CR2_RXDMAEN));
+ ao_dma_start(miso_dma_index);
+ ao_dma_start(mosi_dma_index);
+
+ /* Wait until the SPI unit is done */
+ ao_arch_critical(
+ while (!ao_dma_done[miso_dma_index])
+ ao_sleep(&ao_dma_done[miso_dma_index]);
+ );
+
+ ao_dma_done_transfer(mosi_dma_index);
+ ao_dma_done_transfer(miso_dma_index);
+}
+
void
ao_spi_get(uint8_t spi_index)
{
}
#endif
+#if USB_DEBUG
static void
ao_usb_irq(void)
{
{ ao_usb_irq, "I\0Show USB interrupt counts" },
{ 0, NULL }
};
+#endif
void
ao_usb_init(void)
#if USB_ECHO
ao_add_task(&ao_usb_echo_task, ao_usb_echo, "usb echo");
#endif
+#if USB_DEBUG
ao_cmd_register(&ao_usb_cmds[0]);
+#endif
#if !USB_ECHO
ao_add_stdio(ao_usb_pollchar, ao_usb_putchar, ao_usb_flush);
#endif
#define STM_PUPDR_RESERVED 3
static inline void
-stm_pupdr_set(struct stm_gpio *gpio, int pin, vuint32_t value) {
+stm_pupdr_set(struct stm_gpio *gpio, int pin, uint32_t value) {
gpio->pupdr = ((gpio->pupdr &
~(STM_PUPDR_MASK << STM_PUPDR_SHIFT(pin))) |
value << STM_PUPDR_SHIFT(pin));
}
-static inline vuint32_t
+static inline uint32_t
stm_pupdr_get(struct stm_gpio *gpio, int pin) {
return (gpio->pupdr >> STM_PUPDR_SHIFT(pin)) & STM_PUPDR_MASK;
}
extern uint8_t stm_usb_sram[];
+struct stm_exti {
+ vuint32_t imr;
+ vuint32_t emr;
+ vuint32_t rtsr;
+ vuint32_t ftsr;
+
+ vuint32_t swier;
+ vuint32_t pr;
+};
+
+extern struct stm_exti stm_exti;
+
#endif /* _STM32L_H_ */