commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] r8407 - in usrp2/trunk: doc firmware/apps firmware/inc


From: eb
Subject: [Commit-gnuradio] r8407 - in usrp2/trunk: doc firmware/apps firmware/include firmware/lib host/apps host/lib
Date: Sun, 11 May 2008 23:47:50 -0600 (MDT)

Author: eb
Date: 2008-05-11 23:47:50 -0600 (Sun, 11 May 2008)
New Revision: 8407

Added:
   usrp2/trunk/firmware/apps/app_common_v2.c
   usrp2/trunk/firmware/apps/app_common_v2.h
   usrp2/trunk/firmware/apps/rx_only_v2.c
   usrp2/trunk/firmware/apps/tx_only_v2.c
   usrp2/trunk/firmware/apps/txrx.c
   usrp2/trunk/host/apps/rx_samples_at_t.cc
Modified:
   usrp2/trunk/doc/inband-signaling-eth
   usrp2/trunk/firmware/apps/
   usrp2/trunk/firmware/apps/Makefile.am
   usrp2/trunk/firmware/apps/app_common.c
   usrp2/trunk/firmware/apps/app_passthru.c
   usrp2/trunk/firmware/include/usrp2_eth_packet.h
   usrp2/trunk/firmware/include/usrp2_types.h
   usrp2/trunk/firmware/lib/db_basic.c
   usrp2/trunk/firmware/lib/db_init.c
   usrp2/trunk/firmware/lib/dbsm.c
   usrp2/trunk/firmware/lib/dbsm.h
   usrp2/trunk/host/apps/Makefile.am
   usrp2/trunk/host/apps/rx_streaming_samples.cc
   usrp2/trunk/host/apps/tx_samples.cc
   usrp2/trunk/host/lib/usrp2_basic.cc
   usrp2/trunk/host/lib/usrp2_basic.h
Log:
USRP2 simultaneous Tx and Rx is working.  Uses new config packet
format.  Merged eb/u2-newpktfmt -r8394:8406 into usrp2 trunk.



Modified: usrp2/trunk/doc/inband-signaling-eth
===================================================================
--- usrp2/trunk/doc/inband-signaling-eth        2008-05-12 05:32:16 UTC (rev 
8406)
+++ usrp2/trunk/doc/inband-signaling-eth        2008-05-12 05:47:50 UTC (rev 
8407)
@@ -161,10 +161,10 @@
 Specific sub-packet formats:
 ----------------------------
 
-  RID: 6-bit Request-ID. Copied from request sub-packet into corresponding
+  RID: 8-bit Request-ID. Copied from request sub-packet into corresponding
        reply sub-packet.  RID allows the host to match requests and replies.
 
-  Reg Number: 10-bit Register Number.
+  Reg Number: 8-bit Register Number.
 
 
 
@@ -173,7 +173,7 @@
     Opcode:    OP_ID
 
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |     Opcode    |       2       |    RID    |        mbz        |
+   |     Opcode    |       2       |       RID     |      mbz      |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
 
@@ -182,7 +182,7 @@
     Opcode:    OP_ID_REPLY
 
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |     Opcode    |      50       |    RID    |        mbz        |
+   |     Opcode    |      50       |      RID      |      mbz      |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |  Mac Addr 0   |  Mac Addr 1   |  Mac Addr 2   |  Mac Addr 3   |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -210,30 +210,12 @@
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
 
-Ping Fixed Length:
-
-    Opcode:    OP_PING_FIXED
-
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |     Opcode    |       2       |    RID    |     Ping Value    |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
-
-Ping Fixed Length Reply:
-
-    Opcode:    OP_PING_FIXED_REPLY
-
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |     Opcode    |       2       |    RID    |     Ping Value    |
-   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
-
 Write Register:
 
     Opcode:    OP_WRITE_REG
 
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |     Opcode    |       6       |    mbz    |     Reg Number    |
+   |     Opcode    |       6       |      mbz      |   Reg Number  |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                        Register Value                         |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -250,7 +232,7 @@
 
 
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |     Opcode    |      10       |    mbz    |     Reg Number    |
+   |     Opcode    |      10       |      mbz      |   Reg Number  |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                         Register Value                        |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -263,7 +245,7 @@
     Opcode:    OP_READ_REG
 
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |     Opcode    |       2       |    RID    |     Reg Number    |
+   |     Opcode    |       2       |      RID      |   Reg Number  |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
 
@@ -272,7 +254,7 @@
     Opcode:    OP_READ_REG_REPLY
 
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |     Opcode    |       6       |    RID    |     Reg Number    |
+   |     Opcode    |       6       |      RID      |   Reg Number  |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                        Register Value                         |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -288,12 +270,25 @@
     Length:     Length of Data + 2
 
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |     Opcode    |    Length     |       mbz       |   I2C Addr  |
+   |     Opcode    |    Length     |      RID      |    I2C Addr   |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |    Data ...                                                  .
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
 
+I2C Write Reply:
+
+    Opcode:    OP_I2C_WRITE_REPLY
+    Length:     2
+
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |     Opcode    |       2       |      RID      |      OK       |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+OK is 1 if successful, else 0.
+
+
 I2C Read:
 
     Opcode:    OP_I2C_READ
@@ -301,7 +296,7 @@
     Nbytes:    Number of bytes to read from I2C bus
 
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |     Opcode    |       3       |    RID    | mbz |   I2C Addr  |
+   |     Opcode    |       3       |      RID      |    I2C Addr   |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |     Nbytes    |              unspecified padding              |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -314,12 +309,14 @@
     Data:      Length - 2 bytes of data read from I2C bus.
 
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |     Opcode    |     Length    |    RID    | mbz |   I2C Addr  |
+   |     Opcode    |     Length    |      RID      |      OK       |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |    Data ...                                                  .
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
+OK is 1 if successful, else 0
 
+
 SPI Write:
 
     Opcode:          OP_SPI_WRITE
@@ -330,7 +327,7 @@
     Length:          Length of Data + 6
 
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |     Opcode    |    Length     |              mbz              |
+   |     Opcode    |     Length    |      RID      |      mbz      |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |    Enables    |    Format     |        Opt Header Bytes       |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -338,6 +335,19 @@
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
 
+SPI Write Reply:
+
+    Opcode:    OP_SPI_WRITE_REPLY
+    Length:     2
+
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |     Opcode    |       2       |      RID      |      OK       |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+OK is 1 if successful, else 0.
+
+
 SPI Read:
 
     Opcode:          OP_SPI_READ
@@ -347,7 +357,7 @@
     Nbytes:          Number of bytes to read from SPI bus.
 
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-   |     Opcode    |       7       |    RID    |        mbz        |
+   |     Opcode    |       7       |      RID      |      mbz      |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |    Enables    |    Format     |        Opt Header Bytes       |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+


Property changes on: usrp2/trunk/firmware/apps
___________________________________________________________________
Name: svn:ignore
   - *-stamp
*.a
*.bin
*.dump
*.log
*.rom
*.map
.deps
Makefile
Makefile.in
aclocal.m4
autom4te.cache
blink_leds
blink_leds2
build
compile
config.h
config.h.in
config.log
config.status
configure
depcomp
eth_test
gen_eth_packets
ibs_rx_test
ibs_tx_test
install-sh
libtool
ltmain.sh
missing
py-compile
rcv_eth_packets
run_tests.sh
stamp-h1
test1
test_phy_comm
timer_test
buf_ram_test
buf_ram_zero
hello
test_printf
test_spi
test_i2c
gen_pause_frames
test_serdes
rx_only
tx_only
tx_standalone
tx_drop
tx_drop2
tx_drop_rate_limited
test_lsdac
test_lsadc
read_dbids
test_db_spi
ramp_lsdac
eth_to_serdes
serdes_to_dsp
sd_gentest
sd_bounce
can_i_sub

   + *-stamp
*.a
*.bin
*.dump
*.log
*.rom
*.map
.deps
Makefile
Makefile.in
aclocal.m4
autom4te.cache
blink_leds
blink_leds2
build
compile
config.h
config.h.in
config.log
config.status
configure
depcomp
eth_test
gen_eth_packets
ibs_rx_test
ibs_tx_test
install-sh
libtool
ltmain.sh
missing
py-compile
rcv_eth_packets
run_tests.sh
stamp-h1
test1
test_phy_comm
timer_test
buf_ram_test
buf_ram_zero
hello
test_printf
test_spi
test_i2c
gen_pause_frames
test_serdes
rx_only
tx_only
tx_standalone
tx_drop
tx_drop2
tx_drop_rate_limited
test_lsdac
test_lsadc
read_dbids
test_db_spi
ramp_lsdac
eth_to_serdes
serdes_to_dsp
sd_gentest
sd_bounce
can_i_sub
tx_only_v2
rx_only_v2
txrx


Modified: usrp2/trunk/firmware/apps/Makefile.am
===================================================================
--- usrp2/trunk/firmware/apps/Makefile.am       2008-05-12 05:32:16 UTC (rev 
8406)
+++ usrp2/trunk/firmware/apps/Makefile.am       2008-05-12 05:47:50 UTC (rev 
8407)
@@ -30,6 +30,7 @@
        ibs_tx_test \
        rcv_eth_packets \
        rx_only \
+       rx_only_v2 \
        read_dbids \
        test1 \
        test_db_spi \
@@ -40,7 +41,9 @@
        test_serdes \
        timer_test \
        tx_only \
+       tx_only_v2 \
        tx_standalone \
+       txrx \
        eth_to_serdes \
        serdes_to_dsp \
        sd_gentest \
@@ -52,6 +55,9 @@
 # tx_drop2_SOURCES = tx_drop2.c app_common.c
 tx_only_SOURCES = tx_only.c app_common.c
 rx_only_SOURCES = rx_only.c app_common.c
+rx_only_v2_SOURCES = rx_only_v2.c app_common_v2.c
+tx_only_v2_SOURCES = tx_only_v2.c app_common_v2.c
+txrx_SOURCES = txrx.c app_common_v2.c
 eth_to_serdes_SOURCES = eth_to_serdes.c app_passthru.c
 serdes_to_dsp_SOURCES = serdes_to_dsp.c app_common.c
 

Modified: usrp2/trunk/firmware/apps/app_common.c
===================================================================
--- usrp2/trunk/firmware/apps/app_common.c      2008-05-12 05:32:16 UTC (rev 
8406)
+++ usrp2/trunk/firmware/apps/app_common.c      2008-05-12 05:47:50 UTC (rev 
8407)
@@ -91,7 +91,7 @@
       reply_len = sizeof(u2_eth_packet_t) + sizeof(op_id_reply_t);
       r->opcode = OP_ID_REPLY;
       r->len = sizeof(op_id_reply_t);
-      r->rid_mbz = ((op_id_t *) p)->rid_mbz;
+      r->rid = ((op_id_t *) p)->rid;
       r->addr = *ethernet_mac_addr();
       r->hw_rev = 0x0000;      // FIXME
       // r->fpga_md5sum = ;    // FIXME
@@ -124,7 +124,7 @@
       reply_len = sizeof(u2_eth_packet_t) + sizeof(op_read_time_reply_t);
       r->opcode = OP_READ_TIME_REPLY;
       r->len = sizeof(op_read_time_reply_t);
-      r->rid_mbz = ((op_read_time_t *) p)->rid_mbz;
+      r->rid = ((op_read_time_t *) p)->rid;
       r->time = timer_regs->time;
     }
     send_reply(reply, reply_len);

