commit-gnuradio
[Top][All Lists]
Advanced

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

[Commit-gnuradio] r8496 - in usrp2/trunk/host: apps gr-usrp2 lib


From: jcorgan
Subject: [Commit-gnuradio] r8496 - in usrp2/trunk/host: apps gr-usrp2 lib
Date: Sun, 25 May 2008 19:36:47 -0600 (MDT)

Author: jcorgan
Date: 2008-05-25 19:36:46 -0600 (Sun, 25 May 2008)
New Revision: 8496

Added:
   usrp2/trunk/host/gr-usrp2/usrp2_source_raw.cc
   usrp2/trunk/host/gr-usrp2/usrp2_source_raw.h
   usrp2/trunk/host/lib/ring_buffer.h
   usrp2/trunk/host/lib/sample_buffer.cc
   usrp2/trunk/host/lib/sample_buffer.h
   usrp2/trunk/host/lib/usrp2_basic_thread.cc
   usrp2/trunk/host/lib/usrp2_basic_thread.h
   usrp2/trunk/host/lib/usrp2_tune_result.h
Modified:
   usrp2/trunk/host/apps/rx_streaming_samples.cc
   usrp2/trunk/host/gr-usrp2/Makefile.am
   usrp2/trunk/host/gr-usrp2/usrp2.i
   usrp2/trunk/host/gr-usrp2/usrp2_source_base.cc
   usrp2/trunk/host/gr-usrp2/usrp2_source_base.h
   usrp2/trunk/host/gr-usrp2/usrp2_source_c.cc
   usrp2/trunk/host/gr-usrp2/usrp2_source_c.h
   usrp2/trunk/host/lib/Makefile.am
   usrp2/trunk/host/lib/usrp2_basic.cc
   usrp2/trunk/host/lib/usrp2_basic.h
Log:
Merged r8422:8478 from jcorgan/u2 into usrp2 trunk.

Modified: usrp2/trunk/host/apps/rx_streaming_samples.cc
===================================================================
--- usrp2/trunk/host/apps/rx_streaming_samples.cc       2008-05-26 01:22:16 UTC 
(rev 8495)
+++ usrp2/trunk/host/apps/rx_streaming_samples.cc       2008-05-26 01:36:46 UTC 
(rev 8496)
@@ -334,7 +334,7 @@
   class file_writer *writer = new file_writer(ofd, rb);
   writer->start_undetached();
 
-  usrp2_tune_result tune_result;
+  usrp2_tune_result_sptr tune_result;
   
   if (gain != GAIN_NOT_SET){
     if (!u2->set_rx_gain(gain)){
@@ -343,9 +343,9 @@
     }
   }
 
