commit-gnuradio
[Top][All Lists]
Advanced

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

[Commit-gnuradio] r9062 - in usrp2/branches/features/host-ng/host-ng: .


From: eb
Subject: [Commit-gnuradio] r9062 - in usrp2/branches/features/host-ng/host-ng: . apps include/usrp2 lib
Date: Wed, 30 Jul 2008 16:48:17 -0600 (MDT)

Author: eb
Date: 2008-07-30 16:48:13 -0600 (Wed, 30 Jul 2008)
New Revision: 9062

Added:
   usrp2/branches/features/host-ng/host-ng/apps/test2_usrp2.cc
   usrp2/branches/features/host-ng/host-ng/include/usrp2/copiers.h
   usrp2/branches/features/host-ng/host-ng/include/usrp2/metadata.h
   usrp2/branches/features/host-ng/host-ng/include/usrp2/rx_sample_handler.h
   usrp2/branches/features/host-ng/host-ng/lib/copiers.cc
   usrp2/branches/features/host-ng/host-ng/lib/rx_sample_handler.cc
Modified:
   usrp2/branches/features/host-ng/host-ng/apps/
   usrp2/branches/features/host-ng/host-ng/apps/Makefile.am
   usrp2/branches/features/host-ng/host-ng/configure.ac
   usrp2/branches/features/host-ng/host-ng/include/usrp2/Makefile.am
   usrp2/branches/features/host-ng/host-ng/include/usrp2/usrp2.h
   usrp2/branches/features/host-ng/host-ng/lib/Makefile.am
   usrp2/branches/features/host-ng/host-ng/lib/control.h
   usrp2/branches/features/host-ng/host-ng/lib/eth_buffer.cc
   usrp2/branches/features/host-ng/host-ng/lib/usrp2.cc
   usrp2/branches/features/host-ng/host-ng/lib/usrp2_impl.cc
   usrp2/branches/features/host-ng/host-ng/lib/usrp2_impl.h
Log:
Merged eb/wip -r9031:9061 usrp2 work-in-progress to features/host-ng.
Receive path is believed to be working.  Transmit control messages
have been implemented but not tested.  The receive path contains many
unaligned loads that will fail on most machines other than x86. (We'll
get around to fixing them in a bit.)




Property changes on: usrp2/branches/features/host-ng/host-ng/apps
___________________________________________________________________
Name: svn:ignore
   - Makefile
Makefile.in
.libs
.deps
test_eth
test_usrp2
cerr
*.sh

   + Makefile
Makefile.in
.libs
.deps
test_eth
test_usrp2
test2_usrp2
cerr
*.sh


Modified: usrp2/branches/features/host-ng/host-ng/apps/Makefile.am
===================================================================
--- usrp2/branches/features/host-ng/host-ng/apps/Makefile.am    2008-07-30 
21:56:27 UTC (rev 9061)
+++ usrp2/branches/features/host-ng/host-ng/apps/Makefile.am    2008-07-30 
22:48:13 UTC (rev 9062)
@@ -17,16 +17,16 @@
 
 include $(top_srcdir)/Makefile.common
 
-AM_CPPFLAGS = -Wall -Werror
-INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(CPPUNIT_INCLUDES) $(GRUEL_CFLAGS)
+#AM_CXXFLAGS = -Wall -Werror (handle this with: $ ./configure CXXFLAGS="-Wall 
-Werror -O2 -g")
+AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(CPPUNIT_INCLUDES) $(GRUEL_CFLAGS)
 
 LDADD = \
        ../lib/libusrp2ng.la \
        -lgruel
 
 noinst_PROGRAMS = \
-       test_usrp2
+       test2_usrp2
 
-test_usrp2_SOURCES = \
-       test_usrp2.cc
+test2_usrp2_SOURCES = \
+       test2_usrp2.cc
 

Copied: usrp2/branches/features/host-ng/host-ng/apps/test2_usrp2.cc (from rev 
9061, usrp2/branches/developers/eb/wip/host-ng/apps/test2_usrp2.cc)
===================================================================
--- usrp2/branches/features/host-ng/host-ng/apps/test2_usrp2.cc                 
        (rev 0)