Copied: usrp2/trunk/firmware/apps/app_common_v2.c (from rev 8406, 
usrp2/branches/developers/eb/u2-newpktfmt/firmware/apps/app_common_v2.c)
===================================================================
--- usrp2/trunk/firmware/apps/app_common_v2.c                           (rev 0)
+++ usrp2/trunk/firmware/apps/app_common_v2.c   2008-05-12 05:47:50 UTC (rev 
8407)
@@ -0,0 +1,228 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "app_common_v2.h"
+#include "buffer_pool.h"
+#include "memcpy_wa.h"
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "print_rmon_regs.h"
+#include <string.h>
+
+volatile bool link_is_up = false;      // eth handler sets this
+
+
+// If this is non-zero, this dbsm could be writing to the ethernet
+dbsm_t *ac_could_be_sending_to_eth;
+
+static unsigned char exp_seqno = 0;
+
+
+static void
+burn_mac_addr(const op_burn_mac_addr_t *p)
+{
+  ethernet_set_mac_addr(&p->addr);
+}
+
+void
+set_reply_hdr(u2_eth_packet_t *reply_pkt, u2_eth_packet_t const *cmd_pkt)
+{
+  reply_pkt->ehdr.dst = cmd_pkt->ehdr.src;
+  reply_pkt->ehdr.ethertype = U2_ETHERTYPE;
+  reply_pkt->thdr.flags = 0;
+  reply_pkt->thdr.fifo_status = 0;     // written by protocol engine
+  reply_pkt->thdr.seqno = 0;           // written by protocol engine
+  reply_pkt->thdr.ack = 0;             // written by protocol engine
+  u2p_set_word0(&reply_pkt->fixed, 0, CONTROL_CHAN);
+  reply_pkt->fixed.timestamp = timer_regs->time;
+}
+
+static void
+send_reply(unsigned char *reply, size_t reply_len)
+{
+  if (reply_len < 64)
+    reply_len = 64;
+
+  // wait for buffer to become idle
+  while((buffer_pool_status->status & BPS_IDLE(CPU_TX_BUF)) == 0)
+    ;
+
+  // copy reply into CPU_TX_BUF
+  memcpy_wa(buffer_ram(CPU_TX_BUF), reply, reply_len);
+
+  // wait until nobody else is sending to the ethernet
+  if (ac_could_be_sending_to_eth)
+    dbsm_wait_for_opening(ac_could_be_sending_to_eth);
+
+  // fire it off
+  bp_send_from_buf(CPU_TX_BUF, PORT_ETH, 1, 0, reply_len/4);
+
+  // wait for it to complete (not long, it's a small pkt)
+  while((buffer_pool_status->status & (BPS_DONE(CPU_TX_BUF) | 
BPS_ERROR(CPU_TX_BUF))) == 0)
+    ;
+
+  bp_clear_buf(CPU_TX_BUF);
+}
+
+
+void
+handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len)
+{
+  unsigned char reply[sizeof(u2_eth_packet_t) + sizeof(u2_subpkt_t)] _AL4;
+  unsigned char *s = &reply[sizeof(u2_eth_packet_t)];
+  size_t reply_len = 0;
+
+  // point to beginning of payload (subpackets)
+  unsigned char *p = ((unsigned char *) pkt) + sizeof(u2_eth_packet_t);
+
+  // FIXME iterate over payload, handling more than a single subpacket
+
+  int opcode = p[0];
+
+  switch(opcode){
+  case OP_ID:
+    memset(reply, 0, sizeof(reply));
+    set_reply_hdr((u2_eth_packet_t *) reply, pkt);
+    {
+      op_id_reply_t *r = (op_id_reply_t *) s;
+      reply_len = sizeof(u2_eth_packet_t) + sizeof(op_id_reply_t);
+      r->opcode = OP_ID_REPLY;
+      r->len = sizeof(op_id_reply_t);
+      r->rid = ((op_id_t *) p)->rid;
+      r->addr = *ethernet_mac_addr();
+      r->hw_rev = 0x0000;      // FIXME
+      // r->fpga_md5sum = ;    // FIXME
+      // r->sw_md5sum = ;      // FIXME
+
+      // FIXME Add d'board info, including dbid, min/max gain, min/max freq
+    }
+    send_reply(reply, reply_len);
+    break;
+    
+  case OP_CONFIG_TX_V2:
+    config_tx_v2_cmd((op_config_tx_v2_t *) p);
+    break;
+
+  case OP_CONFIG_RX_V2:
+    config_rx_v2_cmd((op_config_rx_v2_t *) p);
+    break;
+
+  case OP_START_RX_STREAMING:
+    start_rx_streaming_cmd(&pkt->ehdr.src, (op_start_rx_streaming_t *) p);
+    break;
+    
+  case OP_STOP_RX:
+    stop_rx_cmd();
+    break;
+    
+  case OP_BURN_MAC_ADDR:
+    burn_mac_addr((op_burn_mac_addr_t *) p);
+    break;
+
+  case OP_READ_TIME:
+    memset(reply, 0, sizeof(reply));
+    set_reply_hdr((u2_eth_packet_t *) reply, pkt);
+    {
+      op_read_time_reply_t *r = (op_read_time_reply_t *) s;
+      reply_len = sizeof(u2_eth_packet_t) + sizeof(op_read_time_reply_t);
+      r->opcode = OP_READ_TIME_REPLY;
+      r->len = sizeof(op_read_time_reply_t);
+      r->rid = ((op_read_time_t *) p)->rid;
+      r->time = timer_regs->time;
+    }
+    send_reply(reply, reply_len);
+    break;
+
+  default:
+    printf("app_common_v2: unhandled opcode = %d\n", opcode);
+    break;
+  }
+}
+
+
+/*
+ * Called when an ethernet packet is received.
+ * Return true if we handled it here, otherwise
+ * it'll be passed on to the DSP Tx pipe
+ */
+bool
+eth_pkt_inspector(dbsm_t *sm, int bufno)
+{
+  u2_eth_packet_t *pkt = (u2_eth_packet_t *) buffer_ram(bufno);
+  size_t byte_len = (buffer_pool_status->last_line[bufno] - 3) * 4;
+
+  hal_toggle_leds(0x1);
+
+  // inspect rcvd frame and figure out what do do.
+
+  if (pkt->ehdr.ethertype != U2_ETHERTYPE)
+    return true;       // ignore, probably bogus PAUSE frame from MAC
+
+  int chan = u2p_chan(&pkt->fixed);
+
+  switch (chan){
+  case CONTROL_CHAN:
+    handle_control_chan_frame(pkt, byte_len);
+    return true;       // we handled the packet
+    break;
+
+  case 0:
+  default:
+#if 0
+    if((pkt->thdr.seqno) == exp_seqno){
+      exp_seqno++;
+      //putchar('.');
+    }
+    else {
+      // putchar('S');
+      //printf("S%d %d ",exp_seqno,pkt->thdr.seqno);
+      exp_seqno = pkt->thdr.seqno + 1;
+    }
+#endif
+    return false;      // pass it on to Tx DSP
+    break;
+  }
+}
+
+/*
+ * Called when eth phy state changes (w/ interrupts disabled)
+ */
+void
+link_changed_callback(int speed)
+{
+  link_is_up = speed != 0;
+  hal_set_leds(link_is_up ? 0x10 : 0x0, 0x10);
+  printf("\neth link changed: speed = %d\n", speed);
+}
+
+
+void
+print_tune_result(char *msg, bool tune_ok,
+                 u2_fxpt_freq_t target_freq, struct tune_result *r)
+{
+  printf("db_tune %s %s\n", msg, tune_ok ? "true" : "false");
+  putstr("  target_freq   "); print_fxpt_freq(target_freq); newline();
+  putstr("  baseband_freq "); print_fxpt_freq(r->baseband_freq); newline();
+  putstr("  dxc_freq      "); print_fxpt_freq(r->dxc_freq); newline();
+  putstr("  residual_freq "); print_fxpt_freq(r->residual_freq); newline();
+  printf("  inverted      %s\n", r->inverted ? "true" : "false");
+}

Copied: usrp2/trunk/firmware/apps/app_common_v2.h (from rev 8406, 
usrp2/branches/developers/eb/u2-newpktfmt/firmware/apps/app_common_v2.h)
===================================================================
--- usrp2/trunk/firmware/apps/app_common_v2.h                           (rev 0)
+++ usrp2/trunk/firmware/apps/app_common_v2.h   2008-05-12 05:47:50 UTC (rev 
8407)
@@ -0,0 +1,65 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_APP_COMMON_H
+#define INCLUDED_APP_COMMON_H
+
+#include "bool.h"
+#include "usrp2_eth_packet.h"
+#include "dbsm.h"
+#include "memory_map.h"
+#include "hal_io.h"
+#include <stddef.h>
+#include <db.h>
+
+#define CPU_TX_BUF     1       // cpu -> eth
+
+#define        _AL4 __attribute__((aligned (4)))
+
+extern volatile bool link_is_up;       // eth handler sets this
+
+
+// If there's a dbsm that sends to the ethernet, put it's address here
+extern dbsm_t *ac_could_be_sending_to_eth;
+
+
+void set_reply_hdr(u2_eth_packet_t *reply_pkt, u2_eth_packet_t const *cmd_pkt);
+
+/*
+ * Called when an ethernet packet is received.
+ * Return true if we handled it here, otherwise
+ * it'll be passed on to the DSP Tx pipe
+ */
+bool eth_pkt_inspector(dbsm_t *sm, int bufno);
+
+void link_changed_callback(int speed);
+
+void
+print_tune_result(char *msg, bool tune_ok,
+                 u2_fxpt_freq_t target_freq, struct tune_result *r);
+
+
+// FIXME move these somewhere else?
+void config_tx_v2_cmd(op_config_tx_v2_t *p);
+void config_rx_v2_cmd(op_config_rx_v2_t *p);
+void start_rx_streaming_cmd(const u2_mac_addr_t *host, op_start_rx_streaming_t 
*p);
+void stop_rx_cmd(void);
+
+void handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len);
+
+#endif /* INCLUDED_APP_COMMON_H */

Modified: usrp2/trunk/firmware/apps/app_passthru.c
===================================================================
--- usrp2/trunk/firmware/apps/app_passthru.c    2008-05-12 05:32:16 UTC (rev 
8406)
+++ usrp2/trunk/firmware/apps/app_passthru.c    2008-05-12 05:47:50 UTC (rev 
8407)
@@ -74,7 +74,7 @@
        reply_len = 64;
       r->opcode = OP_ID_REPLY;
       r->len = sizeof(op_id_reply_t);
-      r->rid_mbz = 0;          // FIXME
+      r->rid = 0;              // FIXME
       r->addr = *ethernet_mac_addr();
       r->hw_rev = 0x0000;      // FIXME
       // r->fpga_md5sum = ;    // FIXME

Copied: usrp2/trunk/firmware/apps/rx_only_v2.c (from rev 8406, 
usrp2/branches/developers/eb/u2-newpktfmt/firmware/apps/rx_only_v2.c)
===================================================================
--- usrp2/trunk/firmware/apps/rx_only_v2.c                              (rev 0)
+++ usrp2/trunk/firmware/apps/rx_only_v2.c      2008-05-12 05:47:50 UTC (rev 
8407)
@@ -0,0 +1,300 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include "bool.h"
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "memcpy_wa.h"
+#include "dbsm.h"
+#include "app_common_v2.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <db.h>
+#include <db_base.h>
+
+
+#define FW_SETS_SEQNO  1       // define to 0 or 1
+
+#if (FW_SETS_SEQNO)
+static int fw_seqno;   // used when f/w is filling in sequence numbers
+#endif
+
+/*
+ * This program can respond to queries from the host
+ * and stream rx samples.
+ *
+ * Buffer 0 is used for rcvd frames from ethernet
+ * Buffer 1 is used by the cpu to send frames to the host.
+ * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow
+ */
+#define CPU_RX_BUF     0       // eth -> cpu
+//#define CPU_TX_BUF   1       // cpu -> eth
+#define        DSP_RX_BUF_0    2       // dsp rx -> eth (double buffer)
+#define        DSP_RX_BUF_1    3       // dsp rx -> eth
+
+
+// variables for streaming mode
+
+static bool     streaming_p = false;
+static int      streaming_frame_count = 0;
+#define FRAMES_PER_CMD 1000
+
+
+/*
+ * ================================================================
+ *      configure DSP RX double buffering state machine
+ * ================================================================
+ */
+
+// 4 lines of ethernet hdr + 1 line transport hdr + 1 line (word0)
+// DSP Rx writes timestamp followed by nlines_per_frame of samples
+#define DSP_RX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + 
sizeof(u2_transport_hdr_t))/4 + 1)
+
+// receive from DSP
+buf_cmd_args_t dsp_rx_recv_args = {
+  PORT_DSP,
+  DSP_RX_FIRST_LINE,
+  BP_LAST_LINE
+};
+
+// send to ETH
+buf_cmd_args_t dsp_rx_send_args = {
+  PORT_ETH,
+  0,           // starts with ethernet header in line 0
+  0,           // filled in from list_line register
+};
+
+dbsm_t dsp_rx_sm;      // the state machine
+
+// ----------------------------------------------------------------
+
+
+
+// The mac address of the host we're sending to.
+u2_mac_addr_t host_mac_addr;
+
+
+void link_changed_callback(int speed);
+static volatile bool link_is_up = false;       // eth handler sets this
+
+
+void 
+config_tx_v2_cmd(op_config_tx_v2_t *p)
+{
+  // FIXME nop
+}
+
+void
+config_rx_v2_cmd(op_config_rx_v2_t *p)
+{
+  struct tune_result   tune_result;
+  memset(&tune_result, 0, sizeof(tune_result));
+
+  bool ok = true;
+  
+  if (p->valid & CFGV_GAIN){
+    ok &= rx_dboard->set_gain(rx_dboard, p->gain);
+  }
+
+  if (p->valid & CFGV_FREQ){
+    u2_fxpt_freq_t f = u2_fxpt_freq_from_hilo(p->freq_hi, p->freq_lo);
+    bool tune_ok = db_tune(rx_dboard, f, &tune_result);
+    ok &= tune_ok;
+    print_tune_result("Rx", tune_ok, f, &tune_result);
+  }
+
+  if (p->valid & CFGV_INTERP_DECIM){
+    dsp_rx_regs->decim_rate = p->decim - 1;    // register gets N-1
+  }
+
+  if (p->valid & CFGV_SCALE_IQ){
+    dsp_rx_regs->scale_iq = p->scale_iq;
+  }
+
+  // FIXME build and send reply
+}
+
+
+void
+start_rx_streaming_cmd(const u2_mac_addr_t *host, op_start_rx_streaming_t *p)
+{
+  host_mac_addr = *host;       // remember who we're sending to
+
+  /*
+   * Construct  ethernet header and word0 and preload into two buffers
+   */
+  u2_eth_packet_t      pkt;
+  memset(&pkt, 0, sizeof(pkt));
+  pkt.ehdr.dst = *host;
+  pkt.ehdr.ethertype = U2_ETHERTYPE;
+  u2p_set_word0(&pkt.fixed, 0, 0);
+  // DSP RX will fill in timestamp
+
+  memcpy_wa(buffer_ram(DSP_RX_BUF_0), &pkt, sizeof(pkt));
+  memcpy_wa(buffer_ram(DSP_RX_BUF_1), &pkt, sizeof(pkt));
+
+
+  if (FW_SETS_SEQNO)
+    fw_seqno = 0;
+
+  // setup RX DSP regs
+  dsp_rx_regs->clear_state = 1;                        // reset
+
+  if (1){                      // we're streaming
+    streaming_p = true;
+    streaming_frame_count = FRAMES_PER_CMD;
+    dsp_rx_regs->rx_command =
+      MK_RX_CMD(FRAMES_PER_CMD * p->items_per_frame, p->items_per_frame,
+               1, 1);                  // set "chain" bit
+
+    // kick off the state machine
+    dbsm_start(&dsp_rx_sm);
+    dsp_rx_regs->rx_time = 0;          // enqueue first of two commands
+
+    // make sure this one and the rest have the "now" and "chain" bits set.
+    dsp_rx_regs->rx_command =
+      MK_RX_CMD(FRAMES_PER_CMD * p->items_per_frame, p->items_per_frame,
+               1, 1);                          
+    dsp_rx_regs->rx_time = 0;                  // enqueue second command
+  }
+#if 0
+  else {
+    streaming_p = false;
+    dsp_rx_regs->rx_command =
+      MK_RX_CMD(p->total_samples, p->items_per_frame, p->rx_now, 0);
+
+    // kick off the state machine
+    dbsm_start(&dsp_rx_sm);
+    dsp_rx_regs->rx_time = p->rx_time;
+  }
+#endif
+}
+
+
+void
+stop_rx_cmd(void)
+{
+  streaming_p = false;
+  dsp_rx_regs->clear_state = 1;        // flush cmd queue
+  bp_clear_buf(DSP_RX_BUF_0);
+  bp_clear_buf(DSP_RX_BUF_1);
+}
+
+inline static void
+buffer_irq_handler(unsigned irq)
+{
+  uint32_t  status = buffer_pool_status->status;
+
+  if (status & BPS_DONE(CPU_RX_BUF)){  // we've rcvd a frame from ethernet
+    bp_clear_buf(CPU_RX_BUF);
+    eth_pkt_inspector(0, CPU_RX_BUF);
+    bp_receive_to_buf(CPU_RX_BUF, PORT_ETH, 1, 0, BP_LAST_LINE);
+  }
+  if (status & BPS_ERROR(CPU_RX_BUF)){ // error from ethernet
+    bp_clear_buf(CPU_RX_BUF);
+    bp_receive_to_buf(CPU_RX_BUF, PORT_ETH, 1, 0, BP_LAST_LINE);
+  }
+
+  dbsm_process_status(&dsp_rx_sm, status);
+
+  if (status & BPS_DONE(CPU_TX_BUF)){
+    bp_clear_buf(CPU_TX_BUF);
+  }
+}
+
+#if (FW_SETS_SEQNO)
+/*
+ * Debugging ONLY.  This will be handled by the tx_protocol_engine.
+ *
+ * This is called when the DSP Rx chain has filled in a packet.
+ * We set and increment the seqno, then return false, indicating
+ * that we didn't handle the packet.  A bit of a kludge
+ * but it should work.
+ */
+bool 
+fw_sets_seqno_inspector(dbsm_t *sm, int buf_this)      // returns false
+{
+  uint32_t *p = buffer_ram(buf_this);
+  uint32_t seqno = fw_seqno++;
+
+  // KLUDGE all kinds of nasty magic numbers and embedded knowledge
+  uint32_t t = p[4];
+  t = (t & 0xffff00ff) | ((seqno & 0xff) << 8);
+  p[4] = t;
+
+  // queue up another rx command when required
+  if (streaming_p && --streaming_frame_count == 0){
+    streaming_frame_count = FRAMES_PER_CMD;
+    dsp_rx_regs->rx_time = 0;
+  }
+
+  return false;                // we didn't handle the packet
+}
+#endif
+
+
+int
+main(void)
+{
+  u2_init();
+
+  putstr("\nrx_only_v2\n");
+
+  ethernet_register_link_changed_callback(link_changed_callback);
+  ethernet_init();
+
+  // initialize double buffering state machine for DSP RX -> Ethernet
+
+  if (FW_SETS_SEQNO){
+    dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
+             &dsp_rx_recv_args, &dsp_rx_send_args,
+             fw_sets_seqno_inspector);
+  }
+  else {
+    dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
+             &dsp_rx_recv_args, &dsp_rx_send_args,
+             dbsm_nop_inspector);
+  }
+
+  // setup receive from ETH
+  bp_receive_to_buf(CPU_RX_BUF, PORT_ETH, 1, 0, BP_LAST_LINE);
+
+
+  while(1){
+    buffer_irq_handler(0);
+
+    int pending = pic_regs->pending;           // poll for under or overrun
+
+    if (pending & PIC_OVERRUN_INT){
+      dbsm_handle_rx_overrun(&dsp_rx_sm);
+      pic_regs->pending = PIC_OVERRUN_INT;     // clear pending interrupt
+      putchar('O');
+    }
+  }
+}