-  if (!u2->set_rx_freq(freq, &tune_result)){
+  if (!(tune_result = u2->set_rx_freq(freq))){
     std::cerr << "set_rx_freq failed\n";
-    return 1;
+    //return 1;
   }
 
   if (!u2->set_rx_decim(decim)){

Modified: usrp2/trunk/host/gr-usrp2/Makefile.am
===================================================================
--- usrp2/trunk/host/gr-usrp2/Makefile.am       2008-05-26 01:22:16 UTC (rev 
8495)
+++ usrp2/trunk/host/gr-usrp2/Makefile.am       2008-05-26 01:36:46 UTC (rev 
8496)
@@ -27,6 +27,7 @@
        usrp2_sink_c.cc \
        usrp2_source_base.cc \
        usrp2_source_c.cc \
+       usrp2_source_raw.cc \
        usrp2_table.cc
 
 libgr_usrp2_la_LIBADD = \
@@ -36,7 +37,8 @@
        usrp2_sink_base.h \
        usrp2_sink_c.h \
        usrp2_source_base.h \
-       usrp2_source_c.h
+       usrp2_source_c.h \
+       usrp2_source_raw.h
        
 noinst_HEADERS = \
        usrp2_table.h

Modified: usrp2/trunk/host/gr-usrp2/usrp2.i
===================================================================
--- usrp2/trunk/host/gr-usrp2/usrp2.i   2008-05-26 01:22:16 UTC (rev 8495)
+++ usrp2/trunk/host/gr-usrp2/usrp2.i   2008-05-26 01:36:46 UTC (rev 8496)
@@ -29,8 +29,12 @@
 #include "gnuradio_swig_bug_workaround.h"      // mandatory bug fix
 #include "usrp2_sink_c.h"
 #include "usrp2_source_c.h"
+#include "usrp2_source_raw.h"
 %}
 
+%include "../lib/usrp2_tune_result.h"
+%template(usrp2_tune_result_sptr) boost::shared_ptr<usrp2_tune_result>;
+
 // ----------------------------------------------------------------
 
 class usrp2_source_base : public gr_sync_block {
@@ -42,6 +46,13 @@
 public:
   ~usrp2_source_base();
 
+  bool set_gain(double gain);
+  usrp2_tune_result_sptr set_freq(double frequency);
+  bool set_decim(int decimation_factor);
+  bool set_scale_iq(int scale_i, int scale_q);
+
+  float adc_rate() const;
+  int decim_rate() const;
 };
 
 // ----------------------------------------------------------------
@@ -64,6 +75,24 @@
 
 // ----------------------------------------------------------------
 
+GR_SWIG_BLOCK_MAGIC(usrp2,source_raw)
+
+usrp2_source_raw_sptr
+usrp2_make_source_raw(const std::string &ifc="eth0", const std::string 
&mac="") 
+  throw (std::runtime_error);
+
+class usrp2_source_raw : public usrp2_source_base {
+
+protected:
+  usrp2_source_raw(const std::string &ifc, const std::string &mac);
+
+public:
+  ~usrp2_source_raw();
+
+};
+
+// ----------------------------------------------------------------
+
 class usrp2_sink_base : public gr_sync_block {
 
 protected:

Modified: usrp2/trunk/host/gr-usrp2/usrp2_source_base.cc
===================================================================
--- usrp2/trunk/host/gr-usrp2/usrp2_source_base.cc      2008-05-26 01:22:16 UTC 
(rev 8495)
+++ usrp2/trunk/host/gr-usrp2/usrp2_source_base.cc      2008-05-26 01:36:46 UTC 
(rev 8496)
@@ -31,6 +31,8 @@
 
 #define USRP2_SOURCE_BASE_DEBUG 1
 
+#define SAMPLES_PER_PACKET 250
+
 usrp2_source_base::usrp2_source_base(const std::string &name,
                                     gr_io_signature_sptr output_signature,
                                     const std::string &ifc,
@@ -66,12 +68,48 @@
 }
 
 bool
+usrp2_source_base::set_gain(double gain)
+{
+  return d_u2->set_rx_gain(gain);
+}
+
+usrp2_tune_result_sptr
+usrp2_source_base::set_freq(double frequency) 
+{
+  return d_u2->set_rx_freq(frequency);
+}
+
+bool
+usrp2_source_base::set_decim(int decimation_factor)
+{
+  return d_u2->set_rx_decim(decimation_factor);
+}
+
+bool
+usrp2_source_base::set_scale_iq(int scale_i, int scale_q)
+{
+  return d_u2->set_rx_scale_iq(scale_i, scale_q);
+}
+
+float
+usrp2_source_base::adc_rate() const
+{
+  return d_u2->adc_rate();
+}
+
+int 
+usrp2_source_base::decim_rate() const
+{
+  return d_u2->rx_decim_rate();
+}
+
+bool
 usrp2_source_base::start()
 {
   if (USRP2_SOURCE_BASE_DEBUG)
     std::cout << "usrp2_source_base: start" << std::endl;
 
-  return true;
+  return d_u2->start_rx_streaming(SAMPLES_PER_PACKET);
 }
 
 bool
@@ -80,7 +118,7 @@
   if (USRP2_SOURCE_BASE_DEBUG)
     std::cout << "usrp2_source_base: stop" << std::endl;
 
-  return true;
+  return d_u2->stop_rx();
 }
 
 usrp2_source_base::~usrp2_source_base ()
@@ -92,5 +130,14 @@
                        gr_vector_const_void_star &input_items,
                        gr_vector_void_star &output_items)
 {
-  return noutput_items;
+  if (USRP2_SOURCE_BASE_DEBUG)
+    ::write(1, "w", 1);
+
+  uint32_t buffer[SAMPLES_PER_PACKET];
+  uint32_t flags = 0; // In the streaming mode that gr-usrp2 uses, these are 
ignored
+
+  int n = d_u2->rx_samples(std::min(noutput_items, SAMPLES_PER_PACKET), 
buffer, &flags);
+  copy_from_usrp2_buffer(buffer, output_items[0], n);
+
+  return n;
 }

Modified: usrp2/trunk/host/gr-usrp2/usrp2_source_base.h
===================================================================
--- usrp2/trunk/host/gr-usrp2/usrp2_source_base.h       2008-05-26 01:22:16 UTC 
(rev 8495)
+++ usrp2/trunk/host/gr-usrp2/usrp2_source_base.h       2008-05-26 01:36:46 UTC 
(rev 8496)
@@ -37,16 +37,26 @@
     throw (std::runtime_error);
 
   usrp2_basic_sptr d_u2;
-
+  
 public:
   ~usrp2_source_base();
   
   virtual bool start();
   virtual bool stop();
 
+  bool set_gain(double gain);
+  usrp2_tune_result_sptr set_freq(double frequency);
+  bool set_decim(int decimation_factor);
+  bool set_scale_iq(int scale_i, int scale_q);
+
+  float adc_rate() const;
+  int decim_rate() const;
+  
   int work(int noutput_items,
           gr_vector_const_void_star &input_items,
           gr_vector_void_star &output_items);
+
+  virtual void copy_from_usrp2_buffer(uint32_t *src, void *dst, int nsamples) 
= 0;
 };
 
 #endif /* INCLUDED_USRP2_SOURCE_BASE_H */

Modified: usrp2/trunk/host/gr-usrp2/usrp2_source_c.cc
===================================================================
--- usrp2/trunk/host/gr-usrp2/usrp2_source_c.cc 2008-05-26 01:22:16 UTC (rev 
8495)
+++ usrp2/trunk/host/gr-usrp2/usrp2_source_c.cc 2008-05-26 01:36:46 UTC (rev 
8496)
@@ -26,7 +26,10 @@
 
 #include <usrp2_source_c.h>
 #include <gr_io_signature.h>