+++ usrp2/branches/features/host-ng/host-ng/apps/test2_usrp2.cc 2008-07-30 
22:48:13 UTC (rev 9062)
@@ -0,0 +1,380 @@
+/* -*- 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/usrp2.h>
+#include <usrp2/tune_result.h>
+#include <usrp2/strtod_si.h>
+#include <usrp2/rx_sample_handler.h>
+#include <usrp2/copiers.h>
+#include <gruel/realtime.h>
+#include <sys/time.h>
+#include <iostream>
+#include <string.h>
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+#include <stdexcept>
+
+// ------------------------------------------------------------------------
+
+class rx_nop_handler : public usrp2::rx_sample_handler
+{
+  size_t       d_max_samples;
+  size_t       d_nsamples;
+  size_t       d_nframes;
+
+public:
+  
+  rx_nop_handler(size_t max_samples)
+    : d_max_samples(max_samples), d_nsamples(0), d_nframes(0) {}
+      
+  ~rx_nop_handler();
+
+  size_t nframes() const { return d_nframes; }
+  size_t nsamples() const { return d_nsamples; }
+  size_t max_samples() const { return d_max_samples; }
+
+  bool 
+  operator()(const uint32_t *items, size_t nitems, const usrp2::rx_metadata 
*metadata)
+  {
+    // printf("W0: %08x  TS: %08x\n", metadata->word0, metadata->timestamp);
+    // printf("I0: %08x\n", items[0]);
+
+    d_nsamples += nitems;
+    d_nframes++;
+
+    return d_nsamples < d_max_samples;
+  }
+};
+
+rx_nop_handler::~rx_nop_handler()
+{
+  // nop
+}
+
+// ------------------------------------------------------------------------
+
+// FIXME make this a template
+
+class complex_16_file_writer : public rx_nop_handler
+{
+  FILE        *d_fp;
+  std::string  d_filename;
+
+public:
+
+  complex_16_file_writer(const std::string &filename, size_t max_samples)
+    : rx_nop_handler(max_samples), d_filename(filename)
+  {
+    d_fp = fopen(filename.c_str(), "wb");
+    if (d_fp == 0){
+      perror(filename.c_str());
+      throw std::invalid_argument(filename);
+    }
+  }
+
+  ~complex_16_file_writer();
+
+  bool 
+  operator()(const uint32_t *items, size_t nitems, const usrp2::rx_metadata 
*metadata)
+  {
+    bool ok = rx_nop_handler::operator()(items, nitems, metadata);
+
+    size_t host_nitems = nitems;
+    std::complex<int16_t> host_items[host_nitems];
+
+    usrp2::copy_u2_complex_16_to_host_complex_16(nitems, items, host_items);
+
+    size_t n = 0;
+    while (n < host_nitems){
+      size_t r = fwrite(&host_items[n], sizeof(host_items[0]), host_nitems - 
n, d_fp);
+      n += r;
+      if (r == 0){     // out of space?
+       perror(d_filename.c_str());
+       ok = false;
+       break;
+      }
+    }
+
+    return ok;
+  }
+};
+
+complex_16_file_writer::~complex_16_file_writer()
+{
+  fclose(d_fp);
+}
+
+// ------------------------------------------------------------------------
+
+class complex_float_file_writer : public rx_nop_handler
+{
+  FILE        *d_fp;
+  std::string  d_filename;
+
+public:
+
+  complex_float_file_writer(const std::string &filename, size_t max_samples)
+    : rx_nop_handler(max_samples), d_filename(filename)
+  {
+    d_fp = fopen(filename.c_str(), "wb");
+    if (d_fp == 0){
+      perror(filename.c_str());
+      throw std::invalid_argument(filename);
+    }
+  }
+
+  ~complex_float_file_writer();
+
+  bool 
+  operator()(const uint32_t *items, size_t nitems, const usrp2::rx_metadata 
*metadata)
+  {
+    bool ok = rx_nop_handler::operator()(items, nitems, metadata);
+
+    size_t host_nitems = nitems;
+    std::complex<float> host_items[host_nitems];
+
+    usrp2::copy_u2_complex_16_to_host_complex_float(nitems, items, host_items);
+
+    size_t n = 0;
+    while (n < host_nitems){
+      size_t r = fwrite(&host_items[n], sizeof(host_items[0]), host_nitems - 
n, d_fp);
+      n += r;
+      if (r == 0){     // out of space?
+       perror(d_filename.c_str());
+       ok = false;
+       break;
+      }
+    }
+
+    return ok;
+  }
+};
+
+complex_float_file_writer::~complex_float_file_writer()
+{
+  fclose(d_fp);
+}
+
+// ------------------------------------------------------------------------
+
+
+
+
+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, "  -f FREQUENCY         specify receive center frequency in 
Hz [default=0.0]\n");
+  fprintf(stderr, "  -d DECIM             specify receive decimation rate 
[default=5]\n");
+  fprintf(stderr, "  -g GAIN              specify receive daughterboard gain 
[default=0]\n");
+  fprintf(stderr, "  -N NSAMPLES          specify number of samples to receive 
[default=250e6]\n");
+//fprintf(stderr, "  -b BUFSIZE           specify size of receive buffer 
[default=64k]\n");
+  fprintf(stderr, "  -o OUTPUT_FILENAME   specify file to receive samples 
[default=none]\n");
+  fprintf(stderr, "  -s                   write complex<short> 
[default=complex<float>]\n");
+}
+
+int
+main(int argc, char **argv)
+{
+  // options and their defaults
+  const char *interface = "eth0";
+  const char *mac_addr_str = "";
+  double rx_freq = 0.0;
+  int rx_decim = 5;
+  double rx_gain = 0.0;
+  size_t nsamples = static_cast<size_t>(250e6);
+  bool output_shorts = false;
+  char *output_filename = 0;
+
+  int ch;
+
+  while ((ch = getopt(argc, argv, "he:m:f:d:g:N:o:s")) != EOF){
+    double tmp;
+    switch (ch){
+
+    case 'e':
+      interface = optarg;
+      break;
+      
+    case 'm':
+      mac_addr_str = optarg;
+      break;
+
+    case 'f':
+      if (!strtod_si(optarg, &rx_freq)) {
+        std::cerr << "invalid number: " << optarg << std::endl;
+       usage(argv[0]);
+       exit(1);
+      }
+      break;
+
+    case 'g':
+      if (!strtod_si(optarg, &rx_gain)) {
+        std::cerr << "invalid number: " << optarg << std::endl;
+       usage(argv[0]);
+       exit(1);
+      }
+      break;
+
+    case 'd':
+      rx_decim = strtol(optarg, 0, 0);
+      if (rx_decim < 4 or rx_decim > 512) { 
+        std::cerr << "invalid decimation rate: " << 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<size_t>(tmp);
+      break;
+      
+#if 0
+    case 'b':
+      if (!strtod_si(optarg, &tmp)) {
+        std::cerr << "invalid number: " << optarg << std::endl;
+       usage(argv[0]);
+       exit(1);
+      }
+      bufsize = static_cast<size_t>(tmp);
+      break;
+#endif
+
+    case 's':
+      output_shorts = true;
+      break;
+
+    case 'o':
+      output_filename = optarg;
+      break;
+      
+    case 'h':
+    default:
+      usage(argv[0]);
+      exit(1);
+    }
+  }
+
+
+  typedef boost::shared_ptr<rx_nop_handler> handler_sptr;
+  handler_sptr handler;
+
+  if (output_filename){
+    if (output_shorts)
+      handler = handler_sptr(new complex_16_file_writer(output_filename, 
nsamples));
+    else
+      handler = handler_sptr(new complex_float_file_writer(output_filename, 
nsamples));
+  }
+  else
+    handler = handler_sptr(new rx_nop_handler(nsamples));
+
+
+  gruel::rt_status_t rt = gruel::enable_realtime_scheduling();
+  if (rt != gruel::RT_OK)
+    std::cerr << "Failed to enable realtime scheduling" << std::endl;
+
+  usrp2::usrp2::sptr u2 = usrp2::usrp2::make(interface, mac_addr_str);
+  
+  // FIXME in case it was left running...
+  if (!u2->stop_rx_streaming()){
+    fprintf(stderr, "stop_rx_streaming failed\n");
+  }
+
+  if (!u2->set_rx_gain(rx_gain)){
+    fprintf(stderr, "set_rx_gain(%f) failed\n", rx_gain);
+    exit(1);
+  }
+
+  usrp2::tune_result tr;
+  if (!u2->set_rx_center_freq(rx_freq, &tr)){
+    fprintf(stderr, "set_rx_center_freq(%g) failed\n", rx_freq);
+    exit(1);
+  }
+
+  printf("Daughterboard configuration:\n");
+  printf("  baseband_freq=%f\n", tr.baseband_freq);
+  printf("       ddc_freq=%f\n", tr.dxc_freq);
+  printf("  residual_freq=%f\n", tr.residual_freq);
+  printf("       inverted=%s\n\n", tr.spectrum_inverted ? "yes" : "no");
+  
+  if (!u2->set_rx_decim(rx_decim)) {
+    fprintf(stderr, "set_rx_decim(%d) failed\n", rx_decim);
+    exit(1);
+  }
+
+  printf("USRP2 using decimation rate of %d\n", rx_decim);
+    
+  if (!u2->start_rx_streaming(0)){
+    fprintf(stderr, "start_rx_streaming failed\n");
+    exit(1);
+  }
+
+  printf("Receiving %zd samples\n\n", nsamples);
+  
+  struct timeval start, end;
+  gettimeofday(&start, 0);
+
+
+  while(handler->nsamples() < handler->max_samples()){
+    bool ok = u2->rx_samples(0, handler.get());
+    if (!ok){
+      fprintf(stderr, "u2->rx_samples failed\n");
+      return 1;
+    }
+  }
+
+
+  gettimeofday(&end, 0);
+  long n_usecs = end.tv_usec-start.tv_usec;
+  long n_secs = end.tv_sec-start.tv_sec;
+  double elapsed = (double)n_secs + (double)n_usecs*1e-6;
+  double mbs = handler->nsamples()*sizeof(uint32_t)/elapsed/1e6;
+  double pps = handler->nframes()/elapsed;
+  
+  u2->stop_rx_streaming();
+
+  printf("\nCopy handler called %li times.\n", handler->nframes());
+  printf("Copy handler called with %li bytes.\n\n", 
handler->nsamples()*sizeof(uint32_t));
+  printf("Elapsed time was %5.3f seconds.\n", elapsed);
+  printf("Packet rate was %1.0f pkts/sec.\n", pps);
+  printf("Approximate throughput was %5.2f MB/sec.\n", mbs);
+  printf("Total instances of overruns was %d.\n", u2->rx_overruns());
+  printf("Total missing frames was %d.\n", u2->rx_missing()); 
+
+  return 0;
+}

Modified: usrp2/branches/features/host-ng/host-ng/configure.ac
===================================================================
--- usrp2/branches/features/host-ng/host-ng/configure.ac        2008-07-30 
21:56:27 UTC (rev 9061)
+++ usrp2/branches/features/host-ng/host-ng/configure.ac        2008-07-30 
22:48:13 UTC (rev 9062)
@@ -1,4 +1,4 @@
-dnl Copyright 2001,2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc.
+dnl Copyright 2001,2002,2003,2004,2005,2006,2007,2008 Free Software 
Foundation, Inc.
 dnl
 dnl This program is free software: you can redistribute it and/or modify
 dnl it under the terms of the GNU General Public License as published by
@@ -81,10 +81,11 @@
 AC_PROG_INSTALL
 AC_PATH_PROG([RM_PROG], [rm])
 
+AC_LIBTOOL_WIN32_DLL
 dnl AC_DISABLE_SHARED  dnl don't build shared libraries
 AC_ENABLE_SHARED       dnl do build shared libraries
 AC_DISABLE_STATIC      dnl don't build static libraries
-AC_PROG_LIBTOOL
+m4_ifdef([LT_INIT],[LT_INIT],[AC_PROG_LIBTOOL])
 dnl GR_FORTRAN
 
 GR_NO_UNDEFINED                dnl do we need the -no-undefined linker flag

Modified: usrp2/branches/features/host-ng/host-ng/include/usrp2/Makefile.am
===================================================================
--- usrp2/branches/features/host-ng/host-ng/include/usrp2/Makefile.am   
2008-07-30 21:56:27 UTC (rev 9061)
+++ usrp2/branches/features/host-ng/host-ng/include/usrp2/Makefile.am   
2008-07-30 22:48:13 UTC (rev 9062)
@@ -22,6 +22,7 @@
 usrp2includedir = $(includedir)/usrp2
 
 usrp2include_HEADERS = \
+       copiers.h \
        copy_handler.h \
        data_handler.h \
        strtod_si.h \

Copied: usrp2/branches/features/host-ng/host-ng/include/usrp2/copiers.h (from 
rev 9061, usrp2/branches/developers/eb/wip/host-ng/include/usrp2/copiers.h)
===================================================================
--- usrp2/branches/features/host-ng/host-ng/include/usrp2/copiers.h             
                (rev 0)
+++ usrp2/branches/features/host-ng/host-ng/include/usrp2/copiers.h     
2008-07-30 22:48:13 UTC (rev 9062)
@@ -0,0 +1,63 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 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_USRP2_COPIERS_H
+#define INCLUDED_USRP2_COPIERS_H
+
+#include <complex>
+#include <stdint.h>
+
+namespace usrp2 {
+
+  // FIXME we may want to rework this, but this will get us on the air
+
+  /*
+   * ----------------------------------------------------------------
+   * Copy and convert from USRP2 wire format to host format
+   * ----------------------------------------------------------------
+   */
+
+  void 
+  copy_u2_complex_16_to_host_complex_16(size_t nitems,
+                                       const uint32_t *items,
+                                       std::complex<int16_t> *host_items);
+
+  void 
+  copy_u2_complex_16_to_host_complex_float(size_t nitems,
+                                          const uint32_t *items,
+                                          std::complex<float> *host_items);
+
+  /*
+   * ----------------------------------------------------------------
+   * Copy and convert from host format to USRP2 wire format
+   * ----------------------------------------------------------------
+   */
+
+  void 
+  copy_host_complex_16_to_u2_complex_16(size_t nitems,
+                                       const std::complex<int16_t> *host_items,
+                                       uint32_t *items);
+
+  void 
+  copy_host_complex_float_to_u2_complex_16(size_t nitems,
+                                          const std::complex<float> 
*host_items,
+                                          uint32_t *items);
+}
+
+
+#endif /* INCLUDED_USRP2_COPIERS_H */