Copied: usrp2/trunk/firmware/apps/tx_only_v2.c (from rev 8406, 
usrp2/branches/developers/eb/u2-newpktfmt/firmware/apps/tx_only_v2.c)
===================================================================
--- usrp2/trunk/firmware/apps/tx_only_v2.c                              (rev 0)
+++ usrp2/trunk/firmware/apps/tx_only_v2.c      2008-05-12 05:47:50 UTC (rev 
8407)
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include "bool.h"
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "dbsm.h"
+#include "app_common_v2.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <db.h>
+#include <db_base.h>
+
+
+/*
+ * This program can respond to queries from the host
+ * and stream rx samples.
+ *
+ * Buffer 1 is used by the cpu to send frames to the host.
+ * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow
+ * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx  eth flow
+ */
+//#define CPU_RX_BUF   0       // eth -> cpu
+//#define CPU_TX_BUF   1       // cpu -> eth
+
+#define        DSP_RX_BUF_0    2       // dsp rx -> eth (double buffer)
+#define        DSP_RX_BUF_1    3       // dsp rx -> eth
+#define        DSP_TX_BUF_0    4       // eth -> dsp tx (double buffer)
+#define        DSP_TX_BUF_1    5       // eth -> dsp tx
+
+/*
+ * ================================================================
+ *      configure DSP TX double buffering state machine
+ * ================================================================
+ */
+
+// 4 lines of ethernet hdr + 1 line transport hdr + 2 lines (word0 + timestamp)
+// DSP Tx reads word0 (flags) + timestamp followed by samples
+
+#define DSP_TX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + 
sizeof(u2_transport_hdr_t))/4)
+
+// Receive from ethernet
+buf_cmd_args_t dsp_tx_recv_args = {
+  PORT_ETH,
+  0,
+  BP_LAST_LINE
+};
+
+// send to DSP Tx
+buf_cmd_args_t dsp_tx_send_args = {
+  PORT_DSP,
+  DSP_TX_FIRST_LINE,   // starts just past transport header
+  0                    // filled in from last_line register
+};
+
+dbsm_t dsp_tx_sm;      // the state machine
+
+
+// ----------------------------------------------------------------
+
+
+// The mac address of the host we're sending to.
+u2_mac_addr_t host_mac_addr;
+
+
+void 
+config_tx_v2_cmd(op_config_tx_v2_t *p)
+{
+  struct tune_result   tune_result;
+  memset(&tune_result, 0, sizeof(tune_result));
+
+  bool ok = true;
+  
+  if (p->valid & CFGV_GAIN){
+    ok &= tx_dboard->set_gain(tx_dboard, p->gain);
+  }
+
+  if (p->valid & CFGV_FREQ){
+    u2_fxpt_freq_t f = u2_fxpt_freq_from_hilo(p->freq_hi, p->freq_lo);
+    bool tune_ok = db_tune(tx_dboard, f, &tune_result);
+    ok &= tune_ok;
+    print_tune_result("Tx", tune_ok, f, &tune_result);
+  }
+
+  if (p->valid & CFGV_INTERP_DECIM){
+    dsp_tx_regs->interp_rate = p->interp - 1;  // register gets N-1
+  }
+
+  if (p->valid & CFGV_SCALE_IQ){
+    dsp_tx_regs->scale_iq = p->scale_iq;
+  }
+
+  // FIXME build and send reply
+}
+
+void 
+config_rx_v2_cmd(op_config_rx_v2_t *p)
+{
+  // FIXME nop
+}
+
+
+void
+start_rx_streaming_cmd(const u2_mac_addr_t *host, op_start_rx_streaming_t *p)
+{
+  // FIXME nop
+}
+
+
+void
+stop_rx_cmd(void)
+{
+  // FIXME nop
+}
+
+
+static void
+setup_tx()
+{
+  dsp_tx_regs->clear_state = 1;
+  bp_clear_buf(DSP_TX_BUF_0);
+  bp_clear_buf(DSP_TX_BUF_1);
+
+  int tx_scale = 256;
+  int interp = 32;
+
+  // setup some defaults
+
+  dsp_tx_regs->freq = 0;
+  dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale;
+  dsp_tx_regs->interp_rate = interp - 1;               // register gets N-1
+}
+
+
+inline static void
+buffer_irq_handler(unsigned irq)
+{
+  //hal_toggle_leds(0x2);
+
+  uint32_t  status = buffer_pool_status->status;
+
+  dbsm_process_status(&dsp_tx_sm, status);
+
+  if (status & BPS_DONE(CPU_TX_BUF)){
+    bp_clear_buf(CPU_TX_BUF);
+  }
+}
+
+int
+main(void)
+{
+  u2_init();
+
+  putstr("\ntx_only_v2\n");
+
+  ethernet_register_link_changed_callback(link_changed_callback);
+  ethernet_init();
+
+  // initialize double buffering state machine for ethernet -> DSP Tx
+
+  dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0,
+           &dsp_tx_recv_args, &dsp_tx_send_args,
+           eth_pkt_inspector);
+
+  // program tx registers
+  setup_tx();
+
+  // kick off the state machine
+  dbsm_start(&dsp_tx_sm);
+
+  while(1){
+    buffer_irq_handler(0);
+
+    int pending = pic_regs->pending;           // poll for under or overrun
+
+    if (pending & PIC_UNDERRUN_INT){
+      dbsm_handle_tx_underrun(&dsp_tx_sm);
+      pic_regs->pending = PIC_UNDERRUN_INT;    // clear interrupt
+      putchar('U');
+    }
+  }
+}