+#include <iostream>
 
+#define USRP2_SOURCE_C_DEBUG 1
+
 usrp2_source_c_sptr
 usrp2_make_source_c(const std::string &ifc,
                    const std::string &mac) 
@@ -47,3 +50,14 @@
 usrp2_source_c::~usrp2_source_c()
 {
 }
+
+void
+usrp2_source_c::copy_from_usrp2_buffer(uint32_t *src, void *dst, int nsamples)
+{
+  gr_complex *out = (gr_complex *)dst;
+  for (int i = 0; i < nsamples; i++) {
+    float re = (int16_t)(src[i] >> 16);
+    float im = (int16_t)(src[i] & 0xFFFF);
+    *out++ = gr_complex(re, im); 
+  }
+}

Modified: usrp2/trunk/host/gr-usrp2/usrp2_source_c.h
===================================================================
--- usrp2/trunk/host/gr-usrp2/usrp2_source_c.h  2008-05-26 01:22:16 UTC (rev 
8495)
+++ usrp2/trunk/host/gr-usrp2/usrp2_source_c.h  2008-05-26 01:36:46 UTC (rev 
8496)
@@ -46,6 +46,8 @@
 
 public:
   ~usrp2_source_c();
+
+  virtual void copy_from_usrp2_buffer(uint32_t *src, void *dst, int nsamples);
 };
 
 #endif /* INCLUDED_USRP2_SOURCE_C_H */

Copied: usrp2/trunk/host/gr-usrp2/usrp2_source_raw.cc (from rev 8478, 
usrp2/branches/developers/jcorgan/u2/host/gr-usrp2/usrp2_source_raw.cc)
===================================================================
--- usrp2/trunk/host/gr-usrp2/usrp2_source_raw.cc                               
(rev 0)
+++ usrp2/trunk/host/gr-usrp2/usrp2_source_raw.cc       2008-05-26 01:36:46 UTC 
(rev 8496)
@@ -0,0 +1,59 @@
+/* -*- 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 GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <usrp2_source_raw.h>
+#include <gr_io_signature.h>
+#include <iostream>
+
+usrp2_source_raw_sptr
+usrp2_make_source_raw(const std::string &ifc,
+                     const std::string &mac) 
+  throw (std::runtime_error)
+{
+  return usrp2_source_raw_sptr(new usrp2_source_raw(ifc, mac));
+}
+
+usrp2_source_raw::usrp2_source_raw(const std::string &ifc,
+                              const std::string &mac) 
+  throw (std::runtime_error)
+  : usrp2_source_base("usrp2_source_raw",
+                     gr_make_io_signature(1, 1, sizeof(uint32_t)),
+                     ifc, mac)
+{
+}
+
+usrp2_source_raw::~usrp2_source_raw()
+{
+}
+
+void
+usrp2_source_raw::copy_from_usrp2_buffer(uint32_t *src, void *dst, int 
nsamples)
+{
+  uint32_t *out = (uint32_t *)dst;
+
+  for (int i = 0; i < nsamples; i++)
+    *out++ = src[i];
+}

Copied: usrp2/trunk/host/gr-usrp2/usrp2_source_raw.h (from rev 8478, 
usrp2/branches/developers/jcorgan/u2/host/gr-usrp2/usrp2_source_raw.h)
===================================================================
--- usrp2/trunk/host/gr-usrp2/usrp2_source_raw.h                                
(rev 0)
+++ usrp2/trunk/host/gr-usrp2/usrp2_source_raw.h        2008-05-26 01:36:46 UTC 
(rev 8496)
@@ -0,0 +1,53 @@
+/* -*- 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 GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_USRP2_SOURCE_RAW_H
+#define INCLUDED_USRP2_SOURCE_RAW_H
+
+#include <usrp2_source_base.h>
+
+class usrp2_source_raw;
+typedef boost::shared_ptr<usrp2_source_raw> usrp2_source_raw_sptr;
+
+usrp2_source_raw_sptr
+usrp2_make_source_raw(const std::string &ifc="eth0",
+                     const std::string &mac="") 
+  throw (std::runtime_error);
+
+class usrp2_source_raw : public usrp2_source_base {
+
+private:
+  friend usrp2_source_raw_sptr
+  usrp2_make_source_raw(const std::string &ifc,
+                     const std::string &mac) throw (std::runtime_error);
+
+protected:
+  usrp2_source_raw(const std::string &ifc="eth0",
+                const std::string &mac="") throw (std::runtime_error);
+
+public:
+  ~usrp2_source_raw();
+
+  virtual void copy_from_usrp2_buffer(uint32_t *src, void *dst, int nsamples);
+};
+
+#endif /* INCLUDED_USRP2_SOURCE_RAW_H */

Modified: usrp2/trunk/host/lib/Makefile.am
===================================================================
--- usrp2/trunk/host/lib/Makefile.am    2008-05-26 01:22:16 UTC (rev 8495)
+++ usrp2/trunk/host/lib/Makefile.am    2008-05-26 01:36:46 UTC (rev 8496)
@@ -31,8 +31,10 @@
        gri_ethernet_pfring.cc \
        gri_if_stats.cc \
        gri_pktfilter.cc \
