commit-gnuradio
[Top][All Lists]
Advanced

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

[Commit-gnuradio] r7640 - in usrp2/trunk/host: . apps lib


From: eb
Subject: [Commit-gnuradio] r7640 - in usrp2/trunk/host: . apps lib
Date: Mon, 11 Feb 2008 23:15:24 -0700 (MST)

Author: eb
Date: 2008-02-11 23:15:24 -0700 (Mon, 11 Feb 2008)
New Revision: 7640

Added:
   usrp2/trunk/host/apps/rx_streaming_samples.cc
Modified:
   usrp2/trunk/host/apps/
   usrp2/trunk/host/apps/Makefile.am
   usrp2/trunk/host/configure.ac
   usrp2/trunk/host/lib/gri_ethernet.cc
Log:
work-in-progress on streaming samples


Property changes on: usrp2/trunk/host/apps
___________________________________________________________________
Name: svn:ignore
   - *-stamp
*.a
*.bin
*.dump
*.log
*.rom
.deps
.libs
Makefile
Makefile.in
aclocal.m4
autom4te.cache
blink_leds
blink_leds2
build
compile
config.h
config.h.in
config.log
config.status
configure
depcomp
eth_test
gen_eth_packets
ibs_rx_test
ibs_tx_test
install-sh
libtool
ltmain.sh
missing
py-compile
rcv_eth_packets
run_tests.sh
stamp-h1
test1
test_phy_comm
timer_test
buf_ram_test
buf_ram_zero
hello
find_usrps
rx_samples
tx_samples
gen_const
samples.dat
u2_burn_mac_addr

   + *-stamp
*.a
*.bin
*.dump
*.log
*.rom
.deps
.libs
Makefile
Makefile.in
aclocal.m4
autom4te.cache
blink_leds
blink_leds2
build
compile
config.h
config.h.in
config.log
config.status
configure
depcomp
eth_test
gen_eth_packets
ibs_rx_test
ibs_tx_test
install-sh
libtool
ltmain.sh
missing
py-compile
rcv_eth_packets
run_tests.sh
stamp-h1
test1
test_phy_comm
timer_test
buf_ram_test
buf_ram_zero
hello
find_usrps
rx_samples
tx_samples
gen_const
samples.dat
u2_burn_mac_addr
rx_streaming_samples


Modified: usrp2/trunk/host/apps/Makefile.am
===================================================================
--- usrp2/trunk/host/apps/Makefile.am   2008-02-12 03:52:46 UTC (rev 7639)
+++ usrp2/trunk/host/apps/Makefile.am   2008-02-12 06:15:24 UTC (rev 7640)
@@ -24,12 +24,14 @@
 bin_PROGRAMS = \
        find_usrps \
        rx_samples \
+       rx_streaming_samples \
        tx_samples \
        gen_const \
        u2_burn_mac_addr
 
 find_usrps_SOURCES = find_usrps.cc
 rx_samples_SOURCES = rx_samples.cc
+rx_streaming_samples_SOURCES = rx_streaming_samples.cc
 tx_samples_SOURCES = tx_samples.cc
 gen_const_SOURCES = gen_const.cc
 u2_burn_mac_addr = u2_burn_mac_addr.cc