Copied: usrp2/trunk/firmware/apps/txrx.c (from rev 8406, 
usrp2/branches/developers/eb/u2-newpktfmt/firmware/apps/txrx.c)
===================================================================
--- usrp2/trunk/firmware/apps/txrx.c                            (rev 0)
+++ usrp2/trunk/firmware/apps/txrx.c    2008-05-12 05:47:50 UTC (rev 8407)
@@ -0,0 +1,383 @@
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include "bool.h"
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "dbsm.h"
+#include "app_common_v2.h"
+#include "memcpy_wa.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <db.h>
+#include <db_base.h>
+
+
+#define FW_SETS_SEQNO  1       // define to 0 or 1 (FIXME must be 1 for now)
+
+#if (FW_SETS_SEQNO)
+static int fw_seqno;   // used when f/w is filling in sequence numbers
+#endif
+
+
+/*
+ * Full duplex Tx and Rx between ethernet and DSP pipelines
+ *
+ * Buffer 1 is used by the cpu to send frames to the host.
+ * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow
+ * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx  eth flow
+ */
+//#define CPU_RX_BUF   0       // eth -> cpu
+
+#define        DSP_RX_BUF_0    2       // dsp rx -> eth (double buffer)
+#define        DSP_RX_BUF_1    3       // dsp rx -> eth
+#define        DSP_TX_BUF_0    4       // eth -> dsp tx (double buffer)
+#define        DSP_TX_BUF_1    5       // eth -> dsp tx
+
+/*
+ * ================================================================
+ *   configure DSP TX double buffering state machine (eth -> dsp)
+ * ================================================================
+ */
+
+// 4 lines of ethernet hdr + 1 line transport hdr + 2 lines (word0 + timestamp)
+// DSP Tx reads word0 (flags) + timestamp followed by samples
+
+#define DSP_TX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + 
sizeof(u2_transport_hdr_t))/4)
+
+// Receive from ethernet
+buf_cmd_args_t dsp_tx_recv_args = {
+  PORT_ETH,
+  0,
+  BP_LAST_LINE
+};
+
+// send to DSP Tx
+buf_cmd_args_t dsp_tx_send_args = {
+  PORT_DSP,
+  DSP_TX_FIRST_LINE,   // starts just past transport header
+  0                    // filled in from last_line register
+};
+
+dbsm_t dsp_tx_sm;      // the state machine
+
+/*
+ * ================================================================
+ *   configure DSP RX double buffering state machine (dsp -> eth)
+ * ================================================================
+ */
+
+// 4 lines of ethernet hdr + 1 line transport hdr + 1 line (word0)
+// DSP Rx writes timestamp followed by nlines_per_frame of samples
+#define DSP_RX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + 
sizeof(u2_transport_hdr_t))/4 + 1)
+
+// receive from DSP
+buf_cmd_args_t dsp_rx_recv_args = {
+  PORT_DSP,
+  DSP_RX_FIRST_LINE,
+  BP_LAST_LINE
+};
+
+// send to ETH
+buf_cmd_args_t dsp_rx_send_args = {
+  PORT_ETH,
+  0,           // starts with ethernet header in line 0
+  0,           // filled in from list_line register
+};
+
+dbsm_t dsp_rx_sm;      // the state machine
+
+
+// The mac address of the host we're sending to.
+u2_mac_addr_t host_mac_addr;
+
+
+// variables for streaming mode
+
+static bool     streaming_p = false;
+static int      streaming_frame_count = 0;
+#define FRAMES_PER_CMD 1000
+
+
+// ----------------------------------------------------------------
+
+
+
+void 
+config_tx_v2_cmd(op_config_tx_v2_t *p)
+{
+  struct tune_result   tune_result;
+  memset(&tune_result, 0, sizeof(tune_result));
+
+  bool ok = true;
+  
+  if (p->valid & CFGV_GAIN){
+    ok &= tx_dboard->set_gain(tx_dboard, p->gain);
+  }
+
+  if (p->valid & CFGV_FREQ){
+    u2_fxpt_freq_t f = u2_fxpt_freq_from_hilo(p->freq_hi, p->freq_lo);
+    bool tune_ok = db_tune(tx_dboard, f, &tune_result);
+    ok &= tune_ok;
+    print_tune_result("Tx", tune_ok, f, &tune_result);
+  }
+
+  if (p->valid & CFGV_INTERP_DECIM){
+    dsp_tx_regs->interp_rate = p->interp - 1;  // register gets N-1
+  }
+
+  if (p->valid & CFGV_SCALE_IQ){
+    dsp_tx_regs->scale_iq = p->scale_iq;
+  }
+
+  // FIXME build and send reply
+}
+
+void
+config_rx_v2_cmd(op_config_rx_v2_t *p)
+{
+  struct tune_result   tune_result;
+  memset(&tune_result, 0, sizeof(tune_result));
+
+  bool ok = true;
+  
+  if (p->valid & CFGV_GAIN){
+    ok &= rx_dboard->set_gain(rx_dboard, p->gain);
+  }
+
+  if (p->valid & CFGV_FREQ){
+    u2_fxpt_freq_t f = u2_fxpt_freq_from_hilo(p->freq_hi, p->freq_lo);
+    bool tune_ok = db_tune(rx_dboard, f, &tune_result);
+    ok &= tune_ok;
+    print_tune_result("Rx", tune_ok, f, &tune_result);
+  }
+
+  if (p->valid & CFGV_INTERP_DECIM){
+    dsp_rx_regs->decim_rate = p->decim - 1;    // register gets N-1
+  }
+
+  if (p->valid & CFGV_SCALE_IQ){
+    dsp_rx_regs->scale_iq = p->scale_iq;
+  }
+
+  // FIXME build and send reply
+}
+
+
+void
+start_rx_streaming_cmd(const u2_mac_addr_t *host, op_start_rx_streaming_t *p)
+{
+  host_mac_addr = *host;       // remember who we're sending to
+
+  /*
+   * Construct  ethernet header and word0 and preload into two buffers
+   */
+  u2_eth_packet_t      pkt;
+  memset(&pkt, 0, sizeof(pkt));
+  pkt.ehdr.dst = *host;
+  pkt.ehdr.ethertype = U2_ETHERTYPE;
+  u2p_set_word0(&pkt.fixed, 0, 0);
+  // DSP RX will fill in timestamp
+
+  memcpy_wa(buffer_ram(DSP_RX_BUF_0), &pkt, sizeof(pkt));
+  memcpy_wa(buffer_ram(DSP_RX_BUF_1), &pkt, sizeof(pkt));
+
+
+  if (FW_SETS_SEQNO)
+    fw_seqno = 0;
+
+  // setup RX DSP regs
+  dsp_rx_regs->clear_state = 1;                        // reset
+
+  if (1){                      // we're streaming
+    streaming_p = true;
+    streaming_frame_count = FRAMES_PER_CMD;
+    dsp_rx_regs->rx_command =
+      MK_RX_CMD(FRAMES_PER_CMD * p->items_per_frame, p->items_per_frame,
+               1, 1);                  // set "chain" bit
+
+    // kick off the state machine
+    dbsm_start(&dsp_rx_sm);
+    dsp_rx_regs->rx_time = 0;          // enqueue first of two commands
+
+    // make sure this one and the rest have the "now" and "chain" bits set.
+    dsp_rx_regs->rx_command =
+      MK_RX_CMD(FRAMES_PER_CMD * p->items_per_frame, p->items_per_frame,
+               1, 1);                          
+    dsp_rx_regs->rx_time = 0;          // enqueue second command
+  }
+#if 0
+  else {
+    streaming_p = false;
+    dsp_rx_regs->rx_command =
+      MK_RX_CMD(p->total_samples, p->items_per_frame, p->rx_now, 0);
+
+    // kick off the state machine
+    dbsm_start(&dsp_rx_sm);
+    dsp_rx_regs->rx_time = p->rx_time;
+  }
+#endif
+}
+
+
+void
+stop_rx_cmd(void)
+{
+  streaming_p = false;
+  dsp_rx_regs->clear_state = 1;        // flush cmd queue
+  bp_clear_buf(DSP_RX_BUF_0);
+  bp_clear_buf(DSP_RX_BUF_1);
+}
+
+
+static void
+setup_tx()
+{
+  dsp_tx_regs->clear_state = 1;
+  bp_clear_buf(DSP_TX_BUF_0);
+  bp_clear_buf(DSP_TX_BUF_1);
+
+  int tx_scale = 256;
+  int interp = 32;
+
+  // setup some defaults
+
+  dsp_tx_regs->freq = 0;
+  dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale;
+  dsp_tx_regs->interp_rate = interp - 1;               // register gets N-1
+}
+
+
+#if (FW_SETS_SEQNO)
+/*
+ * Debugging ONLY.  This will be handled by the tx_protocol_engine.
+ *
+ * This is called when the DSP Rx chain has filled in a packet.
+ * We set and increment the seqno, then return false, indicating
+ * that we didn't handle the packet.  A bit of a kludge
+ * but it should work.
+ */
+bool 
+fw_sets_seqno_inspector(dbsm_t *sm, int buf_this)      // returns false
+{
+  uint32_t *p = buffer_ram(buf_this);
+  uint32_t seqno = fw_seqno++;
+
+  // KLUDGE all kinds of nasty magic numbers and embedded knowledge
+  uint32_t t = p[4];
+  t = (t & 0xffff00ff) | ((seqno & 0xff) << 8);
+  p[4] = t;
+
+  // queue up another rx command when required
+  if (streaming_p && --streaming_frame_count == 0){
+    streaming_frame_count = FRAMES_PER_CMD;
+    dsp_rx_regs->rx_time = 0;
+  }
+
+  return false;                // we didn't handle the packet
+}
+#endif
+
+
+inline static void
+buffer_irq_handler(unsigned irq)
+{
+  //hal_toggle_leds(0x2);
+
+  uint32_t  status = buffer_pool_status->status;
+
+  dbsm_process_status(&dsp_tx_sm, status);
+  dbsm_process_status(&dsp_rx_sm, status);
+
+#if 0 // not needed, we busy wait in app_common_v2  
+  if (status & BPS_DONE(CPU_TX_BUF)){
+    bp_clear_buf(CPU_TX_BUF);
+  }
+#endif
+
+}
+
+int
+main(void)
+{
+  u2_init();
+
+  putstr("\nTxRx\n");
+
+  ethernet_register_link_changed_callback(link_changed_callback);
+  ethernet_init();
+
+  // initialize double buffering state machine for ethernet -> DSP Tx
+
+  dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0,
+           &dsp_tx_recv_args, &dsp_tx_send_args,
+           eth_pkt_inspector);
+
+
+  // initialize double buffering state machine for DSP RX -> Ethernet
+
+  if (FW_SETS_SEQNO){
+    dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
+             &dsp_rx_recv_args, &dsp_rx_send_args,
+             fw_sets_seqno_inspector);
+  }
+  else {
+    dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
+             &dsp_rx_recv_args, &dsp_rx_send_args,
+             dbsm_nop_inspector);
+  }
+
+  // tell app_common that this dbsm could be sending to the ethernet
+  ac_could_be_sending_to_eth = &dsp_rx_sm;
+
+
+  // program tx registers
+  setup_tx();
+
+  // kick off the state machine
+  dbsm_start(&dsp_tx_sm);
+
+  while(1){
+    buffer_irq_handler(0);
+
+    int pending = pic_regs->pending;           // poll for under or overrun
+
+    if (pending & PIC_UNDERRUN_INT){
+      dbsm_handle_tx_underrun(&dsp_tx_sm);
+      pic_regs->pending = PIC_UNDERRUN_INT;    // clear interrupt
+      putchar('U');
+    }
+
+    if (pending & PIC_OVERRUN_INT){
+      dbsm_handle_rx_overrun(&dsp_rx_sm);
+      pic_regs->pending = PIC_OVERRUN_INT;     // clear pending interrupt
+      putchar('O');
+    }
+  }
+}

Modified: usrp2/trunk/firmware/include/usrp2_eth_packet.h
===================================================================
--- usrp2/trunk/firmware/include/usrp2_eth_packet.h     2008-05-12 05:32:16 UTC 
(rev 8406)
+++ usrp2/trunk/firmware/include/usrp2_eth_packet.h     2008-05-12 05:47:50 UTC 
(rev 8407)
@@ -77,6 +77,8 @@
  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *  |                           Timestamp                           |
  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ *  mbz == must be zero
  */
 
 typedef struct {
@@ -138,11 +140,12 @@
 
 /*
  * full load of samples:
- *   ethernet header + pad + fixed header + maximum number of samples.
- *   sizeof(u2_eth_samples_t) == 2048
+ *   ethernet header + transport header + fixed header + maximum number of 
samples.
+ *   sizeof(u2_eth_samples_t) == 1512
+ *   (payload is 1498 bytes, two bytes shorter than 1500 byte MTU)
  */
 
-#define U2_MAX_SAMPLES 505
+#define U2_MAX_SAMPLES 371
 
 typedef struct {
   u2_eth_packet_t      hdrs;
@@ -152,39 +155,55 @@
 /*
  * Opcodes for control channel
  */
-#define        OP_EOF                  0       // marks last subpacket in 
packet
+#define        OP_EOP                  0       // marks last subpacket in 
packet
 #define OP_ID                  1
 #define        OP_ID_REPLY             2
-#define        OP_START_RX             3
-#define        OP_STOP_RX              4
-#define        OP_WRITE_REG            5
-#define        OP_WRITE_REG_MASKED     6
-#define        OP_READ_REG             7
-#define        OP_READ_REG_REPLY       8
-#define        OP_BURN_MAC_ADDR        9
-#define OP_CONFIG_TX          10
-#define        OP_READ_TIME           11       // What time is it? (100 MHz 
counter)
-#define        OP_READ_TIME_REPLY     12       // This time.
-#define        OP_CONFIG_RX_V2        13
-#define        OP_CONFIG_TX_V2        14
+#define        OP_BURN_MAC_ADDR        3
+#define        OP_READ_TIME            4       // What time is it? (100 MHz 
counter)
+#define        OP_READ_TIME_REPLY      5       // This time.
+#define        OP_CONFIG_RX_V2         6
+#define        OP_CONFIG_RX_REPLY_V2   7
+#define        OP_CONFIG_TX_V2         8
+#define        OP_CONFIG_TX_REPLY_V2   9
+#define        OP_START_RX_STREAMING  10
+#define        OP_STOP_RX             11
 
+#define        OP_START_RX            20       // deprecated
+#define OP_CONFIG_TX          21       // deprecated
 
+#define        OP_WRITE_REG           25       // not implemented
+#define        OP_WRITE_REG_MASKED    26
+#define        OP_READ_REG            27
+#define        OP_READ_REG_REPLY      28
+
+
+/*!
+ * \brief Marker for last subpacket in packet
+ */
 typedef struct {
   uint8_t      opcode;
   uint8_t      len;
   uint16_t     mbz;
-} op_eof_t;
+} op_eop_t;
 
+/*!
+ * \brief Look for USRP2's
+ */
 typedef struct {
   uint8_t      opcode;
   uint8_t      len;
-  uint16_t     rid_mbz;
+  uint8_t      rid;
+  uint8_t      mbz;
 } op_id_t;
 