+       sample_buffer.cc \
        strtod_si.c \
-       usrp2_basic.cc
+       usrp2_basic.cc \
+       usrp2_basic_thread.cc
 
 libpfring_la_SOURCES = \
        pfring.c
@@ -46,6 +48,11 @@
        gri_ethernet_pfring.h \
        gri_if_stats.h \
        gri_pktfilter.h \
+       ring_buffer.h \
+       sample_buffer.h \
        strtod_si.h \
-       usrp2_basic.h
+       usrp2_tune_result.h \
+       usrp2_basic.h \
+       usrp2_basic_thread.h
 
+MOSTLYCLEANFILES = *~ *.loT

Copied: usrp2/trunk/host/lib/ring_buffer.h (from rev 8478, 
usrp2/branches/developers/jcorgan/u2/host/lib/ring_buffer.h)
===================================================================
--- usrp2/trunk/host/lib/ring_buffer.h                          (rev 0)
+++ usrp2/trunk/host/lib/ring_buffer.h  2008-05-26 01:36:46 UTC (rev 8496)
@@ -0,0 +1,89 @@
+/* -*- 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 GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_RING_BUFFER_H
+#define INCLUDED_RING_BUFFER_H
+
+#include <vector>
+#include <cmath>
+
+template <class T> 
+class ring_buffer
+{
+public:
+  ring_buffer(size_t nitems);
+
+  size_t space_available() const;
+  size_t items_available() const;
+  size_t size() const { return d_size; }
+    
+  void write(size_t nitems, const T *items);
+  void read(size_t nitems, T *items);
+  
+private:
+  size_t d_size;
+  size_t d_read_index;
+  size_t d_write_index;
+
+  std::vector<T> d_items;
+};
+
+template<class T>
+ring_buffer<T>::ring_buffer(size_t nitems) 
+  : d_size(pow(2, ceil(log2(nitems+1)))),
+    d_read_index(0),
+    d_write_index(0),
+    d_items(d_size)
+{
+}
+
+template<class T>
+size_t ring_buffer<T>::items_available() const
+{
+  return (d_write_index-d_read_index) & (d_size-1);
+}
+
+template<class T>
+size_t ring_buffer<T>::space_available() const
+{
+  return d_size-items_available()-1;
+}
+
+template<class T>
+void ring_buffer<T>::read(size_t nitems, T *items)
+{
+  for (size_t i=0; i < nitems; i++) {
+    items[i] = d_items[d_read_index];
+    d_read_index = (d_read_index + 1) & (d_size-1);
+  }
+}
+
+template<class T>
+void ring_buffer<T>::write(size_t nitems, const T *items)
+{
+  for (size_t i=0; i < nitems; i++) {
+    d_items[d_write_index] = items[i];
+    d_write_index = (d_write_index+1) & (d_size-1);
+  }
+}
+
+#endif /* INCLUDED_RING_BUFFER_H */