Copied: usrp2/branches/features/host-ng/host-ng/include/usrp2/metadata.h (from 
rev 9061, usrp2/branches/developers/eb/wip/host-ng/include/usrp2/metadata.h)
===================================================================
--- usrp2/branches/features/host-ng/host-ng/include/usrp2/metadata.h            
                (rev 0)
+++ usrp2/branches/features/host-ng/host-ng/include/usrp2/metadata.h    
2008-07-30 22:48:13 UTC (rev 9062)
@@ -0,0 +1,60 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 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_USRP2_METADATA_H
+#define INCLUDED_USRP2_METADATA_H
+
+#include <stdint.h>
+
+namespace usrp2 {
+
+  //! type of the timestamp returned from the USRP2 FPGA
+  typedef uint32_t     fpga_timestamp;
+
+  /*!
+   * \brief metadata associated with received frames
+   */
+  struct rx_metadata {
+    uint32_t           word0;                  //< debugging, extensions
+    fpga_timestamp     timestamp;              //< time that first sample of 
frame was received
+    unsigned int       start_of_burst : 1;     //< this frame is the start of 
a burst
+    unsigned int       end_of_burst   : 1;     //< this frame is the end of a 
burst
+    unsigned int       rx_overrun     : 1;     //< An Rx overrun occurred in 
the FPGA
+    // rssi
+    // agc_mode
+
+    rx_metadata() :
+      word0(0), timestamp(0), start_of_burst(0), end_of_burst(0), 
rx_overrun(0) {}
+  };
+
+  /*!
+   * \brief metadata associated with transmitted frames
+   */
+  struct tx_metadata {
+    fpga_timestamp     timestamp;              //< time to transmit first 
sample of frame
+    unsigned int       send_now       : 1;     //< ignore timestamp, send now
+    unsigned int       start_of_burst : 1;     //< this frame is the start of 
a burst
+    unsigned int       end_of_burst   : 1;     //< this frame is the end of a 
burst
+    // ...
+
+    tx_metadata() :
+      timestamp(0), send_now(0), start_of_burst(0), end_of_burst(0) {}
+  };
+
+}; // usrp2
+
+#endif /* INCLUDED_USRP2_METADATA_H */

Copied: 
usrp2/branches/features/host-ng/host-ng/include/usrp2/rx_sample_handler.h (from 
rev 9061, 
usrp2/branches/developers/eb/wip/host-ng/include/usrp2/rx_sample_handler.h)
===================================================================
--- usrp2/branches/features/host-ng/host-ng/include/usrp2/rx_sample_handler.h   
                        (rev 0)
