altos: Starting to write cc1120 driver
authorKeith Packard <keithp@keithp.com>
Tue, 17 Apr 2012 18:01:18 +0000 (11:01 -0700)
committerKeith Packard <keithp@keithp.com>
Tue, 17 Apr 2012 18:01:18 +0000 (11:01 -0700)
This does "something" in radio test mode, appearing to generate a
730MHz signal.

Signed-off-by: Keith Packard <keithp@keithp.com>
20 files changed:
src/cc1111/ao_packet.c [deleted file]
src/cc1111/ao_packet_master.c [deleted file]
src/cc1111/ao_packet_slave.c [deleted file]
src/drivers/ao_cc1120.c
src/drivers/ao_cc1120.h [new file with mode: 0644]
src/drivers/ao_cc1120_CC1120.h [new file with mode: 0644]
src/drivers/ao_packet.c [new file with mode: 0644]
src/drivers/ao_packet_master.c [new file with mode: 0644]
src/drivers/ao_packet_slave.c [new file with mode: 0644]
src/megametrum-v0.1/Makefile
src/megametrum-v0.1/ao_megametrum.c
src/megametrum-v0.1/ao_pins.h
src/stm/Makefile.defs
src/stm/ao_arch_funcs.h
src/stm/ao_dma_stm.c
src/stm/ao_exti.h [new file with mode: 0644]
src/stm/ao_exti_stm.c [new file with mode: 0644]
src/stm/ao_spi_stm.c
src/stm/ao_usb_stm.c
src/stm/stm32l.h

diff --git a/src/cc1111/ao_packet.c b/src/cc1111/ao_packet.c
deleted file mode 100644 (file)
index 7eeb071..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * 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++];
-}
diff --git a/src/cc1111/ao_packet_master.c b/src/cc1111/ao_packet_master.c
deleted file mode 100644 (file)
index 66f9428..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * 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]);
-}
diff --git a/src/cc1111/ao_packet_slave.c b/src/cc1111/ao_packet_slave.c
deleted file mode 100644 (file)
index fd5d443..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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();
-}
index 9470fa878ea74c01978f6cee1bd7e382546e8ac6..272371d0d7dce966f29e1972422994a9d132ad00 100644 (file)
  */
 
 #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]);
 }
diff --git a/src/drivers/ao_cc1120.h b/src/drivers/ao_cc1120.h
new file mode 100644 (file)
index 0000000..67c0a1b
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+ * 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_ */
diff --git a/src/drivers/ao_cc1120_CC1120.h b/src/drivers/ao_cc1120_CC1120.h
new file mode 100644 (file)
index 0000000..a96c22f
--- /dev/null
@@ -0,0 +1,191 @@
+/* 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
diff --git a/src/drivers/ao_packet.c b/src/drivers/ao_packet.c
new file mode 100644 (file)
index 0000000..19fe055
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * 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++];
+}
diff --git a/src/drivers/ao_packet_master.c b/src/drivers/ao_packet_master.c
new file mode 100644 (file)
index 0000000..66f9428
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * 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]);
+}
diff --git a/src/drivers/ao_packet_slave.c b/src/drivers/ao_packet_slave.c
new file mode 100644 (file)
index 0000000..fd5d443
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * 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();
+}
index 3c3d7173f27959768e63a15b8a49ece0b5ecc868..37832d16e6e9856dcfa79bf20833c79df7ec1a60 100644 (file)
@@ -41,7 +41,10 @@ ALTOS_SRC = \
        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
index 9efde5986e931807a0e68ff066f58bb27a48657e..d93480f2b87379a9c18527c30ea2a6b05b2b018c 100644 (file)
@@ -15,7 +15,8 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-#include "ao.h"
+#include <ao.h>
+#include <ao_exti.h>
 
 void
 beep(void)
@@ -51,6 +52,8 @@ main(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();
index f761e5c3602ab46753f5ae654c74d14722745dd3..2e83de8a35e67f73126d214d5d6af229bda95d60 100644 (file)
@@ -193,4 +193,17 @@ struct ao_adc {
 #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_ */
index 76962a3efd55d98fd0cd7dd9fb474472b699e405..3edfa41d5a512deca15f0b17d9ea8bafea3f10da 100644 (file)
@@ -16,7 +16,7 @@ ifndef VERSION
 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
index 309937d58180545bad3e309186e7e9a231175516..05bb77843ec2ba9081e7a9b92a17e6b1ce1386c2 100644 (file)
@@ -31,9 +31,15 @@ ao_spi_put(uint8_t spi_index);
 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);
 
@@ -47,7 +53,7 @@ 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)                         \
@@ -61,29 +67,29 @@ ao_spi_init(void);
        } 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
index 21390748b86dae82eddaec7e2662be60e38aa6a2..e76c8e8c936954a99cbbe6d1919311a0a1f23cae 100644 (file)
@@ -109,6 +109,7 @@ void
 ao_dma_abort(uint8_t index)
 {
        stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN);
+       ao_wakeup(&ao_dma_done[index]);
 }
 
 void
diff --git a/src/stm/ao_exti.h b/src/stm/ao_exti.h
new file mode 100644 (file)
index 0000000..43eaa52
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * 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_ */
diff --git a/src/stm/ao_exti_stm.c b/src/stm/ao_exti_stm.c
new file mode 100644 (file)
index 0000000..013d453
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * 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);
+}
index be24ebcfd1446cc16f51dbceebe96d6cd0f17b81..8bb0d8e8a2be33e869e393a75598be8dac7c5329 100644 (file)
@@ -96,6 +96,62 @@ ao_spi_send(void *block, uint16_t len, uint8_t spi_index)
        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)
 {
@@ -153,6 +209,63 @@ 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)
 {
index 223fdeaa4620c9eea4d5802dd6966a2f0ae0e9e2..71bf1bc76eecc9cc4170b67fc41bf1449876a487 100644 (file)
@@ -1005,6 +1005,7 @@ ao_usb_echo(void)
 }
 #endif
 
+#if USB_DEBUG
 static void
 ao_usb_irq(void)
 {
@@ -1016,6 +1017,7 @@ __code struct ao_cmds ao_usb_cmds[] = {
        { ao_usb_irq, "I\0Show USB interrupt counts" },
        { 0, NULL }
 };
+#endif
 
 void
 ao_usb_init(void)
@@ -1027,7 +1029,9 @@ 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
index e884ef04a8812e8f5af73daefc9e3f21ebfd5435..10a53a477fd7932d654dbbc0d2e34cb3af973814 100644 (file)
@@ -101,13 +101,13 @@ stm_ospeedr_get(struct stm_gpio *gpio, int pin) {
 #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;
 }
@@ -1589,4 +1589,16 @@ union stm_usb_bdt {
 
 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_ */