Copied: usrp2/trunk/host/lib/sample_buffer.cc (from rev 8478, 
usrp2/branches/developers/jcorgan/u2/host/lib/sample_buffer.cc)
===================================================================
--- usrp2/trunk/host/lib/sample_buffer.cc                               (rev 0)
+++ usrp2/trunk/host/lib/sample_buffer.cc       2008-05-26 01:36:46 UTC (rev 
8496)
@@ -0,0 +1,94 @@
+/* -*- 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 "sample_buffer.h"
+#include <usrp2_eth_packet.h>
+#include <cstdio>
+#include <cassert>
+
+#define SAMPLE_BUFFER_DEBUG 0
+
+sample_buffer::sample_buffer(size_t nsamples, size_t ndescs)
+  : d_samples(nsamples), 
+    d_descs(ndescs),
+    d_rx_remainder(0),
+    d_not_empty(&d_mutex), 
+    d_not_full(&d_mutex)
+{
+}
+
+void
+sample_buffer::write(size_t nsamples, const uint32_t *samples, uint32_t flags)
+{
+  omni_mutex_lock l(d_mutex);
+  
+  while (is_full_p())
+    d_not_full.wait();
+
+  sample_desc_t desc;
+  desc.nsamples = nsamples;
+  desc.flags = flags;
+  d_descs.write(1, &desc);
+  d_samples.write(nsamples, samples);
+
+  ::write(1, "e", 1); // enqueued
+  d_not_empty.signal();
+}
+
+size_t
+sample_buffer::read(size_t nmax, uint32_t *samples, uint32_t *flags)
+{
+  size_t count = 0, n = 0;
+  
+  while (count < nmax) {
+    omni_mutex_lock l(d_mutex);
+    while (is_empty_p())
+      d_not_empty.wait();
+
+    // Try to read from leftover from last descriptor
+    if (d_rx_remainder > 0) {
+      n = std::min(d_rx_remainder, nmax-count);
+      d_rx_remainder -= n;
+      ::write(1, "p", 1); // partial read
+    }
+    else {
+      // Grab a descriptor out of the queue
+      sample_desc_t desc;
+      d_descs.read(1, &desc);
+      n = std::min(nmax-count, desc.nsamples);
+      d_rx_remainder = desc.nsamples-n;
+      if (flags)
+        *flags |= desc.flags;
+      ::write(1, "d", 1); // dequeue
+    }
+    
+    d_samples.read(n, &samples[count]);
+    count += n;
+
+    d_not_full.signal();
+
+    if (flags && (*flags & U2P_TX_END_OF_BURST))
+       return count;
+  }
+
+  return count;
+}

Copied: usrp2/trunk/host/lib/sample_buffer.h (from rev 8478, 
usrp2/branches/developers/jcorgan/u2/host/lib/sample_buffer.h)
===================================================================
--- usrp2/trunk/host/lib/sample_buffer.h                                (rev 0)
+++ usrp2/trunk/host/lib/sample_buffer.h        2008-05-26 01:36:46 UTC (rev 
8496)
@@ -0,0 +1,87 @@
+/* -*- 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_SAMPLE_BUFFER_H
+#define INCLUDED_SAMPLE_BUFFER_H
+
+#include "ring_buffer.h"
+#include <omnithread.h>
+
+typedef struct sample_desc
+{
+  size_t nsamples;
+  uint32_t flags;
+}
+sample_desc_t;
+
+typedef class sample_buffer
+{
+private:
+  ring_buffer<uint32_t> d_samples;
+  ring_buffer<sample_desc_t> d_descs;
+  size_t d_rx_remainder;
+  
+  omni_mutex d_mutex;
+  omni_condition d_not_empty;
+  omni_condition d_not_full;
+
+public:
+  /*!
+   * Create a sample buffer that can hold at least nsamples of data and
+   * ndescs of descriptors.
+   */ 
+  sample_buffer(size_t nsamples, size_t ndescs);
+
+  /*!
+   * Write nsamples of data into buffer and associate flags with this range.
+   * If space is not available, calling thread will block until it is.
+   */  
+  void write(size_t nsamples, const uint32_t *samples, uint32_t flags);
+
+  /*!
+   * Read no more than nsamples of data from buffer.  If samples are available,
+   * read as many as possible until either a) nsamples is reached, or b) the
+   * associated flags for the range has U2P_TX_END_OF_BURST set.  If no 
samples at
+   * all are available, the calling thread will block until they are.
+   *
+   * Returns number of samples read and places the OR of the associated flags
+   * into the 'flags' parameter, if not NULL.
+   */
+  size_t read(size_t nmax, uint32_t *samples, uint32_t *flags);
+
+  /*!
+   * Returns true if there are no samples available for reading.
+   */
+  bool is_empty_p() const { return d_rx_remainder == 0 && 
+                                   d_descs.items_available() == 0; }
+  
+  /*!
+   * Returns true if there is either no space available for samples OR there
+   * is no space available for enqueuing descriptors.
+   */
+  bool is_full_p() const { return d_descs.space_available() == 0 |
+                                  d_samples.space_available() == 0; }
+
+  /*!
+   * Returns sample space available if not full.
+   */
+  size_t space_available() const { return is_full_p() ? 0 : 
d_samples.space_available(); }
+}
+sample_buffer_t;
+
+#endif /* INCLUDED_SAMPLE_BUFFER_H */

Modified: usrp2/trunk/host/lib/usrp2_basic.cc
===================================================================
--- usrp2/trunk/host/lib/usrp2_basic.cc 2008-05-26 01:22:16 UTC (rev 8495)
+++ usrp2/trunk/host/lib/usrp2_basic.cc 2008-05-26 01:36:46 UTC (rev 8496)
@@ -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
@@ -20,14 +20,17 @@
 #include "config.h"
 #endif
 #include "usrp2_basic.h"
+#include "usrp2_basic_thread.h"
 #include "gri_ethernet.h"
 #include "gri_ethernet_pfring.h"       // FIXME
 #include "gri_pktfilter.h"
 #include <usrp2_types.h>
+#include <usrp2_eth_packet.h>
 #include <iostream>
 #include <stdexcept>
 #include <math.h>
-#include <time.h>      // debug
+#include <time.h>
+#include <errno.h>
 
 #ifdef HAVE_SYS_SELECT_H
 #include <sys/select.h>
@@ -54,6 +57,10 @@
 #define MAX_PKTLEN 1512          // biggest thing USRP2 can swallow
                           //   (14-byte ethernet hdr + 1500 byte payload)
 
+usrp2_tune_result::~usrp2_tune_result()
+{
+}
+
 usrp2_basic_sptr 
 usrp2_make_basic(const std::string &ifc, const u2_mac_addr_t &addr)
 {
@@ -61,7 +68,9 @@
 }
 
 usrp2_basic::usrp2_basic(const std::string &ifc, const u2_mac_addr_t &addr)
-  : d_ethernet(new GRI_ETHERNET()), d_pf(0), d_seqno(0), d_next_rid(0)
+  : d_ethernet(new GRI_ETHERNET()), d_pf(0), d_seqno(0), d_next_rid(0),
+    d_rx_started(false), d_tx_started(false), d_thread(0), 
+    d_rx_samples(65535, 255), d_tx_samples(65535, 255)
 {
   if (USRP2_BASIC_DEBUG)
     std::cerr << "usrp2_basic: constructor" << std::endl;
@@ -262,9 +271,10 @@
   return true;
 }
 