+++ usrp2/branches/features/host-ng/host-ng/include/usrp2/rx_sample_handler.h   
2008-07-30 22:48:13 UTC (rev 9062)
@@ -0,0 +1,58 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 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_USRP2_RX_SAMPLE_HANDLER_H
+#define INCLUDED_USRP2_RX_SAMPLE_HANDLER_H
+
+#include <usrp2/metadata.h>
+#include <stddef.h>
+
+
+namespace usrp2 {
+
+  /*!
+   * \brief Abstract function object called to handle received data blocks.
+   *
+   * An object derived from this class is passed to usrp2::rx_samples
+   * to process the received frames of samples.
+   */
+  class rx_sample_handler {
+  public:
+    virtual ~rx_sample_handler();
+
+    /*!
+     * \param items points to the first 32-bit word of uninterpreted sample 
data in the frame.
+     * \param nitems is the number of entries in the frame in units of 
uint32_t's.
+     * \param metadata is the additional per frame data provided by the USRP2 
FPGA.
+     *
+     * \p items points to the raw sample data received off of the ethernet.  
The data is
+     * packed into big-endian 32-bit unsigned ints for transport, but the 
actual format
+     * of the data is dependent on the current configuration of the USRP2.  
The most common
+     * format is 16-bit I & Q, with I in the top of the 32-bit word.
+     *
+     * This is the general purpose, low level interface and relies on other 
functions
+     * to handle all required endian-swapping and format conversion.  \sa 
FIXME.
+     *
+     * \returns true if the object wants to be called again with new data;
+     * false if no additional data is wanted.
+     */
+    virtual bool operator()(const uint32_t *items, size_t nitems, const 
rx_metadata *metadata) = 0;
+  };
+
+};
+
+#endif /* INCLUDED_RX_SAMPLE_HANDLER_H */

Modified: usrp2/branches/features/host-ng/host-ng/include/usrp2/usrp2.h
===================================================================
--- usrp2/branches/features/host-ng/host-ng/include/usrp2/usrp2.h       
2008-07-30 21:56:27 UTC (rev 9061)
+++ usrp2/branches/features/host-ng/host-ng/include/usrp2/usrp2.h       
2008-07-30 22:48:13 UTC (rev 9062)
@@ -22,6 +22,7 @@
 #include <boost/shared_ptr.hpp>
 #include <boost/utility.hpp>
 #include <vector>