+/*!
+ * \brief Reply info from a USRP2
+ */
 typedef struct {
   uint8_t      opcode;
   uint8_t      len;
-  uint16_t     rid_mbz;
+  uint8_t      rid;
+  uint8_t      mbz;
   u2_mac_addr_t        addr;
   uint16_t     hw_rev;
   uint8_t      fpga_md5sum[16];
@@ -194,15 +213,9 @@
 typedef struct {
   uint8_t      opcode;
   uint8_t      len;
-  uint8_t      rx_now;             // 1 -> receive now, 0 -> at rx_time
-  uint8_t      mbz;
-  int32_t      phase_inc;          // 2**32 * desired_freq/100e6
-  uint32_t     scale_iq;           // (scale_i << 16) | scale_q  [16.0 format]
-  uint32_t     decim;              // desired decimation factor (NOT -1)
-  uint32_t     samples_per_frame;  // MTU=1500: [9,372]; MTU=2034: [9,506]
-  uint32_t     total_samples;      // [9, 2^21-1] == [9, 2,097,151]
-  uint32_t     rx_time;            // when to begin receiving
-} op_start_rx_t;
+  uint16_t     mbz;
+  uint32_t     items_per_frame;  // # of 32-bit data items; MTU=1500: [9,371]
+} op_start_rx_streaming_t;
 
 typedef struct {
   uint8_t      opcode;
@@ -213,45 +226,39 @@
 typedef struct {
   uint8_t      opcode;
   uint8_t      len;
-  uint16_t     mbz;
-  int32_t      phase_inc;          // 2**32 * desired_freq/100e6
-  uint32_t     scale_iq;           // (scale_i << 16) | scale_q  [16.0 format]
-  uint32_t     interp;             // desired interpolation factor (NOT -1)
-} op_config_tx_t;
-
-typedef struct {
-  uint8_t      opcode;
-  uint8_t      len;
   u2_mac_addr_t        addr;
 } op_burn_mac_addr_t;
 
 typedef struct {
   uint8_t      opcode;
   uint8_t      len;
-  uint16_t     rid_mbz;
+  uint8_t      rid;
+  uint8_t      mbz;
 } op_read_time_t;
 
 typedef struct {
   uint8_t      opcode;
   uint8_t      len;
-  uint16_t     rid_mbz;
+  uint8_t      rid;
+  uint8_t      mbz;
   uint32_t     time;
 } op_read_time_reply_t;
 
 
-/*
- * Configure the receiver.
+/*!
+ * \brief Configure receiver
  */
 typedef struct {
   uint8_t      opcode;
   uint8_t      len;
-  uint16_t     rid_mbz;
+  uint8_t      rid;
+  uint8_t      mbz;
   // bitmask indicating which of the following fields are valid
   uint16_t     valid;
   uint16_t     gain;           // fxpt_db (Q9.7)
-  uint32_t     target_freq_hi; // high 32-bits of 64-bit fxpt_freq (Q44.20)
-  uint32_t     target_freq_lo; // low  32-bits of 64-bit fxpt_freq (Q44.20)
-  uint32_t     interp;         // desired interpolation factor (NOT -1)
+  uint32_t     freq_hi;        // high 32-bits of 64-bit fxpt_freq (Q44.20)
+  uint32_t     freq_lo;        // low  32-bits of 64-bit fxpt_freq (Q44.20)
+  uint32_t     decim;          // desired decimation factor (NOT -1)
   uint32_t     scale_iq;       // (scale_i << 16) | scale_q [16.0 format]
 } op_config_rx_v2_t;
 
@@ -263,13 +270,14 @@
 #define        CFGV_INTERP_DECIM       0x0004  // interp or decim is valid
 #define        CFGV_SCALE_IQ           0x0008  // scale_iq is valid
 
-/*
- * Reply to receiver configuration
+/*!
+ * \brief Reply to receiver configuration
  */
 typedef struct {
   uint8_t      opcode;
   uint8_t      len;
-  uint16_t     rid_mbz;
+  uint8_t      rid;
+  uint8_t      mbz;
 
   uint16_t     ok;             // config was successful (bool)
   uint16_t     inverted;       // spectrum is inverted (bool)
@@ -284,37 +292,101 @@
   uint32_t     residual_freq_hi;
   uint32_t     residual_freq_lo;
 
-} op_config_rx_v2_reply_t;
+} op_config_rx_reply_v2_t;
 
+/*!
+ *  \brief Configure transmitter
+ */
 typedef struct {
   uint8_t      opcode;
   uint8_t      len;
-  uint16_t     rid_mbz;
+  uint8_t      rid;
+  uint8_t      mbz;
+
   // bitmask indicating which of the following fields are valid
   uint16_t     valid;
   uint16_t     gain;           // fxpt_db (Q9.7)
   uint32_t     freq_hi;        // high 32-bits of 64-bit fxpt_freq (Q44.20)
   uint32_t     freq_lo;        // low  32-bits of 64-bit fxpt_freq (Q44.20)
-  uint32_t     decim;          // desired decimation factor (NOT -1)
+  uint32_t     interp;         // desired interpolation factor (NOT -1)
   uint32_t     scale_iq;       // (scale_i << 16) | scale_q [16.0 format]
 } op_config_tx_v2_t;
 
+/*!
+ * \brief Reply to configure transmitter
+ */
+typedef struct {
+  uint8_t      opcode;
+  uint8_t      len;
+  uint8_t      rid;
+  uint8_t      mbz;
 
+  uint16_t     ok;             // config was successful (bool)
+  uint16_t     inverted;       // spectrum is inverted (bool)
 
-// union of all of them
+  // RF frequency that corresponds to DC in the IF (fxpt_freq)
+  uint32_t     baseband_freq_hi;
+  uint32_t     baseband_freq_lo;
+  // DUC frequency (fxpt_freq)
+  uint32_t     ddc_freq_hi;
+  uint32_t     ddc_freq_lo;
+  // residual frequency (fxpt_freq)
+  uint32_t     residual_freq_hi;
+  uint32_t     residual_freq_lo;
 
+} op_config_tx_reply_v2_t;
+
+
+/*
+ * ================================================================
+ *                 deprecated subpacket types
+ * ================================================================
+ */
+
+typedef struct {                   // Deprecated.  Don't use.
+  uint8_t      opcode;
+  uint8_t      len;
+  uint8_t      rx_now;             // 1 -> receive now, 0 -> at rx_time
+  uint8_t      mbz;
+  int32_t      phase_inc;          // 2**32 * desired_freq/100e6
+  uint32_t     scale_iq;           // (scale_i << 16) | scale_q  [16.0 format]
+  uint32_t     decim;              // desired decimation factor (NOT -1)
+  uint32_t     samples_per_frame;  // MTU=1500: [9,372]; MTU=2034: [9,506]
+  uint32_t     total_samples;      // [9, 2^21-1] == [9, 2,097,151]
+  uint32_t     rx_time;            // when to begin receiving
+} op_start_rx_t;
+
+typedef struct {                   // Deprecated.  Don't use
+  uint8_t      opcode;
+  uint8_t      len;
+  uint16_t     mbz;
+  int32_t      phase_inc;          // 2**32 * desired_freq/100e6
+  uint32_t     scale_iq;           // (scale_i << 16) | scale_q  [16.0 format]
+  uint32_t     interp;             // desired interpolation factor (NOT -1)
+} op_config_tx_t;
+
+/*
+ * ================================================================
+ *             union of all of subpacket types
+ * ================================================================
+ */
 typedef union {
-  op_eof_t             op_eof;
-  op_id_t              op_id;
-  op_id_reply_t                op_id_reply;
-  op_start_rx_t                op_start_rx;
-  op_stop_rx_t         op_stop_rx;
-  op_config_tx_t       op_config_tx;
-  op_burn_mac_addr_t   op_burn_mac_addr;
-  op_read_time_t       op_read_time;
-  op_read_time_reply_t op_read_time_reply;
-  op_config_rx_v2_t    op_config_rx_v2;
-  op_config_tx_v2_t    op_config_tx_v2;
+  op_eop_t                     op_eop;
+  op_id_t                      op_id;
+  op_id_reply_t                        op_id_reply;
+  op_start_rx_streaming_t      op_start_rx_streaming;
+  op_stop_rx_t                 op_stop_rx;
+  op_burn_mac_addr_t           op_burn_mac_addr;
+  op_read_time_t               op_read_time;
+  op_read_time_reply_t         op_read_time_reply;
+  op_config_rx_v2_t            op_config_rx_v2;
+  op_config_rx_reply_v2_t      op_config_rx_reply_v2;
+  op_config_tx_v2_t            op_config_tx_v2;
+  op_config_tx_reply_v2_t      op_config_tx_reply_v2;
+
+  op_start_rx_t                        op_start_rx;            // deprecated
+  op_config_tx_t               op_config_tx;           // deprecated
+
 } u2_subpkt_t;
 
 

Modified: usrp2/trunk/firmware/include/usrp2_types.h
===================================================================
--- usrp2/trunk/firmware/include/usrp2_types.h  2008-05-12 05:32:16 UTC (rev 
8406)
+++ usrp2/trunk/firmware/include/usrp2_types.h  2008-05-12 05:47:50 UTC (rev 
8407)
@@ -33,8 +33,10 @@
  */
 typedef int64_t        u2_fxpt_freq_t;
 
+#define U2_FPF_RP      20      // location of radix point in u2_fxpt_freq_t
+
 // macro so we can init structs at compile time
-#define U2_DOUBLE_TO_FXPT_FREQ(f) (int64_t)((f) * (1 << 20))
+#define U2_DOUBLE_TO_FXPT_FREQ(f) (int64_t)((f) * (1LL << U2_FPF_RP))
 
 static inline u2_fxpt_freq_t
 u2_double_to_fxpt_freq(double f)
@@ -45,16 +47,33 @@
 static inline int
 u2_fxpt_freq_round_to_int(u2_fxpt_freq_t fx)
 {
-  return (int)((fx+(1<<19))>>20);
+  return (int)((fx+(1<<(U2_FPF_RP-1)))>>U2_FPF_RP);
 }
 
 static inline double
 u2_fxpt_freq_to_double(u2_fxpt_freq_t fx)
 {
-  return ((double) fx) * 1.0/(1 << 20);
+  return ((double) fx) * 1.0/(1 << U2_FPF_RP);
 }
 
+static inline uint32_t
+u2_fxpt_freq_hi(u2_fxpt_freq_t f)
+{
+  return ((f >> 32) & 0xffffffff);
+}
 
+static inline uint32_t
+u2_fxpt_freq_lo(u2_fxpt_freq_t f)
+{
+  return (f & 0xffffffff);
+}
+
+static inline u2_fxpt_freq_t
+u2_fxpt_freq_from_hilo(uint32_t hi, uint32_t lo)
+{
+  return (((u2_fxpt_freq_t) hi) << 32) | lo;
+}
+
 /*!
  * \brief Fixed point representation of a gain in dB (VITA-49 compatible)
  *
@@ -63,8 +82,10 @@
  */
 typedef int16_t u2_fxpt_gain_t;
 
+#define U2_FPG_RP      7       // location of radix point in u2_fxpt_gain_t
+
 // macro so we can init structs at compile time
-#define U2_DOUBLE_TO_FXPT_GAIN(g) (int16_t)((g) * (1 << 7))
+#define U2_DOUBLE_TO_FXPT_GAIN(g) (int16_t)((g) * (1 << U2_FPG_RP))
 
 static inline u2_fxpt_gain_t
 u2_double_to_fxpt_gain(double g)
@@ -75,7 +96,7 @@
 static inline float
 u2_fxpt_gain_to_double(u2_fxpt_gain_t fx)
 {
-  return ((double) fx) * 1.0/(1 << 7);
+  return ((double) fx) * 1.0/(1 << U2_FPG_RP);
 }
 
 