-bool
-usrp2_basic::set_rx_freq(double freq, usrp2_tune_result *result)
+usrp2_tune_result_sptr
+usrp2_basic::set_rx_freq(double freq)
 {
+  usrp2_tune_result_sptr result(new usrp2_tune_result());
   uint8_t      pktbuf[MAX_PKTLEN];
   memset(pktbuf, 0, sizeof(pktbuf));
 
@@ -290,15 +300,11 @@
   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 (d_ethernet->write_packet(c, len) == len) {
+    // FIXME: wait for corresponding reply, set tune result members
+  }
 
-  // FIXME wait for corresponding reply, etc.
-
-  if (result)
-    memset(result, 0, sizeof(*result));
-
-  return true;
+  return result;
 }
 
 bool
@@ -332,6 +338,7 @@
 
   // FIXME wait for corresponding reply, etc.
 
+  d_rx_decim = decimation_factor;
   return true;
 }
 
@@ -398,6 +405,9 @@
   if (d_ethernet->write_packet(c, len) != len)
     return false;
 
+  d_rx_started = true;
+  d_thread = new usrp2_basic_thread(this);
+  d_thread->start();
   return true;
 }
 
@@ -421,6 +431,10 @@
   if (d_ethernet->write_packet(c, len) != len)
     return false;
 
+  d_thread->stop();
+  d_rx_started = false;
+
+  d_thread = 0; // pthread derived objects delete themselves
   return true;
 }
 
@@ -582,31 +596,33 @@
 }
 
 int
-usrp2_basic::read_raw_samples(u2_eth_samples_t *pkt)
+usrp2_basic::read_raw_samples(u2_eth_samples_t *pkt, int nmax)
 {
-  int len = d_ethernet->read_packet(pkt, sizeof(*pkt));
-  // printf("read_packet = %d\n", len);
+  int nmaxbytes = (nmax == -1) ? sizeof(*pkt) : nmax*sizeof(uint32_t) + 
sizeof(u2_eth_packet_t);
+  int readsize = std::min(int(sizeof(*pkt)), nmaxbytes);
+  int len = d_ethernet->read_packet(pkt, readsize);
 
   if (len <= 0)
     return len;
 
   // FIXME check channel
 
-
-  // shouldn't happen
-  if ((size_t) len < sizeof(u2_eth_packet_t))
+  if ((size_t) len < sizeof(u2_eth_packet_t)) {
+    printf("usrp2_basic::read_raw_samples: short read, len=%d\n", len);
     return 0;
+  }   
 
-  // convert to samples
   int r = (len - sizeof(u2_eth_packet_t)) / sizeof(uint32_t);
-  // printf("read_raw_samples = %d\n", r);
+  if (USRP2_BASIC_DEBUG)
+    printf("usrp2_basic::read_raw_samples: nmax=%d nmaxbytes=%d readsize=%d 
len=%d r=%d\n", 
+           nmax, nmaxbytes, readsize, len, r);
   return r;
 }
 
 int
-usrp2_basic::read_samples(u2_eth_samples_t *pkt)
+usrp2_basic::read_samples(u2_eth_samples_t *pkt, int nmax)
 {
-  int r = read_raw_samples(pkt);
+  int r = read_raw_samples(pkt, nmax);
 
 #ifndef WORDS_BIGENDIAN
   for (int i = 0; i < r; i++)
@@ -819,3 +835,93 @@
   return memcmp(&a, &b, sizeof(u2_mac_addr_t)) == 0;
 }
 