+#include <usrp2/rx_sample_handler.h>
 
 namespace usrp2 {
 
@@ -39,10 +40,19 @@
 
   typedef std::vector<props> props_vector_t;
 
-  props_vector_t find(const std::string &ifc, const std::string &addr=""); 
+  /*!
+   * \brief Search the ethernet for all USRP2s or for a specific USRP2.
+   *
+   * \param ifc is the name of the OS ethernet interface (e.g., "eth0")
+   * \param mac_addr is the MAC address of the desired USRP2, or "" to search 
for all.
+   * mac_addr must be either a zero length string, "", or must be of the form
+   * "01:02:03:04:05:06" or "05:06".
+   *
+   * \returns a vector of properties, 1 entry for each matching USRP2 found.
+   */
+  props_vector_t find(const std::string &ifc, const std::string &mac_addr=""); 
 
   class tune_result;
-  class data_handler;
   
   class usrp2 : boost::noncopyable
   {
@@ -57,9 +67,9 @@
     /*! 
      * Static function to return an instance of usrp2 as a shared pointer
      *
-     * \param ifc        Network interface name, e.g., "eth0"
-     * \param addr  Network mac address, e.g., "01:02:03:04:05:06" or "05:06",
-     *              default is auto-select
+     * \param ifc   Network interface name, e.g., "eth0"
+     * \param addr  Network mac address, e.g., "01:02:03:04:05:06", "05:06" or 
"".
+     *              "" will autoselect a USRP2 if there is only a single one 
on the local ethernet.
      */
     static sptr make(const std::string &ifc, const std::string &addr="");
 
@@ -69,7 +79,9 @@
     ~usrp2();  
 
     /*
+     * ----------------------------------------------------------------
      * Rx configuration and control
+     * ----------------------------------------------------------------
      */
 
     /*!
@@ -99,9 +111,7 @@
      *      type: floating, fixed point, or raw
      *     depth: bits per sample
      *
-     * Sets format over the wire for samples from USRP2 and determines 
-     * default reader and writer functors   
-     * 
+     * Sets format over the wire for samples from USRP2.
      */
     // bool set_rx_format(...);
 
@@ -115,14 +125,15 @@
     bool start_rx_streaming(unsigned int channel=0, unsigned int 
items_per_frame=0);
   
     /*!
-     * Receive stream data from specified channel
+     * Stop streaming receive mode.
      */
-    bool rx_samples(unsigned int channel, data_handler *handler);
+    bool stop_rx_streaming(unsigned int channel=0);
 
     /*!
-     * Stop streaming receive mode.
+     * \brief Receive data from the specified channel
+     * This method is used to receive all data: streaming or discrete.
      */
-    bool stop_rx_streaming(unsigned int channel=0);
+    bool rx_samples(unsigned int channel, rx_sample_handler *handler);
 
     /*!
      * Returns number of times receive overruns have occurred
@@ -134,9 +145,49 @@
      */
     unsigned int rx_missing();
 
-    /* Ignore :-) */
-    class impl;
+    /*
+     * ----------------------------------------------------------------
+     * Tx configuration and control
+     * ----------------------------------------------------------------
+     */
 
+    /*!
+     * Set receiver gain
+     */
+    bool set_tx_gain(double gain);
+
+    /*!
+     * Set transmitter center frequency
+     */
+    bool set_tx_center_freq(double frequency, tune_result *result);
+
+    /*!
+     * Set transmitter sample rate interpolation
+     */
+    bool set_tx_interp(int interpolation_factor);
+
+    /*!
+     * Set transmit IQ magnitude scaling
+     */
+    bool set_tx_scale_iq(int scale_i, int scale_q);
+
+    /*!
+     * Set transmit sample format
+     *   
+     *    domain: complex or real
+     *      type: floating, fixed point, or raw
+     *     depth: bits per sample
+     *
+     * Sets format over the wire for samples to USRP2.
+     */
+    // bool set_tx_format(...);
+
+    // bool tx_samples(...)
+
+
+
+    class impl;                // implementation details
+
   private:
     // Only usrp2::make factory function can instantiate this class
     usrp2(const std::string &ifc, const std::string &addr);

Modified: usrp2/branches/features/host-ng/host-ng/lib/Makefile.am
===================================================================
--- usrp2/branches/features/host-ng/host-ng/lib/Makefile.am     2008-07-30 
21:56:27 UTC (rev 9061)
+++ usrp2/branches/features/host-ng/host-ng/lib/Makefile.am     2008-07-30 
22:48:13 UTC (rev 9062)
@@ -17,14 +17,15 @@
 
 include $(top_srcdir)/Makefile.common
 
-AM_CPPFLAGS = -Wall -Werror
-INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(CPPUNIT_INCLUDES) $(GRUEL_CFLAGS) 
$(BOOST_CFLAGS)
+#AM_CXXFLAGS = -Wall -Werror (handle this with: $ ./configure CXXFLAGS="-Wall 
-Werror -O2 -g")
+AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(CPPUNIT_INCLUDES) $(GRUEL_CFLAGS) 
$(BOOST_CFLAGS)
 
 lib_LTLIBRARIES = \
        libusrp2ng.la
 
 libusrp2ng_la_SOURCES = \
        control.cc \
+       copiers.cc \
        copy_handler.cc \
        data_handler.cc \
        eth_buffer.cc \
@@ -32,6 +33,7 @@
        find.cc \
        pktfilter.cc \
        ring.cc \
+       rx_sample_handler.cc \
        strtod_si.c \
        usrp2.cc \
        usrp2_impl.cc \

Modified: usrp2/branches/features/host-ng/host-ng/lib/control.h
===================================================================
--- usrp2/branches/features/host-ng/host-ng/lib/control.h       2008-07-30 
21:56:27 UTC (rev 9061)
+++ usrp2/branches/features/host-ng/host-ng/lib/control.h       2008-07-30 
22:48:13 UTC (rev 9062)
@@ -46,6 +46,14 @@
     op_generic_t    eop;
   };
 
+  struct op_config_tx_v2_cmd 
+  {
+    u2_eth_packet_t   h;
+    op_config_tx_v2_t op;
+    op_generic_t      eop;
+  };
+
+
   /*!
    * Control mechanism to allow API calls to block waiting for reply packets
    */    

Copied: usrp2/branches/features/host-ng/host-ng/lib/copiers.cc (from rev 9061, 
usrp2/branches/developers/eb/wip/host-ng/lib/copiers.cc)
===================================================================
--- usrp2/branches/features/host-ng/host-ng/lib/copiers.cc                      
        (rev 0)
+++ usrp2/branches/features/host-ng/host-ng/lib/copiers.cc      2008-07-30 
22:48:13 UTC (rev 9062)
@@ -0,0 +1,108 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio 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, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <usrp2/copiers.h>
+#include <gruel/inet.h>
+#include <stdexcept>
+#include <assert.h>
+#include <string.h>
+
+// FIXME need gruel::not_implemented
+
+namespace usrp2 {
+
+  /*
+   * ----------------------------------------------------------------
+   * Copy and convert from USRP2 wire format to host format
+   * ----------------------------------------------------------------
+   */
+  void 
+  copy_u2_complex_16_to_host_complex_16(size_t nitems,
+                                       const uint32_t *items,
+                                       std::complex<int16_t> *host_items)
+  {
+#ifdef WORDS_BIGENDIAN
+
+    assert(sizeof(items[0]) == sizeof(host_items[0]));
+    memcpy(host_items, items, nitems * sizeof(items[0]));
+
+#else
+
+    // FIXME SIMD welcome here
+
+    for (size_t i = 0; i < nitems; i++){
+      uint32_t t = ntohx(items[i]);
+      //printf("%9d\n", items[i]);
+      host_items[i] = std::complex<int16_t>((t >> 16), t & 0xffff);
+    }
+
+#endif
+  }
+
+
+  void 
+  copy_u2_complex_16_to_host_complex_float(size_t nitems,
+                                          const uint32_t *items,
+                                          std::complex<float> *host_items)
+  {
+    throw std::runtime_error("not implemented");
+  }
+
+
+  /*
+   * ----------------------------------------------------------------
+   * Copy and convert from host format to USRP2 wire format
+   * ----------------------------------------------------------------
+   */
+  void 
+  copy_host_complex_16_to_u2_complex_16(size_t nitems,
+                                       const std::complex<int16_t> *host_items,
+                                       uint32_t *items)
+  {
+#ifdef WORDS_BIGENDIAN
+
+    assert(sizeof(items[0]) == sizeof(host_items[0]));
+    memcpy(items, host_items, nitems * sizeof(items[0]));
+
+#else
+
+    // FIXME SIMD welcome here
+
+    for (size_t i = 0; i < nitems; i++){
+      items[i] = htonl((host_items[i].real() << 16) | (host_items[i].imag() & 
0xffff));
+    }
+
+#endif
+  }
+
+
+  void 
+  copy_host_complex_float_to_u2_complex_16(size_t nitems,
+                                          const std::complex<float> 
*host_items,
+                                          uint32_t *items)
+  {
+    throw std::runtime_error("not implemented");
+  }
+
+}

Modified: usrp2/branches/features/host-ng/host-ng/lib/eth_buffer.cc
===================================================================
--- usrp2/branches/features/host-ng/host-ng/lib/eth_buffer.cc   2008-07-30 
21:56:27 UTC (rev 9061)
+++ usrp2/branches/features/host-ng/host-ng/lib/eth_buffer.cc   2008-07-30 
22:48:13 UTC (rev 9062)
@@ -208,6 +208,14 @@
       void *base = (uint8_t *)hdr+hdr->tp_mac;
       size_t len = hdr->tp_len;
       
+      // FYI, (base % 4 == 2) Not what we want given the current FPGA
+      // code.  This means that our uint32_t samples are not 4-byte
+      // aligned.  We'll have to deal with it downstream.
+
+      if (0)
+       fprintf(stderr, "eth_buffer: base = %p  tp_mac = %3d  tp_net = %3d\n",
+               base, hdr->tp_mac, hdr->tp_net);
+
       // Invoke data handler
       data_handler::result r = (*f)(base, len);
       if (!(r & data_handler::KEEP))

Copied: usrp2/branches/features/host-ng/host-ng/lib/rx_sample_handler.cc (from 
rev 9061, usrp2/branches/developers/eb/wip/host-ng/lib/rx_sample_handler.cc)
===================================================================
--- usrp2/branches/features/host-ng/host-ng/lib/rx_sample_handler.cc            
                (rev 0)
+++ usrp2/branches/features/host-ng/host-ng/lib/rx_sample_handler.cc    
2008-07-30 22:48:13 UTC (rev 9062)
@@ -0,0 +1,27 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 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/rx_sample_handler.h>
+
+usrp2::rx_sample_handler::~rx_sample_handler()
+{
+  // nop
+}

Modified: usrp2/branches/features/host-ng/host-ng/lib/usrp2.cc
===================================================================
--- usrp2/branches/features/host-ng/host-ng/lib/usrp2.cc        2008-07-30 
21:56:27 UTC (rev 9061)
+++ usrp2/branches/features/host-ng/host-ng/lib/usrp2.cc        2008-07-30 
22:48:13 UTC (rev 9062)
@@ -45,6 +45,8 @@
     // NOP
   }
   
+  // Receive
+
   bool 
   usrp2::set_rx_gain(double gain)
   {
@@ -76,7 +78,7 @@
   }
   
   bool
-  usrp2::rx_samples(unsigned int channel, data_handler *handler)
+  usrp2::rx_samples(unsigned int channel, rx_sample_handler *handler)
   {
     return d_impl->rx_samples(channel, handler);
   }
@@ -99,4 +101,33 @@
     return d_impl->rx_missing();
   }
 
+  // Transmit
+
+  bool 
+  usrp2::set_tx_gain(double gain)
+  {
+    return d_impl->set_tx_gain(gain);
+  }
+  
+  bool
+  usrp2::set_tx_center_freq(double frequency, tune_result *result)
+  {
+    return d_impl->set_tx_center_freq(frequency, result);
+  }
+  
+  bool
+  usrp2::set_tx_interp(int interpolation_factor)
+  {
+    return d_impl->set_tx_interp(interpolation_factor);
+  }
+  
+  bool
+  usrp2::set_tx_scale_iq(int scale_i, int scale_q)
+  {
+    return d_impl->set_tx_scale_iq(scale_i, scale_q);
+  }
+  
+
+
+
 } // namespace usrp2