Copied: usrp2/trunk/host/apps/rx_streaming_samples.cc (from rev 7638, 
usrp2/trunk/host/apps/rx_samples.cc)
===================================================================
--- usrp2/trunk/host/apps/rx_streaming_samples.cc                               
(rev 0)
+++ usrp2/trunk/host/apps/rx_streaming_samples.cc       2008-02-12 06:15:24 UTC 
(rev 7640)
@@ -0,0 +1,380 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "usrp2_basic.h"
+#include <iostream>
+#include <complex>
+#include <getopt.h>
+#include <string.h>
+#include "strtod_si.h"
+#include <signal.h>
+#include <stdexcept>
+#include "gri_if_stats.h"
+#include <gr_realtime.h>
+#include <gr_buffer.h>
+#include <omnithread.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+
+
+typedef std::complex<float> fcomplex;
+
+static volatile bool signaled = false;
+static volatile bool stop_writer = false;
+
+static void 
+sig_handler(int sig)
+{
+  signaled = true;
+  stop_writer = true;
+}
+
+static void
+install_sig_handler(int signum,
+                   void (*new_handler)(int))
+{
+  struct sigaction new_action;
+  memset (&new_action, 0, sizeof (new_action));
+
+  new_action.sa_handler = new_handler;
+  sigemptyset (&new_action.sa_mask);
+  new_action.sa_flags = 0;
+
+  if (sigaction (signum, &new_action, 0) < 0){
+    perror ("sigaction (install new)");
+    throw std::runtime_error ("sigaction");
+  }
+}
+
+// ------------------------------------------------------------------------
+
+
+class ringbuffer {
+public:
+  gr_buffer_sptr       d_writer;
+  gr_buffer_reader_sptr        d_reader;
+  omni_semaphore       d_not_full;
+  omni_semaphore       d_not_empty;
+
+  ringbuffer(size_t nsamples);
+  bool touch_and_mlock();
+};
+
+ringbuffer::ringbuffer(size_t nsamples)
+{
+  d_writer = gr_make_buffer(nsamples, sizeof(uint32_t));
+  d_reader = gr_buffer_add_reader(d_writer, 0);
+}
+
+bool
+ringbuffer::touch_and_mlock()
+{
+  size_t pagesize = 4096;
+
+  uint32_t *p = (uint32_t *) d_writer->write_pointer();
+  for (int i = 0; i < d_writer->space_available(); i += pagesize / 
sizeof(uint32_t))
+    p[i] = 0;
+
+  int r = mlockall(MCL_CURRENT | MCL_FUTURE);
+  if (r == -1){
+    perror("mlockall");
+    return false;
+  }
+  return true;
+}
+
+typedef boost::shared_ptr<ringbuffer> ringbuffer_sptr;
+
+// ------------------------------------------------------------------------
+
+class file_writer : public omni_thread
+{
+public:
+  int                  d_fd;
+  ringbuffer_sptr      d_rb;
+
+  file_writer(int fd, ringbuffer_sptr ringbuffer)
+    : d_fd(fd), d_rb(ringbuffer){
+  }
+
+  /*
+   * Invokes the top-level of the new thread (name kind of sucks);
+   */
+  void *run_undetached(void *arg);
+};
+
+void *
+file_writer::run_undetached(void *ignored)
+{
+  while (1){
+    int navail_samples = d_rb->d_reader->items_available();
+
+    if (navail_samples == 0){
+      if (stop_writer)
+       return 0;
+      else {
+       d_rb->d_not_empty.wait();
+       continue;
+      }
+    }
+
+    ::write(d_fd, d_rb->d_reader->read_pointer(), navail_samples * 
sizeof(uint32_t));
+    d_rb->d_reader->update_read_pointer(navail_samples);
+    d_rb->d_not_full.post();
+  }
+}
+
+// ------------------------------------------------------------------------
+
+
+/*
+ * Vectorize me!
+ */
+void
+convert_samples_to_complex(size_t nsamples,
+                          uint32_t *i_samples,
+                          fcomplex *c_samples)
+{
+  uint32_t *p = i_samples;
+  for (size_t i = 0; i < nsamples; i++){
+    int16_t  si = ((int16_t) (p[i] >> 16));
+    int16_t  sq = ((int16_t) (p[i] & 0xffff));
+    c_samples[i] = fcomplex((float) si, (float) sq);
+  }
+}
+
+
+static void
+usage(const char *progname)
+{
+  const char *p = strrchr(progname, '/');      // drop leading directory path
+  if (p)
+    p++;
+
+  if (strncmp(p, "lt-", 3) == 0)               // drop lt- libtool prefix
+    p += 3;
+  
+  fprintf(stderr, "Usage: %s [options]\n\n", p);
+  fprintf(stderr, "Options:\n");
+  fprintf(stderr, "  -h                   show this message and exit\n");
+  fprintf(stderr, "  -e ETH_INTERFACE     specify ethernet interface 
[default=eth0]\n");
+  fprintf(stderr, "  -m MAC_ADDR          mac address of USRP2 HH:HH 
[default=first one found]\n");
+  fprintf(stderr, "  -o OUTPUT_FILE       set output filename 
[default=samples.dat]\n");
+  fprintf(stderr, "  -f FREQ              set frequency to FREQ 
[default=0]\n");
+  fprintf(stderr, "  -d DECIM             set decimation rate to DECIM 
[default=32]\n");
+  fprintf(stderr, "  -N NSAMPLES          total number of samples to receive 
[default=2.5e6]\n");
+  fprintf(stderr, "  -F SAMPLES_PER_FRAME number of samples in each frame 
[default=371]\n");
+  fprintf(stderr, "  -S SCALE             fpga scaling factor for I & Q 
[default=256]\n");
+}
+
+struct pkt_info {
+  int          d_nsamples;
+  int          d_timestamp;
+  unsigned int d_seqno;
+
+  pkt_info(int nsamples, int timestamp, int seqno)
+    : d_nsamples(nsamples),
+      d_timestamp(timestamp),
+      d_seqno(seqno) {}
+};
+
+int
+main(int argc, char **argv)
+{
+
+  // options and their defaults
+  const char *interface = "eth0";
+  const char *mac_addr_str = 0;
+  const char *output_filename = "samples.dat";
+  double freq = 0;
+  int32_t decim = 32;
+  int32_t nsamples = static_cast<int32_t>(2.5e6);
+  int32_t samples_per_frame = 371;
+  int32_t scale = 256;
+
+  int    ch;
+  double tmp;
+  u2_mac_addr_t mac_addr;
+
+  setvbuf(stdout, 0, _IOFBF, 64 * 1024); // make stdout fully buffered
+
+  while ((ch = getopt(argc, argv, "he:m:o:f:d:N:F:S")) != EOF){
+    switch (ch){
+
+    case 'e':
+      interface = optarg;
+      break;
+      
+    case 'm':
+      mac_addr_str = optarg;
+      if (!usrp2_basic::parse_mac_addr(optarg, &mac_addr)){
+       std::cerr << "invalid mac addr: " << optarg << std::endl;
+       usage(argv[0]);
+       exit(1);
+      }
+      break;
+
+    case 'o':
+      output_filename = optarg;
+      break;
+      
+    case 'f':
+      if (!strtod_si(optarg, &freq)){
+       std::cerr << "invalid number: " << optarg << std::endl;
+       usage(argv[0]);
+       exit(1);
+      }
+      break;
+
+    case 'N':
+      if (!strtod_si(optarg, &tmp)){
+       std::cerr << "invalid number: " << optarg << std::endl;
+       usage(argv[0]);
+       exit(1);
+      }
+      nsamples = static_cast<int32_t>(tmp);
+      break;
+
+    case 'F':
+      samples_per_frame = strtol(optarg, 0, 0);
+      break;
+
+    case 'd':
+      decim = strtol(optarg, 0, 0);
+      break;
+
+    case 'S':
+      if (!strtod_si(optarg, &tmp)){
+       std::cerr << "invalid number: " << optarg << std::endl;
+       usage(argv[0]);
+       exit(1);
+      }
+      scale = static_cast<int32_t>(tmp);
+      break;
+      
+    case 'h':
+    default:
+      usage(argv[0]);
+      exit(1);
+    }
+  }
+  
+  if (argc - optind != 0){
+    usage(argv[0]);
+    exit(1);
+  }
+
+  size_t buffer_size = static_cast<size_t>(12.5e6);
+  //buffer_size = (buffer_size + 4095) & ~4095;
+  ringbuffer_sptr rb(new ringbuffer(buffer_size));
+  
+  rb->touch_and_mlock();
+
+  int ofd = 1;                 // stdout
+  if (output_filename){
+    ofd = ::open(output_filename, O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE, 
0664);
+    if (ofd == -1){
+      perror(output_filename);
+      exit (1);
+    }
+  }
+
+  usrp2_basic *u2 = new usrp2_basic();
+
+  if (!u2->open(interface)){
+    std::cerr << "couldn't open " << interface << std::endl;
+    return 0;
+  }
+
+  install_sig_handler(SIGINT, sig_handler);
+  
+  std::vector<op_id_reply_t> r = u2->find_usrps();
+
+  for (size_t i = 0; i < r.size(); i++){
+    std::cout << r[i] << std::endl;
+  }
+
+  if (r.size() == 0){
+    std::cerr << "No USRP2 found.\n";
+    return 1;
+  }
+
+  u2_mac_addr_t which = r[0].addr;     // pick the first one
+
+
+  gr_rt_status_t rt = gr_enable_realtime_scheduling();
+  if (rt != RT_OK)
+    std::cerr << "failed to enable realtime scheduling\n";
+
+
+  // create writer thread
+  class file_writer *writer = new file_writer(ofd, rb);
+  writer->start_undetached();
+  
+
+  if (!u2->start_rx(which, freq, decim, nsamples, samples_per_frame, scale, 
scale)){
+    std::cerr << "start_rx failed\n";
+    return 1;
+  }
+
+
+  long total_samples_recvd = 0;
+
+  while (!signaled && total_samples_recvd < nsamples){
+    u2_eth_samples_t   pkt;
+    
+    // read samples
+    int n = u2->read_samples(which, &pkt);
+    if (n <= 0)
+      break;
+    
+    total_samples_recvd += n;
+
+    // copy the samples into the ring buffer as soon as there's room
+
+    while (rb->d_writer->space_available() < n)
+      rb->d_not_full.wait();
+
+    memcpy(rb->d_writer->write_pointer(),
+          pkt.samples,
+          n * sizeof(uint32_t));
+
+    rb->d_writer->update_write_pointer(n);
+    rb->d_not_empty.post();
+  }
+
+  stop_writer = true;
+  // smp_wmb()
+  rb->d_not_empty.post();      // wake up file writer 
+  
+  if (!u2->stop_rx(which)){
+    std::cerr << "stop_rx failed\n";
+    return 1;
+  }
+
+  void *ignored_result;
+  writer->join(&ignored_result);
+
+  return 0;
+}

Modified: usrp2/trunk/host/configure.ac
===================================================================
--- usrp2/trunk/host/configure.ac       2008-02-12 03:52:46 UTC (rev 7639)
+++ usrp2/trunk/host/configure.ac       2008-02-12 06:15:24 UTC (rev 7640)
@@ -115,7 +115,7 @@
 dnl AC_CHECK_HEADERS(linux/ppdev.h sys/mman.h sys/select.h sys/types.h)
 dnl AC_CHECK_HEADERS(sys/resource.h stdint.h sched.h signal.h sys/syscall.h)
 
-AC_CHECK_HEADERS(arpa/inet.h netinet/in.h byteswap.h sys/select.h)
+AC_CHECK_HEADERS(arpa/inet.h netinet/in.h byteswap.h sys/select.h 
linux/if_packet.h)
 
 dnl Checks for typedefs, structures, and compiler characteristics.
 AC_C_CONST

Modified: usrp2/trunk/host/lib/gri_ethernet.cc
===================================================================
--- usrp2/trunk/host/lib/gri_ethernet.cc        2008-02-12 03:52:46 UTC (rev 
7639)
+++ usrp2/trunk/host/lib/gri_ethernet.cc        2008-02-12 06:15:24 UTC (rev 
7640)
@@ -35,6 +35,9 @@
 
 #include <linux/types.h>
 #include <linux/filter.h>      // packet filter
+#ifdef HAVE_LINUX_IF_PACKET_H
+#include <linux/if_packet.h>   // circular buffer defs for PF_PACKET
+#endif
 
 static int
 open_packet_socket (std::string ifname, int protocol)





reply via email to

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