+void usrp2_basic::loop()
+{
+  fd_set read_fds, write_fds;
+  FD_ZERO(&read_fds);
+  FD_ZERO(&write_fds);
+
+  if (d_rx_started)
+    FD_SET(d_ethernet->fd(), &read_fds);
+  if (d_tx_started)
+    FD_SET(d_ethernet->fd(), &write_fds);
+    
+  struct timeval timeout;
+  timeout.tv_sec = 0;
+  timeout.tv_usec = 100 * 1000;        // 100 ms
+
+  ::write(1, "S", 1); // select
+  int r = select(d_ethernet->fd()+1, &read_fds, &write_fds, 0, &timeout);
+  if (r > 0) {       // Socket available for read or for write
+    if (FD_ISSET(d_ethernet->fd(), &read_fds)) {
+      ::write(1, "r", 1); // data to read()
+      rx_frames();
+    }
+    
+    if (FD_ISSET(d_ethernet->fd(), &write_fds)) {
+      ::write(1, "r", 1); // data to write()
+      tx_frames();
+    }
+  }
+  else if (r == 0) { 
+    ::write(1, "T", 1);   // socket timeout
+    return;
+  }
+  else {         
+    if (errno == EINTR)
+      ::write(1, "I", 1); // interrupted system call
+    else
+      ::write(1, "!", 1); // error on socket
+    return;
+  }
+}
+
+void
+usrp2_basic::rx_frames()
+{
+  uint8_t pktbuf[MAX_PKTLEN];
+  memset(pktbuf, 0, sizeof(pktbuf));
+
+  int len;
+  while (1) {
+    len = d_ethernet->read_packet_dont_block(pktbuf, sizeof(pktbuf));
+    if (len < 0) {
+      ::write(1, "!", 1); // error
+      return;
+    } 
+    else if (len == 0) {
+      ::write(1, "|", 1); // no more frames
+      return;
+    }
+    else if ((size_t)len < sizeof(u2_eth_packet_t)) {
+      ::write(1, "<", 1); // short frame
+    }
+    else
+      ::write(1, "R", 1); // rx ok
+
+    u2_eth_packet_t *p = (u2_eth_packet_t *)pktbuf;
+    if (u2p_chan(&p->fixed) == CONTROL_CHAN) {
+      ::write(1, "-", 1); // ignore (FIXME: multiple channels, control channel)
+      continue;
+    }    
+
+    u2_eth_samples_t *s = (u2_eth_samples_t *)pktbuf;
+    size_t plen = (len-sizeof(s->hdrs))/sizeof(uint32_t);
+    if (d_rx_samples.space_available() < plen) {
+      ::write(1, "uO", 2); // overrun
+      return;
+    }
+
+    d_rx_samples.write(plen, (uint32_t *)(&s->samples[0]), 0);
+  }   
+}
+
+void
+usrp2_basic::tx_frames()
+{
+}
+
+size_t usrp2_basic::rx_samples(size_t nmax, uint32_t *samples, uint32_t *flags)
+{
+  return d_rx_samples.read(nmax, samples, flags);
+}

Modified: usrp2/trunk/host/lib/usrp2_basic.h
===================================================================
--- usrp2/trunk/host/lib/usrp2_basic.h  2008-05-26 01:22:16 UTC (rev 8495)
+++ usrp2/trunk/host/lib/usrp2_basic.h  2008-05-26 01:36:46 UTC (rev 8496)
@@ -23,6 +23,8 @@
 #include <boost/shared_ptr.hpp>
 #include <vector>
 #include "usrp2_eth_packet.h"
+#include "usrp2_tune_result.h"
+#include "sample_buffer.h"
 
 class gri_ethernet;
 class gri_ethernet_pfring;
@@ -30,35 +32,18 @@
 
 #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;
 typedef boost::shared_ptr<usrp2_basic> usrp2_basic_sptr;
 