Modified: usrp2/branches/features/host-ng/host-ng/lib/usrp2_impl.cc
===================================================================
--- usrp2/branches/features/host-ng/host-ng/lib/usrp2_impl.cc   2008-07-30 
21:56:27 UTC (rev 9061)
+++ usrp2/branches/features/host-ng/host-ng/lib/usrp2_impl.cc   2008-07-30 
22:48:13 UTC (rev 9062)
@@ -34,6 +34,7 @@
 #include <iostream>
 #include <stdio.h>
 #include <stddef.h>
+#include <assert.h>
 
 #define USRP2_IMPL_DEBUG 0
 #if USRP2_IMPL_DEBUG
@@ -42,6 +43,9 @@
 #define DEBUG_LOG(x)
 #endif
 
+static const int DEFAULT_RX_SCALE = 1024;
+static const int DEFAULT_TX_SCALE = 3000;
+
 namespace usrp2 {
 
   static const double DEF_CMD_TIMEOUT = 0.1;
@@ -76,6 +80,42 @@
   }
 
 
+  /*!
+   * \param p points to fixed header
+   * \param payload_len_in_bytes is length of the fixed hdr and the payload
+   * \param[out] items is set to point to the first uint32 item in the payload
+   * \param[out] nitems is set to the number of uint32 items in the payload
+   * \param[out] md is filled in with the parsed metadata from the frame.
+   */
+  static bool
+  parse_rx_metadata(void *p, size_t payload_len_in_bytes,
+                   uint32_t **items, size_t *nitems_in_uint32s, rx_metadata 
*md)
+  {
+    if (payload_len_in_bytes < sizeof(u2_fixed_hdr_t)) // invalid format
+      return false;
+
+    // FIXME deal with the fact that (p % 4) == 2
+    //assert((((uintptr_t) p) % 4) == 0);              // must be 4-byte 
aligned
+
+    u2_fixed_hdr_t *fh = static_cast<u2_fixed_hdr_t *>(p);
+    
+    // FIXME unaligned loads!
+    md->word0 = u2p_word0(fh);
+    md->timestamp = u2p_timestamp(fh);
+
+    // md->start_of_burst = (md->word0 & XXX) != 0;
+    // md->end_of_burst =   (md->word0 & XXX) != 0;
+    // md->rx_overrun =     (md->word0 & XXX) != 0;
+
+    *items = (uint32_t *)(&fh[1]);
+    size_t nbytes = payload_len_in_bytes - sizeof(u2_fixed_hdr_t);
+    assert((nbytes % sizeof(uint32_t)) == 0);
+    *nitems_in_uint32s = nbytes / sizeof(uint32_t);
+
+    return true;
+  }
+
+
   usrp2::impl::impl(const std::string &ifc, const std::string &addr)
     : d_eth_buf(new eth_buffer()), d_pf(0), d_bg_thread(0), 
d_bg_running(false),
       d_rx_decim(0), d_rx_seqno(-1), d_tx_seqno(0), d_next_rid(0),
@@ -103,6 +143,9 @@
 
     d_bg_thread = new usrp2_thread(this);
     d_bg_thread->start();
+
+    set_rx_scale_iq(DEFAULT_RX_SCALE, DEFAULT_RX_SCALE);       // set workable 
default
+    set_tx_scale_iq(DEFAULT_TX_SCALE, DEFAULT_TX_SCALE);       // set workable 
default
   }
   
   usrp2::impl::~impl()
@@ -186,6 +229,189 @@
     cmd->eop.len = sizeof(cmd->eop);
   }
 
+  void
+  usrp2::impl::init_config_tx_v2_cmd(op_config_tx_v2_cmd *cmd)
+  {
+    memset(cmd, 0, sizeof(*cmd)); 
+    init_etf_hdrs(&cmd->h, d_addr, 0, CONTROL_CHAN, -1);
+    cmd->op.opcode = OP_CONFIG_TX_V2;
+    cmd->op.len = sizeof(cmd->op);
+    cmd->op.rid = d_next_rid++;
+    cmd->eop.opcode = OP_EOP;
+    cmd->eop.len = sizeof(cmd->eop);
+  }
+
+  bool
+  usrp2::impl::transmit_cmd(void *cmd, size_t len, pending_reply *p, double 
secs)
+  {
+    if (p)    
+      d_pending_replies[p->rid()] = p;
+    
+    // Transmit command
+    if (d_eth_buf->tx_frame(cmd, len) != eth_buffer::EB_OK) {
+      d_pending_replies[p->rid()] = 0;
+      return false;
+    }
+
+    int res = 1;
+    if (p)
+      res = p->wait(secs);
+      
+    d_pending_replies[p->rid()] = 0;
+    return res == 1;
+  }
+
+  // ----------------------------------------------------------------
+  //        Background loop: received packet demuxing
+  // ----------------------------------------------------------------
+
+  void
+  usrp2::impl::stop_bg()
+  {
+    d_bg_running = false;
+    d_bg_pending_cond.signal();
+    
+    void *dummy_status;
+    d_bg_thread->join(&dummy_status);  
+  }
+  
+  void
+  usrp2::impl::bg_loop()
+  {
+    d_bg_running = true;
+    while(d_bg_running) {
+      DEBUG_LOG(":");
+      // Receive available frames from ethernet buffer.  Handler will
+      // process control frames, enqueue data packets in channel
+      // rings, and signal blocked API threads
+      int res = d_eth_buf->rx_frames(this, 100); // FIXME magic timeout
+      if (res == eth_buffer::EB_ERROR)
+       break;  
+
+      // Wait for user API thread(s) to process all enqueued packets.
+      // The channel ring thread that decrements d_num_enqueued to zero 
+      // will signal this thread to continue.
+      {
+        omni_mutex_lock l(d_enqueued_mutex);
+        while(d_num_enqueued > 0 && d_bg_running)
+         d_bg_pending_cond.wait();
+      }
+    }
+    d_bg_running = false;
+  }
+  
+  //
+  // passed to eth_buffer::rx_frames
+  //
+  data_handler::result
+  usrp2::impl::operator()(const void *base, size_t len)
+  {
+    u2_eth_samples_t *pkt = (u2_eth_samples_t *)base;
+
+    // FIXME unaligned load!
+    int chan = u2p_chan(&pkt->hdrs.fixed);
+
+    if (chan == CONTROL_CHAN) {                // control packets
+      DEBUG_LOG("c");
+      return handle_control_packet(base, len);
+    }
+    else {                             // data packets
+      return handle_data_packet(base, len);
+    }
+
+    // not reached
+  }
+
+  data_handler::result
+  usrp2::impl::handle_control_packet(const void *base, size_t len)
+  {
+    // point to beginning of payload (subpackets)
+    unsigned char *p = (unsigned char *)base + sizeof(u2_eth_packet_t);
+    
+    // FIXME (p % 4) == 2.  Not good.  Must watch for unaligned loads.
+
+    // FIXME iterate over payload, handling more than a single subpacket.
+    
+    //int opcode = p[0];
+    unsigned int oplen = p[1];
+    unsigned int rid = p[2];
+
+    pending_reply *rp = d_pending_replies[rid];
+    if (rp) {
+      unsigned int buflen = rp->len();
+      if (oplen != buflen) {
+       std::cerr << "usrp2: mismatched command reply length ("
+                 << oplen << " != " << buflen << ")"
+                 << std::endl;
+      }     
+    
+      // Copy reply into caller's buffer
+      memcpy(rp->buffer(), p, std::min(oplen, buflen));
+      rp->signal();
+      d_pending_replies[rid] = 0;
+      return data_handler::RELEASE;
+    }
+
+    // TODO: handle unsolicited, USRP2 initiated, or late replies
+    DEBUG_LOG("l");
+    return data_handler::RELEASE;
+  }
+  
+  data_handler::result
+  usrp2::impl::handle_data_packet(const void *base, size_t len)
+  {
+    u2_eth_samples_t *pkt = (u2_eth_samples_t *)base;
+    d_num_rx_frames++;
+    d_num_rx_bytes += len;
+    
+    /* --- FIXME start of fake transport layer handler --- */
+
+    if (d_rx_seqno != -1) {
+      int expected_seqno = (d_rx_seqno + 1) & 0xFF;
+      int seqno = pkt->hdrs.thdr.seqno; 
+      
+      if (seqno != expected_seqno) {
+       ::write(2, "uS", 2); // missing sequence number
+       int missing = seqno - expected_seqno;
+       if (missing < 0)
+         missing += 256;
+       
+       d_num_rx_overruns++;
+       d_num_rx_missing += missing;
+      }
+    }
+
+    d_rx_seqno = pkt->hdrs.thdr.seqno;
+
+    /* --- end of fake transport layer handler --- */
+
+    // FIXME unaligned load!
+    unsigned int chan = u2p_chan(&pkt->hdrs.fixed);
+
+    if (!d_channel_rings[chan]) {
+      DEBUG_LOG("!");
+      return data_handler::RELEASE;    // discard packet, no channel handler
+    }
+
+    // Strip off ethernet header and transport header and enqueue the rest
+
+    size_t offset = offsetof(u2_eth_samples_t, hdrs.fixed);
+    if (d_channel_rings[chan]->enqueue(&pkt->hdrs.fixed, len-offset)) {
+      inc_enqueued();
+      DEBUG_LOG("+");
+      return data_handler::KEEP;       // channel ring runner will mark frame 
done
+    }
+    else {
+      DEBUG_LOG("!");
+      return data_handler::RELEASE;    // discard, no room in channel ring
+    }          
+    return data_handler::RELEASE;
+  }
+
+  // ----------------------------------------------------------------
+  //                          Receive
+  // ----------------------------------------------------------------
+
   bool 
   usrp2::impl::set_rx_gain(double gain)
   {
@@ -370,146 +596,9 @@
     return success;
   }
   