Modified: usrp2/trunk/firmware/lib/db_basic.c
===================================================================
--- usrp2/trunk/firmware/lib/db_basic.c 2008-05-12 05:32:16 UTC (rev 8406)
+++ usrp2/trunk/firmware/lib/db_basic.c 2008-05-12 05:47:50 UTC (rev 8407)
@@ -31,6 +31,7 @@
 
 struct db_basic db_basic_tx = {
   .base.dbid = 0x0000,
+  .base.is_tx = true,
   .base.output_enables = 0x0000,
   .base.used_pins = 0x0000,
   .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(-90e9),
@@ -57,6 +58,7 @@
 
 struct db_basic db_basic_rx = {
   .base.dbid = 0x0001,
+  .base.is_tx = false,
   .base.output_enables = 0x0000,
   .base.used_pins = 0x0000,
   .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(-90e9),
@@ -83,6 +85,7 @@
 
 struct db_basic db_lf_tx = {
   .base.dbid = 0x000e,
+  .base.is_tx = true,
   .base.output_enables = 0x0000,
   .base.used_pins = 0x0000,
   .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(-32e6),
@@ -109,6 +112,7 @@
 
 struct db_basic db_lf_rx = {
   .base.dbid = 0x000f,
+  .base.is_tx = false,
   .base.output_enables = 0x0000,
   .base.used_pins = 0x0000,
   .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(0),

Modified: usrp2/trunk/firmware/lib/db_init.c
===================================================================
--- usrp2/trunk/firmware/lib/db_init.c  2008-05-12 05:32:16 UTC (rev 8406)
+++ usrp2/trunk/firmware/lib/db_init.c  2008-05-12 05:47:50 UTC (rev 8407)
@@ -211,13 +211,14 @@
   printf("  baseband = "); print_fxpt_freq(baseband_freq); newline();
   printf("  delta    = "); print_fxpt_freq(delta); newline();
   
+#if 0
   printf("--- printed as uint64_t ---\n");
   printf("  fs       = "); print_uint64(fs); newline();
   printf("  target   = "); print_uint64(target_freq); newline();
   printf("  baseband = "); print_uint64(baseband_freq); newline();
   printf("  delta    = "); print_uint64(delta); newline();
+#endif
 
-
   if (delta >= 0){
     while (delta > fs)
       delta -= fs;

Modified: usrp2/trunk/firmware/lib/dbsm.c
===================================================================
--- usrp2/trunk/firmware/lib/dbsm.c     2008-05-12 05:32:16 UTC (rev 8406)
+++ usrp2/trunk/firmware/lib/dbsm.c     2008-05-12 05:47:50 UTC (rev 8407)
@@ -278,3 +278,20 @@
 
   putchar('O');
 }
+
+void 
+dbsm_wait_for_opening(dbsm_t *sm)
+{
+  if (buffer_state[sm->buf0] == BS_EMPTYING){
+    // wait for xfer to complete
+    int mask = BPS_DONE(sm->buf0) | BPS_ERROR(sm->buf0);
+    while ((buffer_pool_status->status & mask) == 0)
+      ;
+  }
+  else if (buffer_state[sm->buf0 ^ 1] == BS_EMPTYING){
+    // wait for xfer to complete
+    int mask = BPS_DONE(sm->buf0 ^ 1) | BPS_ERROR(sm->buf0 ^ 1);
+    while ((buffer_pool_status->status & mask) == 0)
+      ;
+  }
+}

Modified: usrp2/trunk/firmware/lib/dbsm.h
===================================================================
--- usrp2/trunk/firmware/lib/dbsm.h     2008-05-12 05:32:16 UTC (rev 8406)
+++ usrp2/trunk/firmware/lib/dbsm.h     2008-05-12 05:47:50 UTC (rev 8407)
@@ -74,4 +74,17 @@
 void dbsm_handle_tx_underrun(dbsm_t *sm);
 void dbsm_handle_rx_overrun(dbsm_t *sm);
 
+/*
+ * The cpu calls this when it want to ensure that it can send a buffer
+ * to the same destination being used by this state machine.
+ *
+ * If neither buffer is EMPTYING it returns immediately.  If a buffer
+ * is EMPYTING, it waits for the h/w to transition to the DONE or
+ * ERROR state.
+ *
+ * When this function returns, the caller queues it's buffer and busy
+ * waits for it to complete.
+ */
+void dbsm_wait_for_opening(dbsm_t *sm);
+
 #endif /* INCLUDED_DBSM_H */

Modified: usrp2/trunk/host/apps/Makefile.am
===================================================================
--- usrp2/trunk/host/apps/Makefile.am   2008-05-12 05:32:16 UTC (rev 8406)
+++ usrp2/trunk/host/apps/Makefile.am   2008-05-12 05:47:50 UTC (rev 8407)
@@ -25,18 +25,16 @@
 
 bin_PROGRAMS = \
        find_usrps \
-       rx_samples \
        rx_streaming_samples \
        tx_samples \
-       tx_samples_at_t \
        gen_const \
        u2_burn_mac_addr
 
 find_usrps_SOURCES = find_usrps.cc
-rx_samples_SOURCES = rx_samples.cc
+# rx_samples_SOURCES = rx_samples.cc
 rx_streaming_samples_SOURCES = rx_streaming_samples.cc
 tx_samples_SOURCES = tx_samples.cc
-tx_samples_at_t = tx_samples_at_t.cc
+# tx_samples_at_t = tx_samples_at_t.cc
 gen_const_SOURCES = gen_const.cc
 u2_burn_mac_addr = u2_burn_mac_addr.cc
 

Copied: usrp2/trunk/host/apps/rx_samples_at_t.cc (from rev 7964, 
usrp2/trunk/host/apps/rx_samples.cc)
===================================================================
--- usrp2/trunk/host/apps/rx_samples_at_t.cc                            (rev 0)
+++ usrp2/trunk/host/apps/rx_samples_at_t.cc    2008-05-12 05:47:50 UTC (rev 
8407)
@@ -0,0 +1,378 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "usrp2_basic.h"
+#include <iostream>
+#include <complex>
+#include <getopt.h>
+#include <string.h>
+#include "strtod_si.h"
+#include <signal.h>
+#include <stdexcept>
+#include "gri_if_stats.h"
+#include <gr_realtime.h>
+
+
+typedef std::complex<float> fcomplex;
+
+static volatile bool signaled = false;
+
+static void 
+sig_handler(int sig)
+{
+  signaled = true;
+}
+
+static void
+install_sig_handler(int signum,
+                   void (*new_handler)(int))
+{
+  struct sigaction new_action;
+  memset (&new_action, 0, sizeof (new_action));
+
+  new_action.sa_handler = new_handler;
+  sigemptyset (&new_action.sa_mask);
+  new_action.sa_flags = 0;
+
+  if (sigaction (signum, &new_action, 0) < 0){
+    perror ("sigaction (install new)");
+    throw std::runtime_error ("sigaction");
+  }
+}
+
+
+/*
+ * Vectorize me!
+ */
+void
+convert_samples_to_complex(size_t nsamples,
+                          uint32_t *i_samples,
+                          fcomplex *c_samples)
+{
+  uint32_t *p = i_samples;
+  for (size_t i = 0; i < nsamples; i++){
+    int16_t  si = ((int16_t) (p[i] >> 16));
+    int16_t  sq = ((int16_t) (p[i] & 0xffff));
+    c_samples[i] = fcomplex((float) si, (float) sq);
+  }
+}
+
+
+static void
+usage(const char *progname)
+{
+  const char *p = strrchr(progname, '/');      // drop leading directory path
+  if (p)
+    p++;
+
+  if (strncmp(p, "lt-", 3) == 0)               // drop lt- libtool prefix
+    p += 3;
+  
+  fprintf(stderr, "Usage: %s [options]\n\n", p);
+  fprintf(stderr, "Options:\n");
+  fprintf(stderr, "  -h                   show this message and exit\n");
+  fprintf(stderr, "  -e ETH_INTERFACE     specify ethernet interface 
[default=eth0]\n");
+  fprintf(stderr, "  -m MAC_ADDR          mac address of USRP2 HH:HH 
[default=first one found]\n");
+  fprintf(stderr, "  -o OUTPUT_FILE       set output filename 
[default=NONE]\n");
+  fprintf(stderr, "  -f FREQ              set frequency to FREQ 
[default=0]\n");
+  fprintf(stderr, "  -d DECIM             set decimation rate to DECIM 
[default=32]\n");
+  fprintf(stderr, "  -N NSAMPLES          total number of samples to receive 
[default=2.5e6]\n");
+  fprintf(stderr, "  -F SAMPLES_PER_FRAME number of samples in each frame 
[default=371]\n");
+  fprintf(stderr, "  -S SCALE             fpga scaling factor for I & Q 
[default=256]\n");
+  fprintf(stderr, "  -O ON_TIME           number of samples to capture 
[default=750k]\n");
+  fprintf(stderr, "  -F OFF_TIME          number of samples to ignore 
[default=250k]\n");
+}
+
+struct pkt_info {
+  int          d_nsamples;
+  int          d_timestamp;
+  unsigned int d_seqno;
+
+  pkt_info(int nsamples, int timestamp, int seqno)
+    : d_nsamples(nsamples),
+      d_timestamp(timestamp),
+      d_seqno(seqno) {}
+};
+
+int
+main(int argc, char **argv)
+{
+
+  // options and their defaults
+  const char *interface = "eth0";
+  const char *mac_addr_str = 0;
+  const char *output_filename = 0;
+  double freq = 0;
+  int32_t decim = 32;
+  int32_t nsamples = static_cast<int32_t>(2.5e6);
+  int32_t samples_per_frame = 371;
+  int32_t scale = 1024;
+  int32_t t_on_in_samples = static_cast<int32_t>(750e3);
+  int32_t t_off_in_samples = static_cast<int32_t>(250e3);
+
+  int    ch;
+  double tmp;
+  u2_mac_addr_t mac_addr;
+
+  setvbuf(stdout, 0, _IOFBF, 64 * 1024); // make stdout fully buffered
+
+  while ((ch = getopt(argc, argv, "he:m:o:f:d:N:F:S:O:F:")) != EOF){
+    switch (ch){
+
+    case 'e':
+      interface = optarg;
+      break;
+      
+    case 'm':
+      mac_addr_str = optarg;
+      if (!usrp2_basic::parse_mac_addr(optarg, &mac_addr)){
+       std::cerr << "invalid mac addr: " << optarg << std::endl;
+       usage(argv[0]);
+       exit(1);
+      }
+      break;
+
+    case 'o':
+      output_filename = optarg;
+      break;
+      
+    case 'f':
+      if (!strtod_si(optarg, &freq)){
+       std::cerr << "invalid number: " << optarg << std::endl;
+       usage(argv[0]);
+       exit(1);
+      }
+      break;
+
+    case 'N':
+      if (!strtod_si(optarg, &tmp)){
+       std::cerr << "invalid number: " << optarg << std::endl;
+       usage(argv[0]);
+       exit(1);
+      }
+      nsamples = static_cast<int32_t>(tmp);
+      break;
+
+    case 'F':
+      samples_per_frame = strtol(optarg, 0, 0);
+      break;
+
+    case 'd':
+      decim = strtol(optarg, 0, 0);
+      break;
+
+    case 'S':
+      if (!strtod_si(optarg, &tmp)){
+       std::cerr << "invalid number: " << optarg << std::endl;
+       usage(argv[0]);
+       exit(1);
+      }
+      scale = static_cast<int32_t>(tmp);
+      break;
+      
+    case 'O':
+      if (!strtod_si(optarg, &tmp)){
+       std::cerr << "invalid number: " << optarg << std::endl;
+       usage(argv[0]);
+       exit(1);
+      }
+      t_on_in_samples = static_cast<int32_t>(tmp);
+      break;
+
+    case 'F':
+      if (!strtod_si(optarg, &tmp)){
+       std::cerr << "invalid number: " << optarg << std::endl;
+       usage(argv[0]);
+       exit(1);
+      }
+      t_off_in_samples = static_cast<int32_t>(tmp);
+      break;
+
+    case 'h':
+    default:
+      usage(argv[0]);
+      exit(1);
+    }
+  }
+  
+  if (argc - optind != 0){
+    usage(argv[0]);
+    exit(1);
+  }
+
+  FILE *of = 0;
+  if (output_filename)
+    of = fopen(output_filename, "wb");
+
+  usrp2_basic *u2 = new usrp2_basic();
+
+  if (!u2->open(interface)){
+    std::cerr << "couldn't open " << interface << std::endl;
+    return 0;
+  }
+
+
+  install_sig_handler(SIGINT, sig_handler);
+  if (1){
+    install_sig_handler(SIGALRM, sig_handler);
+    alarm(5);
+  }
+
+  
+  std::vector<op_id_reply_t> r = u2->find_usrps();
+
+  for (size_t i = 0; i < r.size(); i++){
+    std::cout << r[i] << std::endl;
+  }
+
+  if (r.size() == 0){
+    std::cerr << "No USRP2 found.\n";
+    return 1;
+  }
+
+  u2_mac_addr_t which = r[0].addr;     // pick the first one
+
+
+  gr_rt_status_t rt = gr_enable_realtime_scheduling();
+  if (rt != RT_OK)
+    std::cerr << "failed to enable realtime scheduling\n";
+
+
+  gri_if_stats start, stop;
+  gri_get_if_stats(interface, &start);
+
+  if (!u2->start_rx(which, freq, decim, nsamples, samples_per_frame, scale, 
scale)){
+    std::cerr << "start_rx failed\n";
+    return 1;
+  }
+
+
+  std::vector<pkt_info> history;
+  history.reserve(64*1024);            // preallocate 64K entries
+
+  
+  long total_samples_recvd = 0;
+
+  while (!signaled && total_samples_recvd < nsamples){
+    u2_eth_samples_t   pkt;
+    // fcomplex                c_samples[U2_MAX_SAMPLES];
+    
+    // read samples
+    int n = u2->read_samples(which, &pkt);
+    if (n <= 0)
+      break;
+    
+    total_samples_recvd += n;
+
+    history.push_back(pkt_info(n, u2p_timestamp(&pkt.hdrs.fixed), 
pkt.hdrs.thdr.seqno));
+
+    // convert_samples_to_complex(n, pkt.samples, c_samples);
+    // size_t r = fwrite(c_samples, sizeof(fcomplex), n, of);
+
+    if (of){
+      fwrite(pkt.samples, sizeof(uint32_t), n, of);
+      fflush(of);
+    }
+  }
+
+
+  gri_get_if_stats(interface, &stop);
+
+  if (!u2->stop_rx(which)){
+    std::cerr << "stop_rx failed\n";
+    return 1;
+  }
+
+
+  long expected_rx_packets =
+    (nsamples + samples_per_frame - 1)/samples_per_frame;
+
+  long expected_rx_bytes   =
+    expected_rx_packets * sizeof(u2_eth_packet_t) + nsamples * 4;
+
+
+  long total_pkts_recvd = 0;
+  total_samples_recvd = 0;
+
+  int nbad_seqno = 0;
+
+  for (unsigned i = 0; i < history.size(); i++){
+    total_pkts_recvd++;
+    total_samples_recvd += history[i].d_nsamples;
+
+    bool bad_seqno = history[i].d_seqno != (i & 0xff);
+    if (bad_seqno)
+      nbad_seqno++;
+    
+    printf("%3d  %8d  %8ld  %8ld  %3d %s\n",
+          history[i].d_nsamples,
+          history[i].d_timestamp,
+          total_pkts_recvd, total_samples_recvd,
+          history[i].d_seqno,
+          bad_seqno ? "BAD SEQNO" : ""
+          );
+  }
+
+  if (nbad_seqno == 0)
+    printf("\nAll sequence numbers are correct\n");
+  else
+    printf("\n%d sequence numbers were INCORRECT\n", nbad_seqno);
+    
+
+  printf("\nUser space statistics:\n");
+  printf("  rx_samples:  %8ld",     total_samples_recvd);
+  printf("   expected  %8d  %s\n",
+        nsamples,
+        nsamples - total_samples_recvd == 0 ? "OK" : "NOT OK");
+  
+  printf("  rx_packets:  %8ld",     total_pkts_recvd);
+  printf("   expected  %8ld  %s\n",
+        expected_rx_packets,
+        expected_rx_packets - total_pkts_recvd == 0 ? "OK" : "NOT OK");
+  
+
+  fflush(stdout);
+
+  printf("\nKernel interface statistics:\n");
+
+  long long delta;
+  delta = stop.rx_bytes - start.rx_bytes;
+  printf("  rx_bytes:    %8Ld",     delta);
+  printf("   expected  %8ld  %s\n",
+        expected_rx_bytes,
+        expected_rx_bytes - delta == 0 ? "OK" : "NOT OK");
+
+  delta = stop.rx_packets - start.rx_packets;
+  printf("  rx_packets:  %8Ld",     delta);
+  printf("   expected  %8ld  %s\n",
+        expected_rx_packets,
+        expected_rx_packets - delta == 0 ? "OK" : "NOT OK");
+
+  printf("  rx_errs:     %8Ld\n",   stop.rx_errs - start.rx_errs);
+  printf("  rx_drop:     %8Ld\n",   stop.rx_drop - start.rx_drop);
+  printf("  tx_bytes:    %8Ld\n",   stop.tx_bytes - start.tx_bytes);
+  printf("  tx_packets:  %8Ld\n",   stop.tx_packets - start.tx_packets);
+  printf("  tx_errs:     %8Ld\n",   stop.tx_errs - start.tx_errs);
+  printf("  tx_drop:     %8Ld\n",   stop.tx_drop - start.tx_drop);
+
+
+  return 0;
+}

Modified: usrp2/trunk/host/apps/rx_streaming_samples.cc
===================================================================
--- usrp2/trunk/host/apps/rx_streaming_samples.cc       2008-05-12 05:32:16 UTC 
(rev 8406)
+++ usrp2/trunk/host/apps/rx_streaming_samples.cc       2008-05-12 05:47:50 UTC 
(rev 8407)
@@ -183,6 +183,7 @@
   fprintf(stderr, "  -o OUTPUT_FILE       set output filename 
[default=samples.dat]\n");
   fprintf(stderr, "  -f FREQ              set frequency to FREQ 
[default=0]\n");
   fprintf(stderr, "  -d DECIM             set decimation rate to DECIM 
[default=32]\n");
+  fprintf(stderr, "  -g gain              rx gain [default=0dB]\n");
   fprintf(stderr, "  -N NSAMPLES          total number of samples to receive 
[default=infinite]\n");
   fprintf(stderr, "  -F SAMPLES_PER_FRAME number of samples in each frame 
[default=371]\n");
   fprintf(stderr, "  -S SCALE             fpga scaling factor for I & Q 
[default=256]\n");
@@ -199,6 +200,8 @@
       d_seqno(seqno) {}
 };
 
+#define GAIN_NOT_SET (-1000)
+
 int
 main(int argc, char **argv)
 {
@@ -210,8 +213,9 @@
   double freq = 0;
   int32_t decim = 32;
   uint64_t nsamples = ~0;
-  int32_t samples_per_frame = 371;
+  int32_t samples_per_frame = 250;
   int32_t scale = 1024;
+  double gain = GAIN_NOT_SET;
 
   int    ch;
   double tmp;
@@ -219,7 +223,7 @@
 
   // setvbuf(stdout, 0, _IOFBF, 64 * 1024); // make stdout fully buffered
 
-  while ((ch = getopt(argc, argv, "he:m:o:f:d:N:F:S:")) != EOF){
+  while ((ch = getopt(argc, argv, "he:m:o:f:d:N:F:S:g:")) != EOF){
     switch (ch){
 
     case 'e':
@@ -273,6 +277,14 @@
       scale = static_cast<int32_t>(tmp);
       break;
       
+    case 'g':
+      if (!strtod_si(optarg, &gain)){
+       std::cerr << "invalid number: " << optarg << std::endl;
+       usage(argv[0]);
+       exit(1);
+      }
+      break;
+
     case 'h':
     default:
       usage(argv[0]);
@@ -333,12 +345,37 @@
   writer->start_undetached();
   
 
-  if (!u2->start_rx(which, freq, decim, 0, samples_per_frame, scale, scale)){
-    std::cerr << "start_rx failed\n";
+  usrp2_tune_result tune_result;
+  
+  if (gain != GAIN_NOT_SET){
+    if (!u2->set_rx_gain(which, gain)){
+      std::cerr << "set_rx_gain failed\n";
+      return 1;
+    }
+  }
+
+  if (!u2->set_rx_freq(which, freq, &tune_result)){
+    std::cerr << "set_rx_freq failed\n";
     return 1;
   }
 
+  if (!u2->set_rx_decim(which, decim)){
+    std::cerr << "set_rx_decim failed\n";
+    return 1;
+  }
 
+  if (!u2->set_rx_scale_iq(which, scale, scale)){
+    std::cerr << "set_rx_scale_iq failed\n";
+    return 1;
+  }
+
+  if (!u2->start_rx_streaming(which, samples_per_frame)){
+    std::cerr << "start_rx_streaming failed\n";
+    return 1;
+  }
+  
+
+
   uint64_t total_samples_recvd = 0;
   int  expected_seqno = 0;
 

Modified: usrp2/trunk/host/apps/tx_samples.cc
===================================================================
--- usrp2/trunk/host/apps/tx_samples.cc 2008-05-12 05:32:16 UTC (rev 8406)
+++ usrp2/trunk/host/apps/tx_samples.cc 2008-05-12 05:47:50 UTC (rev 8407)
@@ -55,10 +55,13 @@
   fprintf(stderr, "  -r                   repeat.  When EOF of input file is 
reached, seek to beginning\n");
   fprintf(stderr, "  -f FREQ              set frequency to FREQ 
[default=0]\n");
   fprintf(stderr, "  -i INTERP            set interpolation rate to INTERP 
[default=32]\n");
+  fprintf(stderr, "  -g gain              set tx gain\n");
   fprintf(stderr, "  -F SAMPLES_PER_FRAME number of samples in each frame 
[default=371]\n");
   fprintf(stderr, "  -S SCALE             fpga scaling factor for I & Q 
[default=256]\n");
 }
 
+#define GAIN_NOT_SET (-1000)
+
 int
 main(int argc, char **argv)
 {
@@ -68,14 +71,15 @@
   const char *mac_addr_str = 0;
   double freq = 0;
   int32_t interp = 32;
-  int32_t samples_per_frame = 371;
+  int32_t samples_per_frame = U2_MAX_SAMPLES;
   int32_t scale = 256;
+  double gain = GAIN_NOT_SET;
   
   int    ch;
   double tmp;
   u2_mac_addr_t mac_addr;
 
-  while ((ch = getopt(argc, argv, "he:m:I:rf:i:F:S")) != EOF){
+  while ((ch = getopt(argc, argv, "he:m:I:rf:i:F:S:g:")) != EOF){
     switch (ch){
 
     case 'e':
@@ -148,9 +152,10 @@
     }
   }
 
-  if (samples_per_frame < 9 || samples_per_frame > 506){
+  if (samples_per_frame < 9 || samples_per_frame > U2_MAX_SAMPLES){
     std::cerr << prettify_progname(argv[0])
-             << ": samples_per_frame is out of range.  Must be in [9, 506].\n";
+             << ": samples_per_frame is out of range.  "
+             << "Must be in [9, " << U2_MAX_SAMPLES << "].\n";
     usage(argv[0]);
     return 1;
   }
@@ -176,13 +181,31 @@
   u2_mac_addr_t which = r[0].addr;     // pick the first one
 
 
-  if (1){
-    if (!u2->config_tx(which, freq, interp, scale, scale)){
-      std::cerr << "tx_samples: config_tx failed\n";
+  usrp2_tune_result tune_result;
+  
+  if (gain != GAIN_NOT_SET){
+    if (!u2->set_tx_gain(which, gain)){
+      std::cerr << "set_tx_gain failed\n";
       return 1;
     }
   }
 
+  if (!u2->set_tx_freq(which, freq, &tune_result)){
+    std::cerr << "set_tx_freq failed\n";
+    return 1;
+  }
+
+  if (!u2->set_tx_interp(which, interp)){
+    std::cerr << "set_tx_interp failed\n";
+    return 1;
+  }
+
+  if (!u2->set_tx_scale_iq(which, scale, scale)){
+    std::cerr << "set_tx_scale_iq failed\n";
+    return 1;
+  }
+
+
   u2_eth_samples_t     pkt;
   u2p_set_word0(&pkt.hdrs.fixed, U2P_TX_IMMEDIATE | U2P_TX_START_OF_BURST, 0);
   u2p_set_timestamp(&pkt.hdrs.fixed, T_NOW);

Modified: usrp2/trunk/host/lib/usrp2_basic.cc
===================================================================
--- usrp2/trunk/host/lib/usrp2_basic.cc 2008-05-12 05:32:16 UTC (rev 8406)
+++ usrp2/trunk/host/lib/usrp2_basic.cc 2008-05-12 05:47:50 UTC (rev 8407)
@@ -23,6 +23,7 @@
 #include "gri_ethernet.h"
 #include "gri_ethernet_pfring.h"       // FIXME
 #include "gri_pktfilter.h"
+#include <usrp2_types.h>
 #include <iostream>
 #include <math.h>
 #include <time.h>      // debug
@@ -47,12 +48,13 @@
  * callbacks, etc.
  */
 
-#define        MIN_PKTLEN   64         // per ethernet spec
-#define MAX_PKTLEN 2048                // biggest thing USRP2 can swallow
+#define        MIN_PKTLEN   64   // per ethernet spec
+#define MAX_PKTLEN 1512          // biggest thing USRP2 can swallow
+                          //   (14-byte ethernet hdr + 1500 byte payload)
 
 
 usrp2_basic::usrp2_basic()
-  : d_ethernet(new GRI_ETHERNET()), d_pf(0), d_seqno(0)
+  : d_ethernet(new GRI_ETHERNET()), d_pf(0), d_seqno(0), d_next_rid(0)
 {
   assert(sizeof(u2_eth_samples_t) == (size_t) MAX_PKTLEN);
 }
@@ -185,73 +187,187 @@
   return false;
 }
 
+/*
+ * ------------------------------------------------------------------------
+ *                   Rx configuration and control
+ * ------------------------------------------------------------------------
+ */
 
+bool
+usrp2_basic::set_rx_gain(const u2_mac_addr_t &which, double gain)
+{
+  uint8_t      pktbuf[MAX_PKTLEN];
+  memset(pktbuf, 0, sizeof(pktbuf));
 
-// ------------------------------------------------------------------------
+  struct command {
+    u2_eth_packet_t    h;
+    op_config_rx_v2_t  op;
+    op_eop_t           eop;
+  };
 
-static int32_t 
-compute_freq_control_word_fpga(double master_freq, double target_freq,
-                              double *actual_freq)
-{
-  int  v = (int) rint (target_freq / master_freq * pow (2.0, 32.0));
-  *actual_freq = v * master_freq / pow (2.0, 32.0);
-  return v;
+  command *c = (command *) pktbuf;
+  init_etf_hdrs(&c->h, which, 0, CONTROL_CHAN, -1);
+
+  c->op.opcode = OP_CONFIG_RX_V2;
+  c->op.len = sizeof(op_config_rx_v2_t);
+  c->op.rid = d_next_rid++;
+
+  c->op.valid = htons(CFGV_GAIN);
+  c->op.gain = htons(u2_double_to_fxpt_gain(gain));
+
+  c->eop.opcode = OP_EOP;
+  c->eop.len = sizeof(op_eop_t);
+
+  int len = std::max((size_t) MIN_PKTLEN, sizeof(command));
+  if (d_ethernet->write_packet(c, len) != len)
+    return false;
+
+  // FIXME wait for corresponding reply, etc.
+
+  return true;
 }
 
 bool
-usrp2_basic::start_rx(const u2_mac_addr_t &which,
-                     double freq,
-                     unsigned int decim,
-                     unsigned int total_samples,       // 0 or [9, 2**21 - 1]
-                     unsigned int samples_per_frame,   // [9, 371] or [9, 505] 
if MTU==2034
-                     int scale_i,                      // 16.0 fixed point 
format
-                     int scale_q,                      // 16.0 fixed point 
format
-                     bool rx_now,
-                     uint32_t rx_time
-                     )
+usrp2_basic::set_rx_freq(const u2_mac_addr_t &which, double freq,
+                        usrp2_tune_result *result)
 {
   uint8_t      pktbuf[MAX_PKTLEN];
   memset(pktbuf, 0, sizeof(pktbuf));
 
   struct command {
     u2_eth_packet_t    h;
-    op_start_rx_t      op;
+    op_config_rx_v2_t  op;
+    op_eop_t           eop;
   };
-    
-  if ((total_samples < 9 && total_samples != 0) || total_samples >= (1L << 
21)){
-    std::cerr << "usrp2_basic::start_rx: total_samples is out of range\n";
+
+  command *c = (command *) pktbuf;
+  init_etf_hdrs(&c->h, which, 0, CONTROL_CHAN, -1);
+
+  c->op.opcode = OP_CONFIG_RX_V2;
+  c->op.len = sizeof(op_config_rx_v2_t);
+  c->op.rid = d_next_rid++;
+
+  c->op.valid = htons(CFGV_FREQ);
+  u2_fxpt_freq_t  fxpt = u2_double_to_fxpt_freq(freq);
+  c->op.freq_hi = htonl(u2_fxpt_freq_hi(fxpt));
+  c->op.freq_lo = htonl(u2_fxpt_freq_lo(fxpt));
+
+  c->eop.opcode = OP_EOP;
+  c->eop.len = sizeof(op_eop_t);
+
+  int len = std::max((size_t) MIN_PKTLEN, sizeof(command));
+  if (d_ethernet->write_packet(c, len) != len)
     return false;
-  }
 
-  if (samples_per_frame < 9 || samples_per_frame > U2_MAX_SAMPLES){
-    std::cerr << "usrp2_basic::start_rx: samples_per_frame is out of range\n";
+  // FIXME wait for corresponding reply, etc.
+
+  if (result)
+    memset(result, 0, sizeof(*result));
+
+  return true;
+}
+
+bool
+usrp2_basic::set_rx_decim(const u2_mac_addr_t &which, int decimation_factor)
+{
+  uint8_t      pktbuf[MAX_PKTLEN];
+  memset(pktbuf, 0, sizeof(pktbuf));
+
+  struct command {
+    u2_eth_packet_t    h;
+    op_config_rx_v2_t  op;
+    op_eop_t           eop;
+  };
+
+  command *c = (command *) pktbuf;
+  init_etf_hdrs(&c->h, which, 0, CONTROL_CHAN, -1);
+
+  c->op.opcode = OP_CONFIG_RX_V2;
+  c->op.len = sizeof(op_config_rx_v2_t);
+  c->op.rid = d_next_rid++;
+
+  c->op.valid = htons(CFGV_INTERP_DECIM);
+  c->op.decim = htonl(decimation_factor);
+
+  c->eop.opcode = OP_EOP;
+  c->eop.len = sizeof(op_eop_t);
+
+  int len = std::max((size_t) MIN_PKTLEN, sizeof(command));
+  if (d_ethernet->write_packet(c, len) != len)
     return false;
-  }
 
-  command      *c = (command *) pktbuf;
+  // FIXME wait for corresponding reply, etc.
+
+  return true;
+}
+
+bool
+usrp2_basic::set_rx_scale_iq(const u2_mac_addr_t &which, int scale_i, int 
scale_q)
+{
+  uint8_t      pktbuf[MAX_PKTLEN];
+  memset(pktbuf, 0, sizeof(pktbuf));
+
+  struct command {
+    u2_eth_packet_t    h;
+    op_config_rx_v2_t  op;
+    op_eop_t           eop;
+  };
+
+  command *c = (command *) pktbuf;
   init_etf_hdrs(&c->h, which, 0, CONTROL_CHAN, -1);
 
-  c->op.opcode = OP_START_RX;
-  c->op.len = sizeof(op_start_rx_t);
+  c->op.opcode = OP_CONFIG_RX_V2;
+  c->op.len = sizeof(op_config_rx_v2_t);
+  c->op.rid = d_next_rid++;
 
-  double actual_freq;
-  c->op.rx_now = rx_now ? 1 : 0;
-  c->op.phase_inc = htonl(compute_freq_control_word_fpga(adc_rate(), freq, 
&actual_freq));
+  c->op.valid = htons(CFGV_SCALE_IQ);
   c->op.scale_iq = htonl(((scale_i & 0xffff) << 16) | (scale_q & 0xffff));
-  c->op.decim = htonl(decim);
-  c->op.samples_per_frame = htonl(samples_per_frame);
-  c->op.total_samples = htonl(total_samples);
-  c->op.rx_time = htonl(rx_time);
 
+  c->eop.opcode = OP_EOP;
+  c->eop.len = sizeof(op_eop_t);
 
   int len = std::max((size_t) MIN_PKTLEN, sizeof(command));
   if (d_ethernet->write_packet(c, len) != len)
     return false;
 
+  // FIXME wait for corresponding reply, etc.
+
   return true;
 }
 
 bool
+usrp2_basic::start_rx_streaming(const u2_mac_addr_t &which, unsigned int 
items_per_frame)
+{
+  if (items_per_frame == 0)    // provide our default
+    items_per_frame = 250;
+
+  uint8_t      pktbuf[MAX_PKTLEN];
+  memset(pktbuf, 0, sizeof(pktbuf));
+
+  struct command {
+    u2_eth_packet_t            h;
+    op_start_rx_streaming_t    op;
+    op_eop_t                   eop;
+  };
+
+  command *c = (command *) pktbuf;
+  init_etf_hdrs(&c->h, which, 0, CONTROL_CHAN, -1);
+
+  c->op.opcode = OP_START_RX_STREAMING;
+  c->op.len = sizeof(op_start_rx_streaming_t);
+  c->op.items_per_frame = htonl(items_per_frame);
+
+  c->eop.opcode = OP_EOP;
+  c->eop.len = sizeof(op_eop_t);
+
+  int len = std::max((size_t) MIN_PKTLEN, sizeof(command));
+  if (d_ethernet->write_packet(c, len) != len)
+    return false;
+
+  return true;
+}
+
+bool
 usrp2_basic::stop_rx(const u2_mac_addr_t &which)
 {
   uint8_t      pktbuf[MAX_PKTLEN];
@@ -274,41 +390,156 @@
   return true;
 }
 
+/*
+ * ------------------------------------------------------------------------
+ *                       Tx configuration
+ * ------------------------------------------------------------------------
+ */
+
 bool
-usrp2_basic::config_tx(const u2_mac_addr_t &which,
-                      double freq,
-                      unsigned int interp,
-                      int scale_i,                     // 16.0 fixed point 
format
-                      int scale_q                      // 16.0 fixed point 
format
-                      )
+usrp2_basic::set_tx_gain(const u2_mac_addr_t &which, double gain)
 {
   uint8_t      pktbuf[MAX_PKTLEN];
   memset(pktbuf, 0, sizeof(pktbuf));
 
   struct command {
     u2_eth_packet_t    h;
-    op_config_tx_t     op;
+    op_config_tx_v2_t  op;
+    op_eop_t           eop;
   };
-    
-  command      *c = (command *) pktbuf;
+
+  command *c = (command *) pktbuf;
   init_etf_hdrs(&c->h, which, 0, CONTROL_CHAN, -1);
 
-  c->op.opcode = OP_CONFIG_TX;
-  c->op.len = sizeof(op_config_tx_t);
+  c->op.opcode = OP_CONFIG_TX_V2;
+  c->op.len = sizeof(op_config_tx_v2_t);
+  c->op.rid = d_next_rid++;
 
-  double actual_freq;
-  c->op.phase_inc = htonl(compute_freq_control_word_fpga(adc_rate(), freq, 
&actual_freq));
+  c->op.valid = htons(CFGV_GAIN);
+  c->op.gain = htons(u2_double_to_fxpt_gain(gain));
+
+  c->eop.opcode = OP_EOP;
+  c->eop.len = sizeof(op_eop_t);
+
+  int len = std::max((size_t) MIN_PKTLEN, sizeof(command));
+  if (d_ethernet->write_packet(c, len) != len)
+    return false;
+
+  // FIXME wait for corresponding reply, etc.
+
+  return true;
+}
+
+bool
+usrp2_basic::set_tx_freq(const u2_mac_addr_t &which, double freq,
+                        usrp2_tune_result *result)
+{
+  uint8_t      pktbuf[MAX_PKTLEN];
+  memset(pktbuf, 0, sizeof(pktbuf));
+
+  struct command {
+    u2_eth_packet_t    h;
+    op_config_tx_v2_t  op;
+    op_eop_t           eop;
+  };
+
+  command *c = (command *) pktbuf;
+  init_etf_hdrs(&c->h, which, 0, CONTROL_CHAN, -1);
+
+  c->op.opcode = OP_CONFIG_TX_V2;
+  c->op.len = sizeof(op_config_tx_v2_t);
+  c->op.rid = d_next_rid++;
+
+  c->op.valid = htons(CFGV_FREQ);
+  u2_fxpt_freq_t  fxpt = u2_double_to_fxpt_freq(freq);
+  c->op.freq_hi = htonl(u2_fxpt_freq_hi(fxpt));
+  c->op.freq_lo = htonl(u2_fxpt_freq_lo(fxpt));
+
+  c->eop.opcode = OP_EOP;
+  c->eop.len = sizeof(op_eop_t);
+
+  int len = std::max((size_t) MIN_PKTLEN, sizeof(command));
+  if (d_ethernet->write_packet(c, len) != len)
+    return false;
+
+  // FIXME wait for corresponding reply, etc.
+
+  if (result)
+    memset(result, 0, sizeof(*result));
+
+  return true;
+}
+
+bool
+usrp2_basic::set_tx_interp(const u2_mac_addr_t &which, int 
interpolation_factor)
+{
+  uint8_t      pktbuf[MAX_PKTLEN];
+  memset(pktbuf, 0, sizeof(pktbuf));
+
+  struct command {
+    u2_eth_packet_t    h;
+    op_config_tx_v2_t  op;
+    op_eop_t           eop;
+  };
+
+  command *c = (command *) pktbuf;
+  init_etf_hdrs(&c->h, which, 0, CONTROL_CHAN, -1);
+
+  c->op.opcode = OP_CONFIG_TX_V2;
+  c->op.len = sizeof(op_config_tx_v2_t);
+  c->op.rid = d_next_rid++;
+
+  c->op.valid = htons(CFGV_INTERP_DECIM);
+  c->op.interp = htonl(interpolation_factor);
+
+  c->eop.opcode = OP_EOP;
+  c->eop.len = sizeof(op_eop_t);
+
+  int len = std::max((size_t) MIN_PKTLEN, sizeof(command));
+  if (d_ethernet->write_packet(c, len) != len)
+    return false;
+
+  // FIXME wait for corresponding reply, etc.
+
+  return true;
+}
+
+bool
+usrp2_basic::set_tx_scale_iq(const u2_mac_addr_t &which, int scale_i, int 
scale_q)
+{
+  uint8_t      pktbuf[MAX_PKTLEN];
+  memset(pktbuf, 0, sizeof(pktbuf));
+
+  struct command {
+    u2_eth_packet_t    h;
+    op_config_tx_v2_t  op;
+    op_eop_t           eop;
+  };
+
+  command *c = (command *) pktbuf;
+  init_etf_hdrs(&c->h, which, 0, CONTROL_CHAN, -1);
+
+  c->op.opcode = OP_CONFIG_TX_V2;
+  c->op.len = sizeof(op_config_tx_v2_t);
+  c->op.rid = d_next_rid++;
+
+  c->op.valid = htons(CFGV_SCALE_IQ);
   c->op.scale_iq = htonl(((scale_i & 0xffff) << 16) | (scale_q & 0xffff));
-  c->op.interp = htonl(interp);
 
+  c->eop.opcode = OP_EOP;
+  c->eop.len = sizeof(op_eop_t);
+
   int len = std::max((size_t) MIN_PKTLEN, sizeof(command));
   if (d_ethernet->write_packet(c, len) != len)
     return false;
 
+  // FIXME wait for corresponding reply, etc.
+
   return true;
 }
 
 
+
 // ------------------------------------------------------------------------
 
 void
@@ -487,7 +718,7 @@
 
   c->op.opcode = OP_READ_TIME;
   c->op.len = sizeof(op_read_time_t);
-  c->op.rid_mbz = 0;
+  c->op.rid = 0;
   int len = std::max((size_t) MIN_PKTLEN, sizeof(command));
   if (d_ethernet->write_packet(c, len) != len)
     return false;

Modified: usrp2/trunk/host/lib/usrp2_basic.h
===================================================================
--- usrp2/trunk/host/lib/usrp2_basic.h  2008-05-12 05:32:16 UTC (rev 8406)
+++ usrp2/trunk/host/lib/usrp2_basic.h  2008-05-12 05:47:50 UTC (rev 8407)
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2007 Free Software Foundation, Inc.
+ * Copyright 2007,2008 Free Software Foundation, Inc.
  *
  * 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
@@ -30,11 +30,33 @@
 
 #define GRI_ETHERNET gri_ethernet
 
+//! Provides detailed result of tuning request
+
+struct usrp2_tune_result
+{
+  // RF frequency that corresponds to DC in the IF
+  double baseband_freq;
+
+  // frequency programmed into the DDC/DUC
+  double dxc_freq;
+
+  // residual frequency (typically < 0.01 Hz)
+  double residual_freq;
+
+  // is the spectrum inverted?
+  bool  spectrum_inverted;
+
+  usrp2_tune_result()
+    : baseband_freq(0), dxc_freq(0), residual_freq(0), 
spectrum_inverted(false) {}
+};
+
+
 class usrp2_basic : public boost::noncopyable
 {
   GRI_ETHERNET *d_ethernet;
   gri_pktfilter        *d_pf;
   int           d_seqno;
+  int           d_next_rid;
 
   void init_et_hdrs(u2_eth_packet_t *p, const u2_mac_addr_t &dst);
 
@@ -83,6 +105,31 @@
   static bool parse_mac_addr(const std::string &s, u2_mac_addr_t *p);
 
 
+  /*
+   * Rx configuration and control
+   */
+  bool set_rx_gain(const u2_mac_addr_t &which, double gain);
+  bool set_rx_freq(const u2_mac_addr_t &which, double frequency, 
usrp2_tune_result *result);
+  bool set_rx_decim(const u2_mac_addr_t &which, int decimation_factor);
+  bool set_rx_scale_iq(const u2_mac_addr_t &which, int scale_i, int scale_q);
+
+  //! start streaming Rx samples
+  bool start_rx_streaming(const u2_mac_addr_t &which, unsigned int 
items_per_frame=0);
+
+  //! stop streaming Rx samples
+  bool stop_rx(const u2_mac_addr_t &which);
+
+  
+  /*
+   * Tx configuration and control
+   */
+  bool set_tx_gain(const u2_mac_addr_t &which, double gain);
+  bool set_tx_freq(const u2_mac_addr_t &which, double frequency, 
usrp2_tune_result *result);
+  bool set_tx_interp(const u2_mac_addr_t &which, int interpolation_factor);
+  bool set_tx_scale_iq(const u2_mac_addr_t &which, int scale_i, int scale_q);
+  
+
+#if 0
   bool start_rx(const u2_mac_addr_t &which,
                double freq,
                unsigned int decim,
@@ -94,15 +141,14 @@
                uint32_t rx_time = -1           // otherwise begin receiving at 
rx_time
                );
 
-  bool stop_rx(const u2_mac_addr_t &which);
 
-
   bool config_tx(const u2_mac_addr_t &which,
                 double freq,
                 unsigned int interp,
                 int scale_i,                   // 16.0 fixed point format
                 int scale_q                    // 16.0 fixed point format
                 );
+#endif
 
   /*!
    * \brief Read raw samples from USRP2.





reply via email to

[Prev in Thread] Current Thread [Next in Thread]