+class usrp2_basic_thread;
+
 usrp2_basic_sptr usrp2_make_basic(const std::string &ifc, const u2_mac_addr_t 
&addr);
 
 class usrp2_basic : public boost::noncopyable
 {
 private:
   friend usrp2_basic_sptr usrp2_make_basic(const std::string &ifc, const 
u2_mac_addr_t &addr);
+  friend class usrp2_basic_thread;
   usrp2_basic(const std::string &ifc, const u2_mac_addr_t &addr);
   
   GRI_ETHERNET *d_ethernet;
@@ -66,13 +51,24 @@
   int           d_seqno;
   int           d_next_rid;
   u2_mac_addr_t  d_addr;
+  int            d_rx_decim;
+  bool           d_rx_started;
+  bool           d_tx_started;
   
+  usrp2_basic_thread *d_thread;
+  sample_buffer_t d_rx_samples;
+  sample_buffer_t d_tx_samples;
+  
   void init_et_hdrs(u2_eth_packet_t *p, const u2_mac_addr_t &dst);
 
   void init_etf_hdrs(u2_eth_packet_t *p,
                     const u2_mac_addr_t &dst,
                     int word0_flags, int chan, uint32_t timestamp);
 
+  void loop();
+  void rx_frames();
+  void tx_frames();
+  
 public:
   // ---- Static methods ----
 
@@ -130,7 +126,7 @@
    * Rx configuration and control
    */
   bool set_rx_gain(double gain);
-  bool set_rx_freq(double frequency, usrp2_tune_result *result);
+  usrp2_tune_result_sptr set_rx_freq(double frequency);
   bool set_rx_decim(int decimation_factor);
   bool set_rx_scale_iq(int scale_i, int scale_q);
 
@@ -140,6 +136,7 @@
   //! stop streaming Rx samples
   bool stop_rx();
 
+  int rx_decim_rate() const { return d_rx_decim; }
 
   /*
    * Tx configuration and control
@@ -155,7 +152,7 @@
    * \param pkt contains the raw (non-endian corrected) samples
    * \returns number of valid samples in pkt.
    */
-  int read_raw_samples(u2_eth_samples_t *pkt);
+  int read_raw_samples(u2_eth_samples_t *pkt, int nmax = -1);
 
   /*!
    * \brief Read native-endian samples from USRP2.
@@ -163,7 +160,7 @@
    * \param pkt contains native-endian samples.
    * \returns number of valid samples in pkt.
    */
-  int read_samples(u2_eth_samples_t *pkt);
+  int read_samples(u2_eth_samples_t *pkt, int nmax = -1);
 
   /*!
    * \brief Write raw samples to USRP2.
@@ -193,6 +190,14 @@
 
 
   /*!
+   * Receive at most nmax samples.  Returns number of samples actually read,
+   * and places the OR of the sample ranges into the flags variable.
+   *
+   * FIXME: multiple channels
+   */
+  size_t rx_samples(size_t nmax, uint32_t *samples, uint32_t *flags);
+
+  /*!
    * \brief Read FPGA's idea of time
    *
    * N.B., this interface will probably change.
@@ -205,14 +210,13 @@
 
 
   //! Return frequency of master oscillator on USRP2.
-  long  fpga_master_clock_freq () const { return 100000000; }  // 100e6
+  long fpga_master_clock_freq () const { return 100000000; }   // 100e6
 
   //! Return A/D sample rate
   long adc_rate() const { return fpga_master_clock_freq(); }
 
   //! Return D/A sample rate
   long dac_rate() const { return fpga_master_clock_freq(); }
-
 };
 
 std::ostream& operator<<(std::ostream &os, const op_id_reply_t &x);

Copied: usrp2/trunk/host/lib/usrp2_basic_thread.cc (from rev 8478, 
usrp2/branches/developers/jcorgan/u2/host/lib/usrp2_basic_thread.cc)
===================================================================
--- usrp2/trunk/host/lib/usrp2_basic_thread.cc                          (rev 0)
+++ usrp2/trunk/host/lib/usrp2_basic_thread.cc  2008-05-26 01:36:46 UTC (rev 
8496)
@@ -0,0 +1,80 @@
+/* -*- 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 GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <usrp2_basic_thread.h>
+
+#define USRP2_BASIC_THREAD_DEBUG 1
+
+usrp2_basic_thread::usrp2_basic_thread(usrp2_basic *u2) :
+  omni_thread(NULL, PRIORITY_NORMAL),
+  d_u2(u2), d_keep_running(false)
+{
+  if (USRP2_BASIC_THREAD_DEBUG)
+    std::cout << "usrp2_basic_thread: constructor" << std::endl;
+}
+
+usrp2_basic_thread::~usrp2_basic_thread()
+{
+  if (USRP2_BASIC_THREAD_DEBUG)
+    std::cout << "usrp2_basic_thread: destructor" << std::endl;
+
+  if (d_keep_running)
+    stop();
+
+  // we don't own this, so don't delete
+  d_u2 = 0;
+}
+
+void usrp2_basic_thread::start()
+{
+  if (USRP2_BASIC_THREAD_DEBUG)
+    std::cout << "usrp2_basic_thread::start() "
+             << this << std::endl;
+  d_keep_running = true;
+  start_undetached();
+}
+
+void *
+usrp2_basic_thread::run_undetached(void *arg)
+{
+  // This is the first code to run in the new thread context.
+  while(d_keep_running)
+    d_u2->loop();
+
+  return 0;
+}
+
+void
+usrp2_basic_thread::stop()
+{
+  if (USRP2_BASIC_THREAD_DEBUG)
+    std::cout << "usrp2_basic_thread::stop() "
+             << this << std::endl;
+  d_keep_running = false;
+
+  void *dummy_status;
+  join(&dummy_status);  
+}

Copied: usrp2/trunk/host/lib/usrp2_basic_thread.h (from rev 8478, 
usrp2/branches/developers/jcorgan/u2/host/lib/usrp2_basic_thread.h)
===================================================================
--- usrp2/trunk/host/lib/usrp2_basic_thread.h                           (rev 0)
+++ usrp2/trunk/host/lib/usrp2_basic_thread.h   2008-05-26 01:36:46 UTC (rev 
8496)
@@ -0,0 +1,46 @@
+/* -*- 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 GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_USRP2_BASIC_THREAD_H
+#define INCLUDED_USRP2_BASIC_THREAD_H
+
+#include <omnithread.h>
+#include <usrp2_basic.h>
+#include <iostream>
+
+class usrp2_basic_thread : public omni_thread
+{
+private:
+  usrp2_basic *d_u2;    
+  bool         d_keep_running;
+
+public:
+  usrp2_basic_thread(usrp2_basic *u2);
+  ~usrp2_basic_thread();
+
+  void start();
+  void stop();
+
+  virtual void *run_undetached(void *arg);
+};
+
+#endif /* INCLUDED_USRP2_BASIC_THREAD_H */

Copied: usrp2/trunk/host/lib/usrp2_tune_result.h (from rev 8478, 
usrp2/branches/developers/jcorgan/u2/host/lib/usrp2_tune_result.h)
===================================================================
--- usrp2/trunk/host/lib/usrp2_tune_result.h                            (rev 0)
+++ usrp2/trunk/host/lib/usrp2_tune_result.h    2008-05-26 01:36:46 UTC (rev 
8496)
@@ -0,0 +1,46 @@
+/* -*- 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_TUNE_RESULT_H
+#define INCLUDED_USRP2_TUNE_RESULT_H
+
+#include <boost/shared_ptr.hpp>
+
+class usrp2_tune_result
+{
+public:
+  // 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) {}
+  ~usrp2_tune_result();
+};
+
+typedef boost::shared_ptr<usrp2_tune_result> usrp2_tune_result_sptr;
+
+#endif /* INCLUDED_USRP2_TUNE_RESULT_H */





reply via email to

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