-  bool
-  usrp2::impl::transmit_cmd(void *cmd, size_t len, pending_reply *p, double 
secs)
-  {
-    if (p)    
-      d_pending_replies[p->rid()] = p;
-    
-    // Transmit command
-    if (d_eth_buf->tx_frame(cmd, len) != eth_buffer::EB_OK) {
-      d_pending_replies[p->rid()] = 0;
-      return false;
-    }
 
-    int res = 1;
-    if (p)
-      res = p->wait(secs);
-      
-    d_pending_replies[p->rid()] = 0;
-    return res == 1;
-  }
-
-  void
-  usrp2::impl::bg_loop()
-  {
-    d_bg_running = true;
-    while(d_bg_running) {
-      DEBUG_LOG(":");
-      // Receive available frames from ethernet buffer.  Handler will
-      // process control frames, enqueue data packets in channel
-      // rings, and signal blocked API threads
-      int res = d_eth_buf->rx_frames(this, 100); // FIXME magic timeout
-      if (res == eth_buffer::EB_ERROR)
-       break;  
-
-      // Wait for user API thread(s) to process all enqueued packets.
-      // The channel ring thread that decrements d_num_enqueued to zero 
-      // will signal this thread to continue.
-      {
-        omni_mutex_lock l(d_enqueued_mutex);
-        while(d_num_enqueued > 0 && d_bg_running)
-         d_bg_pending_cond.wait();
-      }
-    }
-    d_bg_running = false;
-  }
-  
-  data_handler::result
-  usrp2::impl::operator()(const void *base, size_t len)
-  {
-    u2_eth_samples_t *pkt = (u2_eth_samples_t *)base;
-    int chan = u2p_chan(&pkt->hdrs.fixed);
-
-    if (chan == CONTROL_CHAN) {                // control packets
-      DEBUG_LOG("c");
-      return handle_control_packet(base, len);
-    }
-    else {                             // data packets
-      return handle_data_packet(base, len);
-    }
-
-    // not reached
-  }
-
-  data_handler::result
-  usrp2::impl::handle_control_packet(const void *base, size_t len)
-  {
-    // point to beginning of payload (subpackets)
-    unsigned char *p = (unsigned char *)base + sizeof(u2_eth_packet_t);
-    
-    // FIXME iterate over payload, handling more than a single subpacket.
-    
-    //int opcode = p[0];
-    unsigned int oplen = p[1];
-    unsigned int rid = p[2];
-
-    pending_reply *rp = d_pending_replies[rid];
-    if (rp) {
-      unsigned int buflen = rp->len();
-      if (oplen != buflen) {
-       std::cerr << "usrp2: mismatched command reply length ("
-                 << oplen << " != " << buflen << ")"
-                 << std::endl;
-      }     
-    
-      // Copy reply into caller's buffer
-      memcpy(rp->buffer(), p, std::min(oplen, buflen));
-      rp->signal();
-      d_pending_replies[rid] = 0;
-      return data_handler::RELEASE;
-    }
-
-    // TODO: handle unsolicited, USRP2 initiated, or late replies
-    DEBUG_LOG("l");
-    return data_handler::RELEASE;
-  }
-  
-  data_handler::result
-  usrp2::impl::handle_data_packet(const void *base, size_t len)
-  {
-    u2_eth_samples_t *pkt = (u2_eth_samples_t *)base;
-    d_num_rx_frames++;
-    d_num_rx_bytes += len;
-    
-    if (d_rx_seqno != -1) {
-      int expected_seqno = (d_rx_seqno + 1) & 0xFF;
-      int seqno = pkt->hdrs.thdr.seqno; 
-      
-      if (seqno != expected_seqno) {
-       ::write(2, "uS", 2); // missing sequence number
-       int missing = seqno - expected_seqno;
-       if (missing < 0)
-         missing += 256;
-       
-       d_num_rx_overruns++;
-       d_num_rx_missing += missing;
-      }
-    }
-
-    d_rx_seqno = pkt->hdrs.thdr.seqno;
-
-    unsigned int chan = u2p_chan(&pkt->hdrs.fixed);
-    if (!d_channel_rings[chan]) {
-      DEBUG_LOG("!");
-      return data_handler::RELEASE;    // discard packet, no channel handler
-    }
-
-    size_t offset = offsetof(u2_eth_samples_t, samples);
-    if (d_channel_rings[chan]->enqueue(&pkt->samples, len-offset)) {
-      inc_enqueued();
-      DEBUG_LOG("+");
-      return data_handler::KEEP;       // channel ring runner will mark frame 
done
-    }
-    else {
-      DEBUG_LOG("!");
-      return data_handler::RELEASE;    // discard, no room in channel ring
-    }          
-    return data_handler::RELEASE;
-  }
-
   bool
-  usrp2::impl::rx_samples(unsigned int channel, data_handler *handler)
+  usrp2::impl::rx_samples(unsigned int channel, rx_sample_handler *handler)
   {
     if (channel > MAX_CHAN) {
       std::cerr << "usrp2: invalid channel (" << channel
@@ -537,31 +626,120 @@
     
     // Iterate through frames and present to user
     void *p;
-    size_t len;
-    while (rp->dequeue(&p, &len)) {
-      result r = (*handler)(p, len);
+    size_t frame_len_in_bytes;
+    while (rp->dequeue(&p, &frame_len_in_bytes)) {
+      uint32_t        *items;                  // points to beginning of data 
items
+      size_t           nitems_in_uint32s;
+      rx_metadata      md;
+      if (!parse_rx_metadata(p, frame_len_in_bytes, &items, 
&nitems_in_uint32s, &md))
+       return false;
 
-      // Callers are always required to accept a frame, but then to signal when
-      // they are done.
+      bool want_more = (*handler)(items, nitems_in_uint32s, &md);
       d_eth_buf->release_frame(p);
       DEBUG_LOG("-");
       dec_enqueued();
 
-      if (r & data_handler::DONE)
+      if (!want_more)
         break;
     }
-
     return true;
   }
 
-  void
-  usrp2::impl::stop_bg()
+  // ----------------------------------------------------------------
+  //                           Transmit
+  // ----------------------------------------------------------------
+
+  bool 
+  usrp2::impl::set_tx_gain(double gain)
   {
-    d_bg_running = false;
-    d_bg_pending_cond.signal();
+    op_config_tx_v2_cmd cmd;
+    op_config_tx_reply_v2_t reply;
+
+    init_config_tx_v2_cmd(&cmd);
+    cmd.op.valid = htons(CFGV_GAIN);
+    cmd.op.gain = htons(u2_double_to_fxpt_gain(gain));
     
-    void *dummy_status;
-    d_bg_thread->join(&dummy_status);  
+    pending_reply p(cmd.op.rid, &reply, sizeof(reply));
+    if (!transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
+      return false;
+
+    bool success = (ntohx(reply.ok) == 1);
+    return success;
   }
   
+  bool
+  usrp2::impl::set_tx_center_freq(double frequency, tune_result *result)
+  {
+    op_config_tx_v2_cmd cmd;
+    op_config_tx_reply_v2_t reply;
+
+    init_config_tx_v2_cmd(&cmd);
+    cmd.op.valid = htons(CFGV_FREQ);
+    u2_fxpt_freq_t fxpt = u2_double_to_fxpt_freq(frequency);
+    cmd.op.freq_hi = htonl(u2_fxpt_freq_hi(fxpt));
+    cmd.op.freq_lo = htonl(u2_fxpt_freq_lo(fxpt));
+    
+    pending_reply p(cmd.op.rid, &reply, sizeof(reply));
+    if (!transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
+      return false;
+
+    bool success = (ntohx(reply.ok) == 1);
+    if (result && success) {
+      result->baseband_freq =
+        u2_fxpt_freq_to_double( 
+         u2_fxpt_freq_from_hilo(ntohl(reply.baseband_freq_hi), 
+                                ntohl(reply.baseband_freq_lo)));
+
+      result->dxc_freq =
+        u2_fxpt_freq_to_double( 
+         u2_fxpt_freq_from_hilo(ntohl(reply.duc_freq_hi), 
+                                ntohl(reply.duc_freq_lo)));
+
+      result->residual_freq =
+        u2_fxpt_freq_to_double( 
+        u2_fxpt_freq_from_hilo(ntohl(reply.residual_freq_hi), 
+                               ntohl(reply.residual_freq_lo)));
+
+      result->spectrum_inverted = (bool)(ntohx(reply.inverted) == 1);
+    }
+
+    return success;
+  }
+  
+  bool
+  usrp2::impl::set_tx_interp(int interpolation_factor)
+  {
+    op_config_tx_v2_cmd cmd;
+    op_config_tx_reply_v2_t reply;
+
+    init_config_tx_v2_cmd(&cmd);
+    cmd.op.valid = htons(CFGV_INTERP_DECIM);
+    cmd.op.interp = htonl(interpolation_factor);
+    
+    pending_reply p(cmd.op.rid, &reply, sizeof(reply));
+    if (!transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
+      return false;
+
+    bool success = (ntohx(reply.ok) == 1);
+    return success;
+  }
+  
+  bool
+  usrp2::impl::set_tx_scale_iq(int scale_i, int scale_q)
+  {
+    op_config_tx_v2_cmd cmd;
+    op_config_tx_reply_v2_t reply;
+
+    init_config_tx_v2_cmd(&cmd);
+    cmd.op.valid = htons(CFGV_SCALE_IQ);
+    cmd.op.scale_iq = htonl(((scale_i & 0xffff) << 16) | (scale_q & 0xffff));
+    
+    pending_reply p(cmd.op.rid, &reply, sizeof(reply));
+    if (!transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
+      return false;
+
+    bool success = (ntohx(reply.ok) == 1);
+    return success;
+  }
+
 } // namespace usrp2

Modified: usrp2/branches/features/host-ng/host-ng/lib/usrp2_impl.h
===================================================================
--- usrp2/branches/features/host-ng/host-ng/lib/usrp2_impl.h    2008-07-30 
21:56:27 UTC (rev 9061)
+++ usrp2/branches/features/host-ng/host-ng/lib/usrp2_impl.h    2008-07-30 
22:48:13 UTC (rev 9062)
@@ -82,6 +82,7 @@
                       int word0_flags, int chan, uint32_t timestamp);
     void stop_bg();
     void init_config_rx_v2_cmd(op_config_rx_v2_cmd *cmd);
+    void init_config_tx_v2_cmd(op_config_tx_v2_cmd *cmd);
     bool transmit_cmd(void *cmd, size_t len, pending_reply *p, double 
secs=0.0);
     virtual data_handler::result operator()(const void *base, size_t len);
     data_handler::result handle_control_packet(const void *base, size_t len);
@@ -92,15 +93,22 @@
     ~impl();
     
     void bg_loop();
+
     bool set_rx_gain(double gain);
     bool set_rx_center_freq(double frequency, tune_result *result);
     bool set_rx_decim(int decimation_factor);
     bool set_rx_scale_iq(int scale_i, int scale_q);
     bool start_rx_streaming(unsigned int channel, unsigned int 
items_per_frame);
-    bool rx_samples(unsigned int channel, data_handler *handler);
+    bool rx_samples(unsigned int channel, rx_sample_handler *handler);
     bool stop_rx_streaming(unsigned int channel);
     unsigned int rx_overruns() const { return d_num_rx_overruns; }
     unsigned int rx_missing() const { return d_num_rx_missing; }
+
+    bool set_tx_gain(double gain);
+    bool set_tx_center_freq(double frequency, tune_result *result);
+    bool set_tx_interp(int interpolation_factor);
+    bool set_tx_scale_iq(int scale_i, int scale_q);
+
   };
   
 } // namespace usrp2





reply via email to

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