Merge branch 'master' into wip/burx_support

* master: (39 commits)
  Add gru.hexshort to deal with short hex constants
  Assign USB PID for Hans de Bok
  Add missing buffer allocator hint to gr_ofdm_sampler.cc
  Really fix the missing include for boost::bind
  gr-wxgui: Added additional color table entries
  Missed updates for omnithread/mblock removal
  Remove omnithreads library.
  Remove mblock library.  We hardly knew 'ye.
  Convert gr-audio-portaudio to Boost via gruel
  Further updates for removing omnithreads
  Update build configuration for OSX omnithreads changeover
  Add missing include file for boost::bind
  Convert gcell to use boost::threads instead of omnithread.
  Fix sequence error indication after stopping then restarting streaming on USRP2.
  initial move from mld_threads to gruel:: namespace threads and such
  Initial changes to remove mld_thread and instead use gruel:: namespace classes
  Fixing doxygen warnings from arb_resampler. Also, removed set_taps from public
  Fixing doxygen warnings from channelizer block.
  Fixing documentation to get rid of doxygen warnings.
  Adding documentation for fff version of othe PFB clock sync algorithm.
  ...
This commit is contained in:
Johnathan Corgan 2010-05-11 18:00:19 -07:00
commit fa46b23ddb
61 changed files with 111 additions and 12726 deletions

View File

@ -55,6 +55,8 @@
#define USB_PID_FSF_BDALE_8 0x0012 // Bdale Garbee <bdale@gag.com>
#define USB_PID_FSF_BDALE_9 0x0013 // Bdale Garbee <bdale@gag.com>
#define USB_PID_FSF_HPSDR_HERMES 0x0014 // HPSDR Hermes
#define USB_PID_FSF_THINKRF 0x0015 // Catalin Patulea <catalin.patulea@thinkrf.com>
#define USB_PID_FSF_MSA 0x0016 // Hans de Bok <hdbok@dionaea.demon.nl> Scotty's Modular Spectrum Analyzer
#define USB_PID_FSF_LBNL_UXO 0x0018 // http://recycle.lbl.gov/~ldoolitt/uxo/

View File

@ -146,7 +146,7 @@ def build_shell_script (out, ihx_filename, rev, prefix):
out.write ('#!/bin/sh\n')
out.write ('usrper -x load_firmware ' + prefix + '/share/usrp/rev%d/std.ihx\n' % rev)
out.write ('sleep 1\n')
out.write ('sleep 2\n')
# print "len(image) =", len(image)
@ -161,7 +161,7 @@ def build_shell_script (out, ihx_filename, rev, prefix):
(i2c_addr, rom_addr, ''.join (hex_image[0:l])))
hex_image = hex_image[l:]
rom_addr = rom_addr + l
out.write ('sleep 1\n')
out.write ('sleep 2\n')
if __name__ == '__main__':
usage = "usage: %prog -p PREFIX -r REV [options] bootfile.ihx"

View File

@ -1,7 +1,7 @@
#
# USRP - Universal Software Radio Peripheral
#
# Copyright (C) 2003,2004,2006,2007,2008,2009 Free Software Foundation, Inc.
# Copyright (C) 2003,2004,2006,2007,2008,2009,2010 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
@ -31,10 +31,10 @@ libusrp_la_common_LIBADD = \
$(BOOST_THREAD_LIB) \
../misc/libmisc.la
# darwin fusb requires omnithreads
# darwin fusb requires gruel (for threading)
if FUSB_TECH_darwin
AM_CPPFLAGS = $(common_INCLUDES) $(OMNITHREAD_INCLUDES) $(BOOST_CPPFLAGS) $(WITH_INCLUDES)
libusrp_la_LIBADD = $(libusrp_la_common_LIBADD) $(OMNITHREAD_LA)
AM_CPPFLAGS = $(common_INCLUDES) $(GRUEL_INCLUDES) $(BOOST_CPPFLAGS) $(WITH_INCLUDES)
libusrp_la_LIBADD = $(libusrp_la_common_LIBADD) $(GRUEL_LA)
libusrp_la_LDFLAGS = $(libusrp_la_common_LDFLAGS) -framework CoreFoundation
else
AM_CPPFLAGS = $(common_INCLUDES) $(BOOST_CPPFLAGS) $(WITH_INCLUDES)
@ -70,7 +70,6 @@ darwin_CODE = \
circular_buffer.h \
circular_linked_list.h \
darwin_libusb.h \
mld_threads.h \
usrp_prims_libusb0.cc

View File

@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
* Copyright 2006,2009 Free Software Foundation, Inc.
* Copyright 2006,2009,2010 Free Software Foundation, Inc.
*
* This file is part of GNU Radio.
*
@ -23,7 +23,7 @@
#ifndef _CIRCULAR_BUFFER_H_
#define _CIRCULAR_BUFFER_H_
#include "mld_threads.h"
#include <gruel/thread.h>
#include <iostream>
#include <stdexcept>
@ -37,7 +37,8 @@
#define DEBUG(X) do{} while(0);
#endif
template <class T> class circular_buffer
template <class T>
class circular_buffer
{
private:
// the buffer to use
@ -48,8 +49,9 @@ private:
size_t d_n_avail_write_I, d_n_avail_read_I;
// stuff to control access to class internals
mld_mutex_ptr d_internal;
mld_condition_ptr d_readBlock, d_writeBlock;
gruel::mutex* d_internal;
gruel::condition_variable* d_readBlock;
gruel::condition_variable* d_writeBlock;
// booleans to decide how to control reading, writing, and aborting
bool d_doWriteBlock, d_doFullRead, d_doAbort;
@ -94,16 +96,14 @@ public:
};
inline size_t n_avail_write_items () {
d_internal->lock ();
gruel::scoped_lock l (*d_internal);
size_t retVal = d_n_avail_write_I;
d_internal->unlock ();
return (retVal);
};
inline size_t n_avail_read_items () {
d_internal->lock ();
gruel::scoped_lock l (*d_internal);
size_t retVal = d_n_avail_read_I;
d_internal->unlock ();
return (retVal);
};
@ -120,13 +120,13 @@ public:
// create a mutex to handle contention of shared resources;
// any routine needed access to shared resources uses lock()
// before doing anything, then unlock() when finished.
d_internal = new mld_mutex ();
d_internal = new gruel::mutex ();
// link the internal mutex to the read and write conditions;
// when wait() is called, the internal mutex will automatically
// be unlock()'ed. Upon return (from a signal() to the condition),
// be unlock()'ed. Upon return (from a notify_one() to the condition),
// the internal mutex will be lock()'ed.
d_readBlock = new mld_condition (d_internal);
d_writeBlock = new mld_condition (d_internal);
d_readBlock = new gruel::condition_variable ();
d_writeBlock = new gruel::condition_variable ();
};
/*
@ -167,9 +167,8 @@ public:
if (!buf)
throw std::runtime_error ("circular_buffer::enqueue(): "
"input buffer is NULL.\n");
d_internal->lock ();
gruel::scoped_lock l (*d_internal);
if (d_doAbort) {
d_internal->unlock ();
return (2);
}
// set the return value to 1: success; change if needed
@ -178,11 +177,11 @@ public:
if (d_doWriteBlock) {
while (bufLen_I > d_n_avail_write_I) {
DEBUG (std::cerr << "enqueue: #len > #a, waiting." << std::endl);
// wait will automatically unlock() the internal mutex
d_writeBlock->wait ();
// and lock() it here.
// wait; will automatically unlock() the internal mutex via
// the scoped lock
d_writeBlock->wait (l);
// and auto re-lock() it here.
if (d_doAbort) {
d_internal->unlock ();
DEBUG (std::cerr << "enqueue: #len > #a, aborting." << std::endl);
return (2);
}
@ -208,8 +207,7 @@ public:
d_writeNdx_I += n_now_I;
d_n_avail_read_I += bufLen_I;
d_n_avail_write_I -= bufLen_I;
d_readBlock->signal ();
d_internal->unlock ();
d_readBlock->notify_one ();
return (retval);
};
@ -255,19 +253,18 @@ public:
throw std::runtime_error ("circular_buffer::dequeue()");
}
d_internal->lock ();
gruel::scoped_lock l (*d_internal);
if (d_doAbort) {
d_internal->unlock ();
return (2);
}
if (d_doFullRead) {
while (d_n_avail_read_I < l_bufLen_I) {
DEBUG (std::cerr << "dequeue: #a < #len, waiting." << std::endl);
// wait will automatically unlock() the internal mutex
d_readBlock->wait ();
// and lock() it here.
// wait; will automatically unlock() the internal mutex via
// the scoped lock
d_readBlock->wait (l);
// and re-lock() it here.
if (d_doAbort) {
d_internal->unlock ();
DEBUG (std::cerr << "dequeue: #a < #len, aborting." << std::endl);
return (2);
}
@ -276,11 +273,11 @@ public:
} else {
while (d_n_avail_read_I == 0) {
DEBUG (std::cerr << "dequeue: #a == 0, waiting." << std::endl);
// wait will automatically unlock() the internal mutex
d_readBlock->wait ();
// and lock() it here.
// wait; will automatically unlock() the internal mutex via
// the scoped lock
d_readBlock->wait (l);
// and re-lock() it here.
if (d_doAbort) {
d_internal->unlock ();
DEBUG (std::cerr << "dequeue: #a == 0, aborting." << std::endl);
return (2);
}
@ -303,17 +300,15 @@ public:
*bufLen_I = l_bufLen_I;
d_n_avail_read_I -= l_bufLen_I;
d_n_avail_write_I += l_bufLen_I;
d_writeBlock->signal ();
d_internal->unlock ();
d_writeBlock->notify_one ();
return (1);
};
void abort () {
d_internal->lock ();
gruel::scoped_lock l (*d_internal);
d_doAbort = true;
d_writeBlock->signal ();
d_readBlock->signal ();
d_internal->unlock ();
d_writeBlock->notify_one ();
d_readBlock->notify_one ();
};
};

View File

@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
* Copyright 2006,2009 Free Software Foundation, Inc.
* Copyright 2006,2009,2010 Free Software Foundation, Inc.
*
* This file is part of GNU Radio.
*
@ -23,7 +23,7 @@
#ifndef _CIRCULAR_LINKED_LIST_H_
#define _CIRCULAR_LINKED_LIST_H_
#include <mld_threads.h>
#include <gruel/thread.h>
#include <stdexcept>
#define __INLINE__ inline
@ -110,8 +110,8 @@ template <class T> class circular_linked_list {
private:
s_node_ptr d_current, d_iterate, d_available, d_inUse;
size_t d_n_nodes, d_n_used;
mld_mutex_ptr d_internal;
mld_condition_ptr d_ioBlock;
gruel::mutex* d_internal;
gruel::condition_variable* d_ioBlock;
public:
circular_linked_list (size_t n_nodes) {
@ -150,8 +150,8 @@ public:
}
}
d_available = d_current = l_prev;
d_ioBlock = new mld_condition ();
d_internal = d_ioBlock->mutex ();
d_ioBlock = new gruel::condition_variable ();
d_internal = new gruel::mutex ();
};
~circular_linked_list () {
@ -163,19 +163,21 @@ public:
}
delete d_ioBlock;
d_ioBlock = NULL;
delete d_internal;
d_internal = NULL;
d_available = d_inUse = d_iterate = d_current = NULL;
d_n_used = d_n_nodes = 0;
};
s_node_ptr find_next_available_node () {
d_internal->lock ();
gruel::scoped_lock l (*d_internal);
// find an available node
s_node_ptr l_node = d_available;
DEBUG (std::cerr << "w ");
while (! l_node) {
DEBUG (std::cerr << "x" << std::endl);
// the ioBlock condition will automatically unlock() d_internal
d_ioBlock->wait ();
d_ioBlock->wait (l);
// and lock() is here
DEBUG (std::cerr << "y" << std::endl);
l_node = d_available;
@ -196,13 +198,12 @@ public:
l_node->insert_before (d_inUse);
d_n_used++;
l_node->set_not_available ();
d_internal->unlock ();
return (l_node);
};
void make_node_available (s_node_ptr l_node) {
if (!l_node) return;
d_internal->lock ();
gruel::scoped_lock l (*d_internal);
DEBUG (std::cerr << "::m_n_a: #u = " << num_used()
<< ", node = " << l_node << std::endl);
// remove this node from the inUse list
@ -221,11 +222,8 @@ public:
DEBUG (std::cerr << "s" << d_n_used);
// signal the condition when new data arrives
d_ioBlock->signal ();
d_ioBlock->notify_one ();
DEBUG (std::cerr << "t ");
// unlock the mutex for thread safety
d_internal->unlock ();
};
__INLINE__ void iterate_start () { d_iterate = d_current; };
@ -233,7 +231,7 @@ public:
s_node_ptr iterate_next () {
#if 0
// lock the mutex for thread safety
d_internal->lock ();
gruel::scoped_lock l (*d_internal);
#endif
s_node_ptr l_this = NULL;
if (d_iterate) {
@ -242,10 +240,6 @@ public:
if (d_iterate == d_current)
d_iterate = NULL;
}
#if 0
// unlock the mutex for thread safety
d_internal->unlock ();
#endif
return (l_this);
};
@ -261,7 +255,7 @@ public:
__INLINE__ void num_used_dec (void) {
if (d_n_used != 0) --d_n_used;
// signal the condition that new data has arrived
d_ioBlock->signal ();
d_ioBlock->notify_one ();
};
__INLINE__ bool in_use () { return (d_n_used != 0); };
};

View File

@ -80,7 +80,9 @@ wbxng_base::set_freq(double freq)
actual_baseband_freq is the RF frequency that corresponds to DC in the IF.
*/
freq_t int_freq = freq_t(freq);
// clamp freq
freq_t int_freq = freq_t(std::max(freq_min(), std::min(freq, freq_max())));
bool ok = d_common->_set_freq(int_freq*2);
double freq_result = (double) d_common->_get_freq()/2.0;
struct freq_result_t args = {ok, freq_result};

View File

@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
* Copyright 2006,2009 Free Software Foundation, Inc.
* Copyright 2006,2009,2010 Free Software Foundation, Inc.
*
* This file is part of GNU Radio.
*
@ -24,9 +24,6 @@
#include "config.h"
#endif
// tell mld_threads to NOT use omni_threads,
// but rather Darwin's pthreads
#define _USE_OMNI_THREADS_
#define DO_DEBUG 0
#include <usb.h>
@ -85,10 +82,12 @@ fusb_ephandle_darwin::fusb_ephandle_darwin (fusb_devhandle_darwin* dh,
l_buf = NULL;
}
d_readRunning = new mld_mutex ();
d_runThreadRunning = new mld_mutex ();
d_runBlock = new mld_condition ();
d_readBlock = new mld_condition ();
d_readRunning = new gruel::mutex ();
d_runThreadRunning = new gruel::mutex ();
d_runBlock = new gruel::condition_variable ();
d_readBlock = new gruel::condition_variable ();
d_runBlock_mutex = new gruel::mutex ();
d_readBlock_mutex = new gruel::mutex ();
}
fusb_ephandle_darwin::~fusb_ephandle_darwin ()
@ -116,6 +115,10 @@ fusb_ephandle_darwin::~fusb_ephandle_darwin ()
d_readRunning = NULL;
delete d_runThreadRunning;
d_runThreadRunning = NULL;
delete d_runBlock_mutex;
d_runBlock_mutex = NULL;
delete d_readBlock_mutex;
d_readBlock_mutex = NULL;
delete d_runBlock;
d_runBlock = NULL;
delete d_readBlock;
@ -200,14 +203,14 @@ fusb_ephandle_darwin::start ()
// lock the runBlock mutex, before creating the run thread.
// this guarantees that we can control execution between these 2 threads
d_runBlock->mutex ()->lock ();
gruel::scoped_lock l (*d_runBlock_mutex);
// create the run thread, which allows OSX to process I/O separately
d_runThread = new mld_thread (run_thread, this);
d_runThread = new gruel::thread (run_thread, this);
// wait until the run thread (and possibky read thread) are -really-
// going; this will unlock the mutex before waiting for a signal ()
d_runBlock->wait ();
d_runBlock->wait (l);
if (usb_debug) {
std::cerr << "fusb_ephandle_darwin::start: " << (d_input_p ? "read" : "write")
@ -225,12 +228,12 @@ fusb_ephandle_darwin::run_thread (void* arg)
// lock the run thread running mutex; if ::stop() is called, it will
// first abort() the pipe then wait for the run thread to finish,
// via a lock() on this mutex
mld_mutex_ptr l_runThreadRunning = This->d_runThreadRunning;
l_runThreadRunning->lock ();
gruel::mutex* l_runThreadRunning = This->d_runThreadRunning;
gruel::scoped_lock l0 (*l_runThreadRunning);
mld_mutex_ptr l_readRunning = This->d_readRunning;
mld_condition_ptr l_readBlock = This->d_readBlock;
mld_mutex_ptr l_readBlock_mutex = l_readBlock->mutex ();
gruel::mutex* l_readRunning = This->d_readRunning;
gruel::condition_variable* l_readBlock = This->d_readBlock;
gruel::mutex* l_readBlock_mutex = This->d_readBlock_mutex;
bool l_input_p = This->d_input_p;
@ -250,41 +253,39 @@ fusb_ephandle_darwin::run_thread (void* arg)
// get run loop reference, to allow other threads to stop
This->d_CFRunLoopRef = CFRunLoopGetCurrent ();
mld_thread_ptr l_rwThread = NULL;
gruel::thread* l_rwThread = NULL;
if (l_input_p) {
// lock the readBlock mutex, before creating the read thread.
// this guarantees that we can control execution between these 2 threads
l_readBlock_mutex->lock ();
gruel::scoped_lock l1 (*l_readBlock_mutex);
// create the read thread, which just issues all of the starting
// async read commands, then returns
l_rwThread = new mld_thread (read_thread, arg);
l_rwThread = new gruel::thread (read_thread, arg);
// wait until the the read thread is -really- going; this will
// unlock the read block mutex before waiting for a signal ()
l_readBlock->wait ();
l_readBlock->wait (l1);
}
// now signal the run condition to release and finish ::start().
{
// now signal the run condition to release and finish ::start().
// lock the runBlock mutex first; this will force waiting until the
// ->wait() command is issued in ::start()
mld_mutex_ptr l_run_block_mutex = This->d_runBlock->mutex ();
l_run_block_mutex->lock ();
// lock the runBlock mutex first; this will force waiting until the
// ->wait() command is issued in ::start()
gruel::mutex* l_run_block_mutex = This->d_runBlock_mutex;
gruel::scoped_lock l2 (*l_run_block_mutex);
// now that the lock is in place, signal the parent thread that
// things are running
This->d_runBlock->signal ();
// release the run_block mutex, just in case
l_run_block_mutex->unlock ();
// now that the lock is in place, signal the parent thread that
// things are running
This->d_runBlock->notify_one ();
}
// run the loop
CFRunLoopRun ();
if (l_input_p) {
// wait for read_thread () to finish, if needed
l_readRunning->lock ();
l_readRunning->unlock ();
gruel::scoped_lock l3 (*l_readRunning);
}
// remove run loop stuff
@ -295,9 +296,6 @@ fusb_ephandle_darwin::run_thread (void* arg)
std::cerr << "fusb_ephandle_darwin::run_thread: finished for "
<< (l_input_p ? "read" : "write") << "." << std::endl;
}
// release the run thread running mutex
l_runThreadRunning->unlock ();
}
void
@ -311,23 +309,23 @@ fusb_ephandle_darwin::read_thread (void* arg)
// before doing anything else, lock the read running mutex. this
// mutex does flow control between this thread and the run_thread
mld_mutex_ptr l_readRunning = This->d_readRunning;
l_readRunning->lock ();
gruel::mutex* l_readRunning = This->d_readRunning;
gruel::scoped_lock l0 (*l_readRunning);
// signal the read condition from run_thread() to continue
// lock the readBlock mutex first; this will force waiting until the
// ->wait() command is issued in ::run_thread()
mld_condition_ptr l_readBlock = This->d_readBlock;
mld_mutex_ptr l_read_block_mutex = l_readBlock->mutex ();
l_read_block_mutex->lock ();
gruel::condition_variable* l_readBlock = This->d_readBlock;
gruel::mutex* l_read_block_mutex = This->d_readBlock_mutex;
// now that the lock is in place, signal the parent thread that
// things are running here
l_readBlock->signal ();
{
gruel::scoped_lock l1 (*l_read_block_mutex);
// release the run_block mutex, just in case
l_read_block_mutex->unlock ();
// now that the lock is in place, signal the parent thread that
// things are running here
l_readBlock->notify_one ();
}
// queue up all of the available read requests
s_queue_ptr l_queue = This->d_queue;
@ -341,10 +339,6 @@ fusb_ephandle_darwin::read_thread (void* arg)
if (usb_debug) {
std::cerr << "fusb_ephandle_darwin::read_thread: finished." << std::endl;
}
// release the read running mutex, to let the parent thread knows
// that this thread is finished
l_readRunning->unlock ();
}
void
@ -569,8 +563,7 @@ fusb_ephandle_darwin::stop ()
CFRunLoopStop (d_CFRunLoopRef);
// wait for the runThread to stop
d_runThreadRunning->lock ();
d_runThreadRunning->unlock ();
gruel::scoped_lock l (*d_runThreadRunning);
if (usb_debug) {
std::cerr << "fusb_ephandle_darwin::stop: " << (d_input_p ? "read" : "write")

View File

@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
* Copyright 2006,2009 Free Software Foundation, Inc.
* Copyright 2006,2009,2010 Free Software Foundation, Inc.
*
* This file is part of GNU Radio.
*
@ -150,8 +150,8 @@ class fusb_ephandle_darwin : public fusb_ephandle
{
private:
fusb_devhandle_darwin* d_devhandle;
mld_thread_ptr d_runThread;
mld_mutex_ptr d_runThreadRunning;
gruel::thread* d_runThread;
gruel::mutex* d_runThreadRunning;
CFRunLoopRef d_CFRunLoopRef;
@ -174,8 +174,11 @@ public:
s_queue_ptr d_queue;
circular_buffer<char>* d_buffer;
size_t d_bufLenBytes;
mld_mutex_ptr d_readRunning;
mld_condition_ptr d_runBlock, d_readBlock;
gruel::mutex* d_readRunning;
gruel::mutex* d_runBlock_mutex;
gruel::mutex* d_readBlock_mutex;
gruel::condition_variable* d_runBlock;
gruel::condition_variable* d_readBlock;
// CREATORS

View File

@ -1,275 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2006 Free Software Foundation, Inc.
*
* This file is part of GNU Radio.
*
* Primary Author: Michael Dickens, NCIP Lab, University of Notre Dame
*
* 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_MLD_THREADS_H_
#define _INCLUDED_MLD_THREADS_H_
/* classes which allow for either pthreads or omni_threads */
#define __macos__
#ifdef _USE_OMNI_THREADS_
#include <gnuradio/omnithread.h>
#else
#include <pthread.h>
#endif
#include <stdexcept>
#define __INLINE__ inline
#ifndef DO_DEBUG
#define DO_DEBUG 0
#endif
#if DO_DEBUG
#define DEBUG(X) do{X} while(0);
#else
#define DEBUG(X) do{} while(0);
#endif
class mld_condition_t;
class mld_mutex_t {
#ifdef _USE_OMNI_THREADS_
typedef omni_mutex l_mutex, *l_mutex_ptr;
#else
typedef pthread_mutex_t l_mutex, *l_mutex_ptr;
#endif
friend class mld_condition_t;
private:
l_mutex_ptr d_mutex;
protected:
inline l_mutex_ptr mutex () { return (d_mutex); };
public:
__INLINE__ mld_mutex_t () {
#ifdef _USE_OMNI_THREADS_
d_mutex = new omni_mutex ();
#else
d_mutex = (l_mutex_ptr) new l_mutex;
int l_ret = pthread_mutex_init (d_mutex, NULL);
if (l_ret != 0) {
fprintf (stderr, "Error %d creating mutex.\n", l_ret);
throw std::runtime_error ("mld_mutex_t::mld_mutex_t()\n");
}
#endif
};
__INLINE__ ~mld_mutex_t () {
unlock ();
#ifndef _USE_OMNI_THREADS_
int l_ret = pthread_mutex_destroy (d_mutex);
if (l_ret != 0) {
fprintf (stderr, "mld_mutex_t::~mld_mutex_t(): "
"Error %d destroying mutex.\n", l_ret);
}
#endif
delete d_mutex;
d_mutex = NULL;
};
__INLINE__ void lock () {
#ifdef _USE_OMNI_THREADS_
d_mutex->lock ();
#else
int l_ret = pthread_mutex_lock (d_mutex);
if (l_ret != 0) {
fprintf (stderr, "mld_mutex_t::lock(): "
"Error %d locking mutex.\n", l_ret);
}
#endif
};
__INLINE__ void unlock () {
#ifdef _USE_OMNI_THREADS_
d_mutex->unlock ();
#else
int l_ret = pthread_mutex_unlock (d_mutex);
if (l_ret != 0) {
fprintf (stderr, "mld_mutex_t::unlock(): "
"Error %d locking mutex.\n", l_ret);
}
#endif
};
__INLINE__ bool trylock () {
#ifdef _USE_OMNI_THREADS_
int l_ret = d_mutex->trylock ();
#else
int l_ret = pthread_mutex_unlock (d_mutex);
#endif
return (l_ret == 0 ? true : false);
};
inline void acquire () { lock(); };
inline void release () { unlock(); };
inline void wait () { lock(); };
inline void post () { unlock(); };
};
typedef mld_mutex_t mld_mutex, *mld_mutex_ptr;
class mld_condition_t {
#ifdef _USE_OMNI_THREADS_
typedef omni_condition l_condition, *l_condition_ptr;
#else
typedef pthread_cond_t l_condition, *l_condition_ptr;
#endif
private:
l_condition_ptr d_condition;
mld_mutex_ptr d_mutex;
bool d_i_own_mutex;
public:
__INLINE__ mld_condition_t (mld_mutex_ptr mutex = NULL) {
if (mutex) {
d_i_own_mutex = false;
d_mutex = mutex;
} else {
d_i_own_mutex = true;
d_mutex = new mld_mutex ();
}
#ifdef _USE_OMNI_THREADS_
d_condition = new omni_condition (d_mutex->mutex ());
#else
d_condition = (l_condition_ptr) new l_condition;
int l_ret = pthread_cond_init (d_condition, NULL);
if (l_ret != 0) {
fprintf (stderr, "Error %d creating condition.\n", l_ret);
throw std::runtime_error ("mld_condition_t::mld_condition_t()\n");
}
#endif
};
__INLINE__ ~mld_condition_t () {
signal ();
#ifndef _USE_OMNI_THREADS_
int l_ret = pthread_cond_destroy (d_condition);
if (l_ret != 0) {
fprintf (stderr, "mld_condition_t::mld_condition_t(): "
"Error %d destroying condition.\n", l_ret);
}
#endif
delete d_condition;
d_condition = NULL;
if (d_i_own_mutex)
delete d_mutex;
d_mutex = NULL;
};
__INLINE__ mld_mutex_ptr mutex () {return (d_mutex);};
__INLINE__ void signal () {
DEBUG (fprintf (stderr, "a "););
#ifdef _USE_OMNI_THREADS_
d_condition->signal ();
#else
int l_ret = pthread_cond_signal (d_condition);
if (l_ret != 0) {
fprintf (stderr, "mld_condition_t::signal(): "
"Error %d.\n", l_ret);
}
#endif
DEBUG (fprintf (stderr, "b "););
};
__INLINE__ void wait () {
DEBUG (fprintf (stderr, "c "););
#ifdef _USE_OMNI_THREADS_
d_condition->wait ();
#else
int l_ret = pthread_cond_wait (d_condition, d_mutex->mutex ());
if (l_ret != 0) {
fprintf (stderr, "mld_condition_t::wait(): "
"Error %d.\n", l_ret);
}
#endif
DEBUG (fprintf (stderr, "d "););
};
};
typedef mld_condition_t mld_condition, *mld_condition_ptr;
class mld_thread_t {
#ifdef _USE_OMNI_THREADS_
typedef omni_thread l_thread, *l_thread_ptr;
#else
typedef pthread_t l_thread, *l_thread_ptr;
#endif
private:
#ifndef _USE_OMNI_THREADS_
l_thread d_thread;
void (*d_start_routine)(void*);
void *d_arg;
#else
l_thread_ptr d_thread;
#endif
#ifndef _USE_OMNI_THREADS_
static void* local_start_routine (void *arg) {
mld_thread_t* This = (mld_thread_t*) arg;
(*(This->d_start_routine))(This->d_arg);
return (NULL);
};
#endif
public:
__INLINE__ mld_thread_t (void (*start_routine)(void *), void *arg) {
#ifdef _USE_OMNI_THREADS_
d_thread = new omni_thread (start_routine, arg);
d_thread->start ();
#else
d_start_routine = start_routine;
d_arg = arg;
int l_ret = pthread_create (&d_thread, NULL, local_start_routine, this);
if (l_ret != 0) {
fprintf (stderr, "Error %d creating thread.\n", l_ret);
throw std::runtime_error ("mld_thread_t::mld_thread_t()\n");
}
#endif
};
__INLINE__ ~mld_thread_t () {
#ifdef _USE_OMNI_THREADS_
// delete d_thread;
d_thread = NULL;
#else
int l_ret = pthread_detach (d_thread);
if (l_ret != 0) {
fprintf (stderr, "Error %d detaching thread.\n", l_ret);
throw std::runtime_error ("mld_thread_t::~mld_thread_t()\n");
}
#endif
};
};
typedef mld_thread_t mld_thread, *mld_thread_ptr;
#endif /* _INCLUDED_MLD_THREADS_H_ */

View File

@ -1,35 +0,0 @@
/Makefile
/Makefile.in
/.la
/.lo
/.deps
/.libs
/*.la
/*.lo
/*.dat
/.*.swp
/usrper
/usrper2
/test_input
/test_fusb
/test_usrp
/test_usrp0
/test_usrp_standard_rx
/test_usrp_standard_tx
/test_usrp_standard_2tx
/test_usrp_inband_timestamps
/test_usrp_inband_registers
/test_usrp_inband_rx
/test_usrp_inband_2rx
/test_usrp_inband_tx
/test_usrp_inband_2tx
/test_usrp_basic_rx
/check_order_quickly
/usrp_cal_dc_offset
/test_usrp_inband_cs
/read_packets
/test_usrp_inband_ping
/test_usrp_inband_underrun
/test_usrp_inband_overrun
/gmac_mbh.cc
/test_gmac_tx

View File

@ -1,77 +0,0 @@
#
# Copyright 2003,2006,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.
#
include $(top_srcdir)/Makefile.common
AM_CPPFLAGS = \
$(DEFINES) $(OMNITHREAD_INCLUDES) $(PMT_INCLUDES) $(MBLOCK_INCLUDES) \
$(USRP_INCLUDES) $(USRP_INBAND_INCLUDES) $(BOOST_CPPFLAGS) \
$(CPPUNIT_INCLUDES) $(WITH_INCLUDES) -I$(top_srcdir)/mblock/src/lib
bin_PROGRAMS =
noinst_PROGRAMS = \
test_usrp_inband_ping \
test_usrp_inband_registers \
test_usrp_inband_rx \
test_usrp_inband_2rx \
test_usrp_inband_tx \
test_usrp_inband_2tx \
test_usrp_inband_timestamps \
test_usrp_inband_overrun \
test_usrp_inband_underrun \
read_packets
noinst_HEADERS = \
ui_nco.h \
ui_sincos.h
test_usrp_inband_ping_SOURCES = test_usrp_inband_ping.cc
test_usrp_inband_ping_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
test_usrp_inband_tx_SOURCES = test_usrp_inband_tx.cc ui_sincos.c
test_usrp_inband_tx_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
test_usrp_inband_2tx_SOURCES = test_usrp_inband_2tx.cc ui_sincos.c
test_usrp_inband_2tx_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
test_usrp_inband_timestamps_SOURCES = test_usrp_inband_timestamps.cc ui_sincos.c
test_usrp_inband_timestamps_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
test_usrp_inband_registers_SOURCES = test_usrp_inband_registers.cc ui_sincos.c
test_usrp_inband_registers_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
test_usrp_inband_overrun_SOURCES = test_usrp_inband_overrun.cc
test_usrp_inband_overrun_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
test_usrp_inband_underrun_SOURCES = test_usrp_inband_underrun.cc
test_usrp_inband_underrun_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
test_usrp_inband_rx_SOURCES = test_usrp_inband_rx.cc ui_sincos.c
test_usrp_inband_rx_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
test_usrp_inband_2rx_SOURCES = test_usrp_inband_2rx.cc ui_sincos.c
test_usrp_inband_2rx_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
read_packets_SOURCES = read_packets.cc
read_packets_LDADD = $(USRP_LA) $(USRP_INBAND_LA)

View File

@ -1,109 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,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 <iostream>
#include <usrp_inband_usb_packet.h>
#include <mblock/class_registry.h>
#include <vector>
#include <usrp_usb_interface.h>
#include <fstream>
typedef usrp_inband_usb_packet transport_pkt; // makes conversion to gigabit easy
int main(int argc, char *argv[]) {
if(argc !=2) {
std::cout << "Usage: ./read_packets <data_file>\n";
return -1;
}
std::ifstream infile;
std::ofstream outfile;
unsigned int pkt_size = transport_pkt::max_pkt_size();
unsigned int pkt_num=0;
transport_pkt *pkt;
char pkt_data[pkt_size]; // allocate the number of bytes for a single packet
pkt = (transport_pkt *)pkt_data; // makes operations cleaner to read
// Open the file and read the packets, dumping information
infile.open(argv[1], std::ios::binary|std::ios::in);
if(!infile.is_open())
exit(-1);
//outfile.open("dump.dat",std::ios::out|std::ios::binary);
// read 1 packet in to the memory
infile.read(pkt_data, pkt_size);
while(!infile.eof()) {
printf("Packet %u\n", pkt_num);
if(pkt->start_of_burst())
printf("\tstart of burst\n");
if(pkt->end_of_burst())
printf("\tend of burst\n");
// if(pkt->carrier_sense())
// printf("\tcarrier sense\n");
if(pkt->underrun())
printf("\tunderrun\n");
if(pkt->overrun())
printf("\toverrun\n");
printf("\tchannel: \t0x%x\n", pkt->chan());
printf("\ttimestamp: \t0x%x\n", pkt->timestamp());
//printf("\ttimestamp: \t%u\n", pkt->timestamp());
printf("\tlength: \t%u\n", pkt->payload_len());
printf("\trssi: \t%u\n", pkt->rssi());
printf("\tpayload: \n");
for(int i=0; i < pkt->payload_len(); i++)
//for(int i=0; i < pkt->max_payload(); i++)
{
printf("\t%d\t0x%x\n", i, *(pkt->payload()+i));
//outfile.write((const char*)(pkt->payload()+i),1);
//printf("\t\t0x%x\n", pkt->payload()+i);
}
printf("\n\n");
pkt_num++;
// read 1 packet in to the memory
infile.read(pkt_data, pkt_size);
}
infile.close();
//outfile.close();
}

View File

@ -1,371 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,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 <mblock/mblock.h>
#include <mblock/runtime.h>
#include <mb_runtime_nop.h> // QA only
#include <mblock/protocol_class.h>
#include <mblock/exception.h>
#include <mblock/msg_queue.h>
#include <mblock/message.h>
#include <mb_mblock_impl.h>
#include <mblock/msg_accepter.h>
#include <mblock/class_registry.h>
#include <pmt.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <fstream>
// Include the symbols needed for communication with USRP server
#include <symbols_usrp_server_cs.h>
#include <symbols_usrp_channel.h>
#include <symbols_usrp_low_level_cs.h>
#include <symbols_usrp_rx.h>
static bool verbose = true;
class test_usrp_rx : public mb_mblock
{
mb_port_sptr d_rx;
mb_port_sptr d_cs;
pmt_t d_rx_chan0, d_rx_chan1;
enum state_t {
INIT,
OPENING_USRP,
ALLOCATING_CHANNEL,
RECEIVING,
CLOSING_CHANNEL,
CLOSING_USRP,
};
state_t d_state;
std::ofstream d_ofile;
long d_samples_recvd;
long d_samples_to_recv;
public:
test_usrp_rx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
~test_usrp_rx();
void initial_transition();
void handle_message(mb_message_sptr msg);
protected:
void open_usrp();
void close_usrp();
void allocate_channel();
void send_packets();
void enter_receiving();
void build_and_send_next_frame();
void handle_response_recv_raw_samples(pmt_t invocation_handle);
void enter_closing_channel();
};
test_usrp_rx::test_usrp_rx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
: mb_mblock(runtime, instance_name, user_arg),
d_rx_chan0(PMT_NIL), d_rx_chan1(PMT_NIL),
d_samples_recvd(0),
d_samples_to_recv(20e6)
{
d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
// Pass a dictionary to usrp_server which specifies which interface to use, the stub or USRP
pmt_t usrp_dict = pmt_make_dict();
// To test the application without a USRP
bool fake_usrp_p = false;
if(fake_usrp_p) {
pmt_dict_set(usrp_dict,
pmt_intern("fake-usrp"),
PMT_T);
}
// Specify the RBF to use
pmt_dict_set(usrp_dict,
pmt_intern("rbf"),
pmt_intern("inband_2rxhb_2tx.rbf"));
pmt_dict_set(usrp_dict,
pmt_intern("decim-rx"),
pmt_from_long(64));
define_component("server", "usrp_server", usrp_dict);
connect("self", "rx0", "server", "rx0");
connect("self", "cs", "server", "cs");
}
test_usrp_rx::~test_usrp_rx()
{
}
void
test_usrp_rx::initial_transition()
{
open_usrp();
}
void
test_usrp_rx::handle_message(mb_message_sptr msg)
{
pmt_t event = msg->signal();
pmt_t data = msg->data();
pmt_t handle = PMT_F;
pmt_t status = PMT_F;
std::string error_msg;
switch(d_state){
//----------------------------- OPENING_USRP ----------------------------//
// We only expect a response from opening the USRP which should be succesful
// or failed.
case OPENING_USRP:
if (pmt_eq(event, s_response_open)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
allocate_channel();
return;
}
else {
error_msg = "failed to open usrp:";
goto bail;
}
}
goto unhandled;
//----------------------- ALLOCATING CHANNELS --------------------//
// Allocate an RX channel to perform the overrun test.
case ALLOCATING_CHANNEL:
if (pmt_eq(event, s_response_allocate_channel)){
status = pmt_nth(1, data);
if(pmt_eqv(d_rx_chan0, PMT_NIL))
d_rx_chan0 = pmt_nth(2, data);
else
d_rx_chan1 = pmt_nth(2, data);
if (pmt_eq(status, PMT_T) && !pmt_eqv(d_rx_chan1, PMT_NIL)){
enter_receiving();
return;
}
else if(pmt_eq(status, PMT_F)){
error_msg = "failed to allocate channel:";
goto bail;
}
return;
}
goto unhandled;
//--------------------------- RECEIVING ------------------------------//
// In the receiving state, we receive samples until the specified amount
// while counting the number of overruns.
case RECEIVING:
if (pmt_eq(event, s_response_recv_raw_samples)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
handle_response_recv_raw_samples(data);
return;
}
else {
error_msg = "bad response-xmit-raw-frame:";
goto bail;
}
}
goto unhandled;
//------------------------- CLOSING CHANNEL ----------------------------//
// Check deallocation response for the RX channel
case CLOSING_CHANNEL:
if (pmt_eq(event, s_response_deallocate_channel)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
close_usrp();
return;
}
else {
error_msg = "failed to deallocate channel:";
goto bail;
}
}
// Alternately, we ignore all response recv samples while waiting for the
// channel to actually close
if (pmt_eq(event, s_response_recv_raw_samples))
return;
goto unhandled;
//--------------------------- CLOSING USRP ------------------------------//
// Once we have received a successful USRP close response, we shutdown all
// mblocks and exit.
case CLOSING_USRP:
if (pmt_eq(event, s_response_close)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
fflush(stdout);
shutdown_all(PMT_T);
return;
}
else {
error_msg = "failed to close USRP:";
goto bail;
}
}
goto unhandled;
default:
goto unhandled;
}
return;
// An error occured, print it, and shutdown all m-blocks
bail:
std::cerr << error_msg << data
<< "status = " << status << std::endl;
shutdown_all(PMT_F);
return;
// Received an unhandled message for a specific state
unhandled:
if(verbose && !pmt_eq(event, pmt_intern("%shutdown")))
std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
<< "in state "<< d_state << std::endl;
}
void
test_usrp_rx::open_usrp()
{
pmt_t which_usrp = pmt_from_long(0);
d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, which_usrp));
d_state = OPENING_USRP;
if(verbose)
std::cout << "[TEST_USRP_INBAND_RX] Opening the USRP\n";
}
void
test_usrp_rx::close_usrp()
{
d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
d_state = CLOSING_USRP;
if(verbose)
std::cout << "[TEST_USRP_INBAND_RX] Closing the USRP\n";
}
void
test_usrp_rx::allocate_channel()
{
long capacity = (long) 16e6;
d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
d_state = ALLOCATING_CHANNEL;
if(verbose)
std::cout << "[TEST_USRP_INBAND_RX] Requesting RX channel allocation\n";
}
void
test_usrp_rx::enter_receiving()
{
d_state = RECEIVING;
d_rx->send(s_cmd_start_recv_raw_samples,
pmt_list2(PMT_F,
d_rx_chan0));
d_rx->send(s_cmd_start_recv_raw_samples,
pmt_list2(PMT_F,
d_rx_chan1));
if(verbose)
std::cout << "[TEST_USRP_INBAND_RX] Receiving...\n";
}
void
test_usrp_rx::handle_response_recv_raw_samples(pmt_t data)
{
pmt_t invocation_handle = pmt_nth(0, data);
pmt_t status = pmt_nth(1, data);
pmt_t v_samples = pmt_nth(2, data);
pmt_t timestamp = pmt_nth(3, data);
pmt_t channel = pmt_nth(4, data);
pmt_t properties = pmt_nth(5, data);
d_samples_recvd += pmt_length(v_samples) / 4;
// Check for overrun
if(!pmt_is_dict(properties)) {
std::cout << "[TEST_USRP_INBAND_RX] Recv samples dictionary is improper\n";
return;
}
// Check if the number samples we have received meets the test
if(d_samples_recvd >= d_samples_to_recv) {
d_rx->send(s_cmd_stop_recv_raw_samples, pmt_list2(PMT_NIL, d_rx_chan0));
d_rx->send(s_cmd_stop_recv_raw_samples, pmt_list2(PMT_NIL, d_rx_chan1));
enter_closing_channel();
return;
}
}
void
test_usrp_rx::enter_closing_channel()
{
d_state = CLOSING_CHANNEL;
d_rx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_rx_chan0));
d_rx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_rx_chan1));
if(verbose)
std::cout << "[TEST_USRP_INBAND_RX] Deallocating RX channel\n";
}
REGISTER_MBLOCK_CLASS(test_usrp_rx);
// ----------------------------------------------------------------
int
main (int argc, char **argv)
{
mb_runtime_sptr rt = mb_make_runtime();
pmt_t result = PMT_NIL;
rt->run("top", "test_usrp_rx", PMT_F, &result);
}

View File

@ -1,430 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,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 <mblock/mblock.h>
#include <mblock/runtime.h>
#include <mb_runtime_nop.h> // QA only
#include <mblock/protocol_class.h>
#include <mblock/exception.h>
#include <mblock/msg_queue.h>
#include <mblock/message.h>
#include <mb_mblock_impl.h>
#include <mblock/msg_accepter.h>
#include <mblock/class_registry.h>
#include <pmt.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <ui_nco.h>
#include <symbols_usrp_server_cs.h>
#include <symbols_usrp_channel.h>
#include <symbols_usrp_low_level_cs.h>
#include <symbols_usrp_tx.h>
static bool verbose = true;
class test_usrp_tx : public mb_mblock
{
mb_port_sptr d_tx;
mb_port_sptr d_cs;
pmt_t d_tx_chan0, d_tx_chan1;
enum state_t {
INIT,
OPENING_USRP,
ALLOCATING_CHANNEL,
TRANSMITTING,
CLOSING_CHANNEL,
CLOSING_USRP,
};
state_t d_state;
long d_nsamples_to_send;
long d_nsamples_xmitted;
long d_nframes_xmitted;
long d_samples_per_frame;
bool d_done_sending;
// for generating sine wave output
ui_nco<float,float> d_nco;
double d_amplitude;
public:
test_usrp_tx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
~test_usrp_tx();
void initial_transition();
void handle_message(mb_message_sptr msg);
protected:
void open_usrp();
void close_usrp();
void allocate_channel();
void send_packets();
void enter_transmitting();
void build_and_send_next_frame();
void handle_xmit_response(pmt_t invocation_handle);
void enter_closing_channel();
};
test_usrp_tx::test_usrp_tx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
: mb_mblock(runtime, instance_name, user_arg),
d_tx_chan0(PMT_NIL), d_tx_chan1(PMT_NIL),
d_state(INIT), d_nsamples_to_send((long) 80e6),
d_nsamples_xmitted(0),
d_nframes_xmitted(0),
d_samples_per_frame((long)(126 * 4)), // full packet
d_done_sending(false),
d_amplitude(16384)
{
// std::cout << "[TEST_USRP_TX] Initializing...\n";
d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
//bool fake_usrp_p = true;
bool fake_usrp_p = false;
// Test the TX side
pmt_t usrp_dict = pmt_make_dict();
if(fake_usrp_p) {
pmt_dict_set(usrp_dict,
pmt_intern("fake-usrp"),
PMT_T);
}
// Specify the RBF to use
pmt_dict_set(usrp_dict,
pmt_intern("rbf"),
pmt_intern("inband_2rxhb_2tx.rbf"));
// Set TX and RX interpolations
pmt_dict_set(usrp_dict,
pmt_intern("interp-tx"),
pmt_from_long(128));
// pmt_dict_set(usrp_dict,
// pmt_intern("rf-freq"),
// pmt_from_long(10e6));
define_component("server", "usrp_server", usrp_dict);
connect("self", "tx0", "server", "tx0");
connect("self", "cs", "server", "cs");
// initialize NCO
double freq = 100e3;
int interp = 32; // 32 -> 4MS/s
double sample_rate = 128e6 / interp;
d_nco.set_freq(2*M_PI * freq/sample_rate);
// FIXME need to somehow set the interp rate in the USRP.
// for now, we'll have the low-level code hardwire it.
}
test_usrp_tx::~test_usrp_tx()
{
}
void
test_usrp_tx::initial_transition()
{
open_usrp();
}
void
test_usrp_tx::handle_message(mb_message_sptr msg)
{
pmt_t event = msg->signal();
pmt_t data = msg->data();
pmt_t handle = PMT_F;
pmt_t status = PMT_F;
std::string error_msg;
//std::cout << msg << std::endl;
switch(d_state){
case OPENING_USRP:
if (pmt_eq(event, s_response_open)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
allocate_channel();
return;
}
else {
error_msg = "failed to open usrp:";
goto bail;
}
}
goto unhandled;
case ALLOCATING_CHANNEL:
if (pmt_eq(event, s_response_allocate_channel)){
status = pmt_nth(1, data);
if(pmt_eqv(d_tx_chan0, PMT_NIL))
d_tx_chan0 = pmt_nth(2, data);
else
d_tx_chan1 = pmt_nth(2, data);
if (pmt_eq(status, PMT_T) && !pmt_eqv(d_tx_chan1, PMT_NIL)){
enter_transmitting();
return;
}
else if(pmt_eq(status, PMT_F)){
error_msg = "failed to allocate channel:";
goto bail;
}
return;
}
goto unhandled;
case TRANSMITTING:
if (pmt_eq(event, s_response_xmit_raw_frame)){
handle = pmt_nth(0, data);
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
handle_xmit_response(handle);
return;
}
else {
error_msg = "bad response-xmit-raw-frame:";
goto bail;
}
}
goto unhandled;
case CLOSING_CHANNEL:
if (pmt_eq(event, s_response_deallocate_channel)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
close_usrp();
return;
}
else {
error_msg = "failed to deallocate channel:";
goto bail;
}
}
goto unhandled;
case CLOSING_USRP:
if (pmt_eq(event, s_response_close)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
shutdown_all(PMT_T);
return;
}
else {
error_msg = "failed to close USRP:";
goto bail;
}
}
goto unhandled;
default:
goto unhandled;
}
return;
bail:
std::cerr << error_msg << data
<< "status = " << status << std::endl;
shutdown_all(PMT_F);
return;
unhandled:
std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
<< "in state "<< d_state << std::endl;
}
void
test_usrp_tx::open_usrp()
{
pmt_t which_usrp = pmt_from_long(0);
d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, which_usrp));
d_state = OPENING_USRP;
if(verbose)
std::cout << "[TEST_USRP_INBAND_TX] Opening the USRP\n";
}
void
test_usrp_tx::close_usrp()
{
d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
d_state = CLOSING_USRP;
if(verbose)
std::cout << "[TEST_USRP_INBAND_TX] Closing the USRP\n";
}
void
test_usrp_tx::allocate_channel()
{
long capacity = (long) 16e6;
// Send two capacity requests, which will allocate us two channels
d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
d_state = ALLOCATING_CHANNEL;
if(verbose)
std::cout << "[TEST_USRP_INBAND_TX] Requesting TX channel allocation\n";
}
void
test_usrp_tx::enter_transmitting()
{
d_state = TRANSMITTING;
d_nsamples_xmitted = 0;
if(verbose)
std::cout << "[TEST_USRP_INBAND_TX] Transmitting...\n";
build_and_send_next_frame(); // fire off 4 to start pipeline
build_and_send_next_frame();
build_and_send_next_frame();
build_and_send_next_frame();
}
void
test_usrp_tx::build_and_send_next_frame()
{
// allocate the uniform vector for the samples
// FIXME perhaps hold on to this between calls
#if 1
long nsamples_this_frame =
std::min(d_nsamples_to_send - d_nsamples_xmitted,
d_samples_per_frame);
#else
long nsamples_this_frame = d_samples_per_frame;
#endif
if (nsamples_this_frame == 0){
d_done_sending = true;
return;
}
size_t nshorts = 2 * nsamples_this_frame; // 16-bit I & Q
pmt_t uvec = pmt_make_s16vector(nshorts, 0);
size_t ignore;
int16_t *samples = pmt_s16vector_writable_elements(uvec, ignore);
// fill in the complex sinusoid
for (int i = 0; i < nsamples_this_frame; i++){
if (1){
gr_complex s;
d_nco.sincos(&s, 1, d_amplitude);
// write 16-bit i & q
samples[2*i] = (int16_t) s.real();
samples[2*i+1] = (int16_t) s.imag();
}
else {
gr_complex s(d_amplitude, d_amplitude);
// write 16-bit i & q
samples[2*i] = (int16_t) s.real();
samples[2*i+1] = (int16_t) s.imag();
}
}
pmt_t tx_properties = pmt_make_dict();
pmt_t timestamp = pmt_from_long(0xffffffff); // NOW
d_tx->send(s_cmd_xmit_raw_frame,
pmt_list5(pmt_from_long(d_nframes_xmitted), // invocation-handle
d_tx_chan0, // channel
uvec, // the samples
timestamp,
tx_properties));
// Resend on channel 1
d_tx->send(s_cmd_xmit_raw_frame,
pmt_list5(pmt_from_long(d_nframes_xmitted), // invocation-handle
d_tx_chan1, // channel
uvec, // the samples
timestamp,
tx_properties));
d_nsamples_xmitted += nsamples_this_frame;
d_nframes_xmitted++;
if(verbose && 0)
std::cout << "[TEST_USRP_INBAND_TX] Transmitted frame\n";
}
void
test_usrp_tx::handle_xmit_response(pmt_t handle)
{
if (d_done_sending &&
pmt_to_long(handle) == (d_nframes_xmitted - 1)){
// We're done sending and have received all responses
enter_closing_channel();
}
build_and_send_next_frame();
}
void
test_usrp_tx::enter_closing_channel()
{
d_state = CLOSING_CHANNEL;
// Deallocate both channels
d_tx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_tx_chan0));
d_tx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_tx_chan1));
if(verbose)
std::cout << "[TEST_USRP_INBAND_tX] Deallocating TX channel\n";
}
REGISTER_MBLOCK_CLASS(test_usrp_tx);
// ----------------------------------------------------------------
int
main (int argc, char **argv)
{
// handle any command line args here
mb_runtime_sptr rt = mb_make_runtime();
pmt_t result = PMT_NIL;
rt->run("top", "test_usrp_tx", PMT_F, &result);
}

View File

@ -1,375 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,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 <mblock/mblock.h>
#include <mblock/runtime.h>
#include <mblock/protocol_class.h>
#include <mblock/exception.h>
#include <mblock/msg_queue.h>
#include <mblock/message.h>
#include <mblock/msg_accepter.h>
#include <mblock/class_registry.h>
#include <pmt.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <fstream>
// Include the symbols needed for communication with USRP server
#include <symbols_usrp_server_cs.h>
#include <symbols_usrp_channel.h>
#include <symbols_usrp_low_level_cs.h>
#include <symbols_usrp_rx.h>
static bool verbose = true;
class test_usrp_rx : public mb_mblock
{
mb_port_sptr d_rx;
mb_port_sptr d_cs;
pmt_t d_rx_chan; // returned tx channel handle
enum state_t {
INIT,
OPENING_USRP,
ALLOCATING_CHANNEL,
RECEIVING,
CLOSING_CHANNEL,
CLOSING_USRP,
};
state_t d_state;
std::ofstream d_ofile;
long d_n_overruns;
long d_samples_recvd;
long d_samples_to_recv;
public:
test_usrp_rx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
~test_usrp_rx();
void initial_transition();
void handle_message(mb_message_sptr msg);
protected:
void open_usrp();
void close_usrp();
void allocate_channel();
void send_packets();
void enter_receiving();
void build_and_send_next_frame();
void handle_response_recv_raw_samples(pmt_t invocation_handle);
void enter_closing_channel();
};
test_usrp_rx::test_usrp_rx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
: mb_mblock(runtime, instance_name, user_arg),
d_n_overruns(0),
d_samples_recvd(0),
d_samples_to_recv(10e6)
{
d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
// Pass a dictionary to usrp_server which specifies which interface to use, the stub or USRP
pmt_t usrp_dict = pmt_make_dict();
// Specify the RBF to use
pmt_dict_set(usrp_dict,
pmt_intern("rbf"),
pmt_intern("inband_1rxhb_1tx.rbf"));
pmt_dict_set(usrp_dict,
pmt_intern("decim-rx"),
pmt_from_long(128));
define_component("server", "usrp_server", usrp_dict);
connect("self", "rx0", "server", "rx0");
connect("self", "cs", "server", "cs");
}
test_usrp_rx::~test_usrp_rx()
{
}
void
test_usrp_rx::initial_transition()
{
open_usrp();
}
void
test_usrp_rx::handle_message(mb_message_sptr msg)
{
pmt_t event = msg->signal();
pmt_t data = msg->data();
pmt_t handle = PMT_F;
pmt_t status = PMT_F;
std::string error_msg;
switch(d_state){
//----------------------------- OPENING_USRP ----------------------------//
// We only expect a response from opening the USRP which should be succesful
// or failed.
case OPENING_USRP:
if (pmt_eq(event, s_response_open)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
allocate_channel();
return;
}
else {
error_msg = "failed to open usrp:";
goto bail;
}
}
goto unhandled;
//----------------------- ALLOCATING CHANNELS --------------------//
// Allocate an RX channel to perform the overrun test.
case ALLOCATING_CHANNEL:
if (pmt_eq(event, s_response_allocate_channel)){
status = pmt_nth(1, data);
d_rx_chan = pmt_nth(2, data);
if (pmt_eq(status, PMT_T)){
enter_receiving();
return;
}
else {
error_msg = "failed to allocate channel:";
goto bail;
}
}
goto unhandled;
//--------------------------- RECEIVING ------------------------------//
// In the receiving state, we receive samples until the specified amount
// while counting the number of overruns.
case RECEIVING:
if (pmt_eq(event, s_response_recv_raw_samples)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
handle_response_recv_raw_samples(data);
return;
}
else {
error_msg = "bad response-xmit-raw-frame:";
goto bail;
}
}
goto unhandled;
//------------------------- CLOSING CHANNEL ----------------------------//
// Check deallocation response for the RX channel
case CLOSING_CHANNEL:
if (pmt_eq(event, s_response_deallocate_channel)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
close_usrp();
return;
}
else {
error_msg = "failed to deallocate channel:";
goto bail;
}
}
// Alternately, we ignore all response recv samples while waiting for the
// channel to actually close
if (pmt_eq(event, s_response_recv_raw_samples))
return;
goto unhandled;
//--------------------------- CLOSING USRP ------------------------------//
// Once we have received a successful USRP close response, we shutdown all
// mblocks and exit.
case CLOSING_USRP:
if (pmt_eq(event, s_response_close)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
std::cout << "\nOverruns: " << d_n_overruns << std::endl;
fflush(stdout);
shutdown_all(PMT_T);
return;
}
else {
error_msg = "failed to close USRP:";
goto bail;
}
}
goto unhandled;
default:
goto unhandled;
}
return;
// An error occured, print it, and shutdown all m-blocks
bail:
std::cerr << error_msg << data
<< "status = " << status << std::endl;
shutdown_all(PMT_F);
return;
// Received an unhandled message for a specific state
unhandled:
if(verbose && !pmt_eq(event, pmt_intern("%shutdown")))
std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
<< "in state "<< d_state << std::endl;
}
void
test_usrp_rx::open_usrp()
{
pmt_t which_usrp = pmt_from_long(0);
d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, which_usrp));
d_state = OPENING_USRP;
if(verbose)
std::cout << "[TEST_USRP_INBAND_OVERRUN] Opening the USRP\n";
}
void
test_usrp_rx::close_usrp()
{
d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
d_state = CLOSING_USRP;
if(verbose)
std::cout << "[TEST_USRP_INBAND_OVERRUN] Closing the USRP\n";
}
void
test_usrp_rx::allocate_channel()
{
long capacity = (long) 16e6;
d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
d_state = ALLOCATING_CHANNEL;
if(verbose)
std::cout << "[TEST_USRP_INBAND_OVERRUN] Requesting RX channel allocation\n";
}
void
test_usrp_rx::enter_receiving()
{
d_state = RECEIVING;
d_rx->send(s_cmd_start_recv_raw_samples,
pmt_list2(PMT_F,
d_rx_chan));
if(verbose)
std::cout << "[TEST_USRP_INBAND_OVERRUN] Receiving...\n";
}
void
test_usrp_rx::handle_response_recv_raw_samples(pmt_t data)
{
pmt_t invocation_handle = pmt_nth(0, data);
pmt_t status = pmt_nth(1, data);
pmt_t v_samples = pmt_nth(2, data);
pmt_t timestamp = pmt_nth(3, data);
pmt_t channel = pmt_nth(4, data);
pmt_t properties = pmt_nth(5, data);
d_samples_recvd += pmt_length(v_samples) / 4;
// Check for overrun
if(!pmt_is_dict(properties)) {
std::cout << "[TEST_USRP_INBAND_OVERRUN] Recv samples dictionary is improper\n";
return;
}
if(pmt_t overrun = pmt_dict_ref(properties,
pmt_intern("overrun"),
PMT_NIL)) {
if(pmt_eqv(overrun, PMT_T)) {
d_n_overruns++;
if(verbose && 0)
std::cout << "[TEST_USRP_INBAND_OVERRUN] Underrun\n";
}
else {
if(verbose && 0)
std::cout << "[TEST_USRP_INBAND_OVERRUN] No overrun\n" << overrun <<std::endl;
}
} else {
if(verbose && 0)
std::cout << "[TEST_USRP_INBAND_OVERRUN] No overrun\n";
}
// Check if the number samples we have received meets the test
if(d_samples_recvd >= d_samples_to_recv) {
d_rx->send(s_cmd_stop_recv_raw_samples, pmt_list2(PMT_NIL, d_rx_chan));
enter_closing_channel();
return;
}
}
void
test_usrp_rx::enter_closing_channel()
{
d_state = CLOSING_CHANNEL;
sleep(2);
d_rx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_rx_chan));
if(verbose)
std::cout << "[TEST_USRP_INBAND_OVERRUN] Deallocating RX channel\n";
}
REGISTER_MBLOCK_CLASS(test_usrp_rx);
// ----------------------------------------------------------------
int
main (int argc, char **argv)
{
// handle any command line args here
mb_runtime_sptr rt = mb_make_runtime();
pmt_t result = PMT_NIL;
rt->run("top", "test_usrp_rx", PMT_F, &result);
}

View File

@ -1,374 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,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 <mblock/mblock.h>
#include <mblock/runtime.h>
#include <mblock/protocol_class.h>
#include <mblock/exception.h>
#include <mblock/msg_queue.h>
#include <mblock/message.h>
#include <mblock/msg_accepter.h>
#include <mblock/class_registry.h>
#include <pmt.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <iostream>
// Include the symbols needed for communication with USRP server
#include <symbols_usrp_server_cs.h>
#include <symbols_usrp_channel.h>
#include <symbols_usrp_low_level_cs.h>
#include <symbols_usrp_tx.h>
#include <symbols_usrp_rx.h>
static bool verbose = false;
class test_usrp_inband_ping : public mb_mblock
{
mb_port_sptr d_tx; // Ports connected to the USRP server
mb_port_sptr d_rx;
mb_port_sptr d_cs;
pmt_t d_tx_chan; // Returned channel from TX allocation
pmt_t d_rx_chan; // Returned channel from RX allocation
pmt_t d_which_usrp; // The USRP to use for the test
long d_warm_msgs; // The number of messages to 'warm' the USRP
long d_warm_recvd; // The number of msgs received in the 'warm' state
// Keep track of current state
enum state_t {
INIT,
OPENING_USRP,
ALLOCATING_CHANNELS,
WARMING_USRP,
PINGING,
CLOSING_CHANNELS,
CLOSING_USRP,
};
state_t d_state;
public:
test_usrp_inband_ping(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
~test_usrp_inband_ping();
void initial_transition();
void handle_message(mb_message_sptr msg);
protected:
void opening_usrp();
void allocating_channels();
void enter_warming_usrp();
void enter_pinging();
void build_and_send_ping();
void closing_channels();
void closing_usrp();
};
int
main (int argc, char **argv)
{
// handle any command line args here
mb_runtime_sptr rt = mb_make_runtime();
pmt_t result = PMT_NIL;
rt->run("top", "test_usrp_inband_ping", PMT_F, &result);
}
test_usrp_inband_ping::test_usrp_inband_ping(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
: mb_mblock(runtime, instance_name, user_arg),
d_tx_chan(PMT_NIL),
d_rx_chan(PMT_NIL),
d_which_usrp(pmt_from_long(0)),
d_state(INIT)
{
// A dictionary is used to pass parameters to the USRP
pmt_t usrp_dict = pmt_make_dict();
// Specify the RBF to use
pmt_dict_set(usrp_dict,
pmt_intern("rbf"),
pmt_intern("fixed1.rbf"));
// Set TX and RX interpolations
pmt_dict_set(usrp_dict,
pmt_intern("interp-tx"),
pmt_from_long(128));
pmt_dict_set(usrp_dict,
pmt_intern("decim-rx"),
pmt_from_long(16));
d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
// Create an instance of USRP server and connect ports
define_component("server", "usrp_server", usrp_dict);
connect("self", "tx0", "server", "tx0");
connect("self", "rx0", "server", "rx0");
connect("self", "cs", "server", "cs");
}
test_usrp_inband_ping::~test_usrp_inband_ping()
{
}
void
test_usrp_inband_ping::initial_transition()
{
opening_usrp();
}
// Handle message reads all incoming messages from USRP server which will be
// initialization and ping responses. We perform actions based on the current
// state and the event (ie, ping response)
void
test_usrp_inband_ping::handle_message(mb_message_sptr msg)
{
pmt_t event = msg->signal();
pmt_t data = msg->data();
pmt_t port_id = msg->port_id();
pmt_t handle = PMT_F;
pmt_t status = PMT_F;
std::string error_msg;
// Dispatch based on state
switch(d_state) {
//----------------------------- OPENING_USRP ----------------------------//
// We only expect a response from opening the USRP which should be succesful
// or failed.
case OPENING_USRP:
if(pmt_eq(event, s_response_open)) {
status = pmt_nth(1, data); // failed/succes
if(pmt_eq(status, PMT_T)) {
allocating_channels();
return;
}
else {
error_msg = "failed to open usrp:";
goto bail;
}
}
goto unhandled; // all other messages not handled in this state
//----------------------- ALLOCATING CHANNELS --------------------//
// When allocating channels, we need to wait for 2 responses from
// USRP server: one for TX and one for RX. Both are initialized to
// NIL so we know to continue to the next state once both are set.
case ALLOCATING_CHANNELS:
// A TX allocation response
if(pmt_eq(event, s_response_allocate_channel)
&& pmt_eq(d_tx->port_symbol(), port_id))
{
status = pmt_nth(1, data);
// If successful response, extract the channel
if(pmt_eq(status, PMT_T)) {
d_tx_chan = pmt_nth(2, data);
if(verbose)
std::cout << "[TEST_USRP_INBAND_PING] Received TX allocation"
<< " on channel " << d_tx_chan << std::endl;
// If the RX has also been allocated already, we can continue
if(!pmt_eqv(d_rx_chan, PMT_NIL))
enter_warming_usrp();
return;
}
else { // TX allocation failed
error_msg = "failed to allocate TX channel:";
goto bail;
}
}
// A RX allocation response
if(pmt_eq(event, s_response_allocate_channel)
&& pmt_eq(d_rx->port_symbol(), port_id))
{
status = pmt_nth(1, data);
// If successful response, extract the channel
if(pmt_eq(status, PMT_T)) {
d_rx_chan = pmt_nth(2, data);
if(verbose)
std::cout << "[TEST_USRP_INBAND_PING] Received RX allocation"
<< " on channel " << d_rx_chan << std::endl;
// If the TX has also been allocated already, we can continue
if(!pmt_eqv(d_tx_chan, PMT_NIL))
enter_warming_usrp();
return;
}
else { // RX allocation failed
error_msg = "failed to allocate RX channel:";
goto bail;
}
}
goto unhandled;
//----------------------- WARMING USRP --------------------//
// The FX2 seems to need some amount of data to be buffered
// before it begins reading. We use this state to simply
// warm up the USRP before benchmarking pings.
case WARMING_USRP:
// We really don't care about the responses from the
// control channel in the warming stage, but once we receive
// the proper number of responses we switch states.
if(pmt_eq(event, s_response_from_control_channel)
&& pmt_eq(d_rx->port_symbol(), port_id))
{
d_warm_recvd++;
if(d_warm_recvd > d_warm_msgs)
enter_pinging();
return;
}
goto unhandled;
case PINGING:
goto unhandled;
case CLOSING_CHANNELS:
goto unhandled;
case CLOSING_USRP:
goto unhandled;
case INIT:
goto unhandled;
}
// An error occured, print it, and shutdown all m-blocks
bail:
std::cerr << error_msg << data
<< "status = " << status << std::endl;
shutdown_all(PMT_F);
return;
// Received an unhandled message for a specific state
unhandled:
if(verbose)
std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
<< "in state "<< d_state << std::endl;
}
// Sends a command to USRP server to open up a connection to the
// specified USRP, which is defaulted to USRP 0 on the system
void
test_usrp_inband_ping::opening_usrp()
{
if(verbose)
std::cout << "[TEST_USRP_INBAND_PING] Opening USRP "
<< d_which_usrp << std::endl;
d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, d_which_usrp));
d_state = OPENING_USRP;
}
// RX and TX channels must be allocated so that the USRP server can
// properly share bandwidth across multiple USRPs. No commands will be
// successful to the USRP through the USRP server on the TX or RX channels until
// a bandwidth allocation has been received.
void
test_usrp_inband_ping::allocating_channels()
{
d_state = ALLOCATING_CHANNELS;
long capacity = (long) 16e6;
d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
}
// The USRP needs some amount of initial data to pass a buffering point such
// that it begins to pull and read data from the FX2. We send an arbitrary
// amount of data to start the pipeline, which are just pings.
void
test_usrp_inband_ping::enter_warming_usrp()
{
d_state = WARMING_USRP;
for(int i=0; i < d_warm_msgs; i++)
build_and_send_ping();
}
void
test_usrp_inband_ping::enter_pinging()
{
d_state = PINGING;
if(verbose)
std::cout << "[TEST_USRP_INBAND_PING] Running ping tests\n";
}
// Pings are sent over the TX channel using the signal 'cmd-to-control-channel'
// to the USRP server. Within this message there can be infinite subpackets
// stored as a list (the second parameter) and sent. The only subpacket we send
// is a ping, interpreted by the 'op-ping-fixed' signal.
void
test_usrp_inband_ping::build_and_send_ping()
{
d_tx->send(s_cmd_to_control_channel, // USRP server signal
pmt_list2(PMT_NIL, // invocation handle
pmt_list1(pmt_list3(s_op_ping_fixed,
pmt_from_long(0),
pmt_from_long(0)))));
if(verbose)
std::cout << "[TEST_USRP_INBAND_PING] Ping!!" << std::endl;
}
REGISTER_MBLOCK_CLASS(test_usrp_inband_ping);

View File

@ -1,435 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 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 <mblock/mblock.h>
#include <mblock/runtime.h>
#include <mblock/protocol_class.h>
#include <mblock/exception.h>
#include <mblock/msg_queue.h>
#include <mblock/message.h>
//#include <mb_mblock_impl.h>
#include <mblock/msg_accepter.h>
#include <mblock/class_registry.h>
#include <pmt.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <iostream>
// Include the symbols needed for communication with USRP server
#include <symbols_usrp_server_cs.h>
#include <symbols_usrp_channel.h>
#include <symbols_usrp_low_level_cs.h>
#include <symbols_usrp_tx.h>
#include <symbols_usrp_rx.h>
static bool verbose = true;
class test_usrp_inband_registers : public mb_mblock
{
mb_port_sptr d_tx; // Ports connected to the USRP server
mb_port_sptr d_rx;
mb_port_sptr d_cs;
pmt_t d_tx_chan; // Returned channel from TX allocation
pmt_t d_rx_chan; // Returned channel from RX allocation
pmt_t d_which_usrp; // The USRP to use for the test
long d_warm_msgs; // The number of messages to 'warm' the USRP
long d_warm_recvd; // The number of msgs received in the 'warm' state
// Keep track of current state
enum state_t {
INIT,
OPENING_USRP,
ALLOCATING_CHANNELS,
WRITE_REGISTER,
READ_REGISTER,
CLOSING_CHANNELS,
CLOSING_USRP,
};
state_t d_state;
public:
test_usrp_inband_registers(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
~test_usrp_inband_registers();
void initial_transition();
void handle_message(mb_message_sptr msg);
protected:
void opening_usrp();
void allocating_channels();
void write_register();
void read_register();
void closing_channels();
void closing_usrp();
void enter_receiving();
void build_and_send_ping();
};
int
main (int argc, char **argv)
{
// handle any command line args here
mb_runtime_sptr rt = mb_make_runtime();
pmt_t result = PMT_NIL;
rt->run("top", "test_usrp_inband_registers", PMT_F, &result);
}
test_usrp_inband_registers::test_usrp_inband_registers(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
: mb_mblock(runtime, instance_name, user_arg),
d_tx_chan(PMT_NIL),
d_rx_chan(PMT_NIL),
d_which_usrp(pmt_from_long(0)),
d_state(INIT)
{
// A dictionary is used to pass parameters to the USRP
pmt_t usrp_dict = pmt_make_dict();
// Specify the RBF to use
pmt_dict_set(usrp_dict,
pmt_intern("rbf"),
pmt_intern("inband_1rxhb_1tx.rbf"));
// Set TX and RX interpolations
pmt_dict_set(usrp_dict,
pmt_intern("interp-tx"),
pmt_from_long(128));
pmt_dict_set(usrp_dict,
pmt_intern("decim-rx"),
pmt_from_long(16));
d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
// Create an instance of USRP server and connect ports
define_component("server", "usrp_server", usrp_dict);
connect("self", "tx0", "server", "tx0");
connect("self", "rx0", "server", "rx0");
connect("self", "cs", "server", "cs");
}
test_usrp_inband_registers::~test_usrp_inband_registers()
{
}
void
test_usrp_inband_registers::initial_transition()
{
opening_usrp();
}
// Handle message reads all incoming messages from USRP server which will be
// initialization and ping responses. We perform actions based on the current
// state and the event (ie, ping response)
void
test_usrp_inband_registers::handle_message(mb_message_sptr msg)
{
pmt_t event = msg->signal();
pmt_t data = msg->data();
pmt_t port_id = msg->port_id();
pmt_t handle = PMT_F;
pmt_t status = PMT_F;
std::string error_msg;
// Dispatch based on state
switch(d_state) {
//----------------------------- OPENING_USRP ----------------------------//
// We only expect a response from opening the USRP which should be succesful
// or failed.
case OPENING_USRP:
if(pmt_eq(event, s_response_open)) {
status = pmt_nth(1, data); // failed/succes
if(pmt_eq(status, PMT_T)) {
allocating_channels();
return;
}
else {
error_msg = "failed to open usrp:";
goto bail;
}
}
goto unhandled; // all other messages not handled in this state
//----------------------- ALLOCATING CHANNELS --------------------//
// When allocating channels, we need to wait for 2 responses from
// USRP server: one for TX and one for RX. Both are initialized to
// NIL so we know to continue to the next state once both are set.
case ALLOCATING_CHANNELS:
// A TX allocation response
if(pmt_eq(event, s_response_allocate_channel)
&& pmt_eq(d_tx->port_symbol(), port_id))
{
status = pmt_nth(1, data);
// If successful response, extract the channel
if(pmt_eq(status, PMT_T)) {
d_tx_chan = pmt_nth(2, data);
if(verbose)
std::cout << "[TEST_USRP_INBAND_PING] Received TX allocation"
<< " on channel " << d_tx_chan << std::endl;
// If the RX has also been allocated already, we can continue
if(!pmt_eqv(d_rx_chan, PMT_NIL)) {
enter_receiving();
write_register();
}
return;
}
else { // TX allocation failed
error_msg = "failed to allocate TX channel:";
goto bail;
}
}
// A RX allocation response
if(pmt_eq(event, s_response_allocate_channel)
&& pmt_eq(d_rx->port_symbol(), port_id))
{
status = pmt_nth(1, data);
// If successful response, extract the channel
if(pmt_eq(status, PMT_T)) {
d_rx_chan = pmt_nth(2, data);
if(verbose)
std::cout << "[TEST_USRP_INBAND_PING] Received RX allocation"
<< " on channel " << d_rx_chan << std::endl;
// If the TX has also been allocated already, we can continue
if(!pmt_eqv(d_tx_chan, PMT_NIL)) {
enter_receiving();
write_register();
}
return;
}
else { // RX allocation failed
error_msg = "failed to allocate RX channel:";
goto bail;
}
}
goto unhandled;
//-------------------------- WRITE REGISTER ----------------------------//
// In the write register state, we do not expect to receive any messages
// since the write does not directly generate a response until the USRP
// responds.
case WRITE_REGISTER:
goto unhandled;
//-------------------------- READ REGISTER ----------------------------//
// In the read register state, we only expect a read register response back
// that has the value we expect to have in it. We read the response, ensure
// that the read was successful and display the register value.
case READ_REGISTER:
if(pmt_eq(event, s_response_from_control_channel)
&& pmt_eq(d_tx->port_symbol(), port_id))
{
status = pmt_nth(1, data);
// If the read was successful, we extract the subpacket information
if(pmt_eq(status, PMT_T)) {
pmt_t subp = pmt_nth(2, data); // subpacket should be the read reg reply
pmt_t subp_sig = pmt_nth(0, subp);
pmt_t subp_data = pmt_nth(1, subp);
if(!pmt_eqv(subp_sig, s_op_read_reg_reply)) {
error_msg = "received improper subpacket when expecting reg reply.";
goto bail;
}
pmt_t rid = pmt_nth(0, subp_data);
pmt_t reg_num = pmt_nth(1, subp_data);
pmt_t reg_val = pmt_nth(2, subp_data);
if(verbose)
std::cout << "[TEST_USRP_INBAND_REGISTERS] Received read reg reply "
<< "("
<< "RID: " << rid << ", "
<< "Reg: " << reg_num << ", "
<< "Val: " << reg_val
<< ")\n";
// read_register(); FIX ME STATE TRANSITION
return;
} else { // bail on unsuccessful write
error_msg = "failed to write to register.";
goto bail;
}
}
goto unhandled;
case CLOSING_CHANNELS:
goto unhandled;
case CLOSING_USRP:
goto unhandled;
case INIT:
goto unhandled;
}
// An error occured, print it, and shutdown all m-blocks
bail:
std::cerr << error_msg << data
<< "status = " << status << std::endl;
shutdown_all(PMT_F);
return;
// Received an unhandled message for a specific state
unhandled:
if(verbose && !pmt_eq(event, s_response_recv_raw_samples))
std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
<< "in state "<< d_state << std::endl;
}
// Sends a command to USRP server to open up a connection to the
// specified USRP, which is defaulted to USRP 0 on the system
void
test_usrp_inband_registers::opening_usrp()
{
if(verbose)
std::cout << "[TEST_USRP_INBAND_PING] Opening USRP "
<< d_which_usrp << std::endl;
d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, d_which_usrp));
d_state = OPENING_USRP;
}
// RX and TX channels must be allocated so that the USRP server can
// properly share bandwidth across multiple USRPs. No commands will be
// successful to the USRP through the USRP server on the TX or RX channels until
// a bandwidth allocation has been received.
void
test_usrp_inband_registers::allocating_channels()
{
d_state = ALLOCATING_CHANNELS;
long capacity = (long) 16e6;
d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
}
// After allocating the channels, a write register command will be sent to the
// USRP.
void
test_usrp_inband_registers::write_register()
{
d_state = WRITE_REGISTER;
long reg = 0;
d_tx->send(s_cmd_to_control_channel, // C/S packet
pmt_list2(PMT_NIL, // invoc handle
pmt_list1(
pmt_list2(s_op_write_reg,
pmt_list2(
pmt_from_long(reg),
pmt_from_long(0xbeef))))));
if(verbose)
std::cout << "[TEST_USRP_INBAND_REGISTERS] Writing 0xbeef to "
<< reg << std::endl;
read_register(); // immediately transition to read the register
}
// Temporary: for testing pings
void
test_usrp_inband_registers::build_and_send_ping()
{
d_tx->send(s_cmd_to_control_channel,
pmt_list2(PMT_NIL, pmt_list1(pmt_list2(s_op_ping_fixed,
pmt_list2(pmt_from_long(0),
pmt_from_long(0))))));
std::cout << "[TEST_USRP_INBAND_CS] Ping sent" << std::endl;
}
// After writing to the register, we want to read the value back and ensure that
// it is the same value that we wrote.
void
test_usrp_inband_registers::read_register()
{
d_state = READ_REGISTER;
long reg = 9;
d_tx->send(s_cmd_to_control_channel, // C/S packet
pmt_list2(PMT_NIL, // invoc handle
pmt_list1(
pmt_list2(s_op_read_reg,
pmt_list2(
pmt_from_long(0), // rid
pmt_from_long(reg))))));
if(verbose)
std::cout << "[TEST_USRP_INBAND_REGISTERS] Reading from register "
<< reg << std::endl;
}
// Used to enter the receiving state
void
test_usrp_inband_registers::enter_receiving()
{
d_rx->send(s_cmd_start_recv_raw_samples,
pmt_list2(PMT_F,
d_rx_chan));
}
REGISTER_MBLOCK_CLASS(test_usrp_inband_registers);

View File

@ -1,362 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 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 <mblock/mblock.h>
#include <mblock/runtime.h>
#include <mblock/protocol_class.h>
#include <mblock/exception.h>
#include <mblock/msg_queue.h>
#include <mblock/message.h>
#include <mblock/msg_accepter.h>
#include <mblock/class_registry.h>
#include <pmt.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <fstream>
// Include the symbols needed for communication with USRP server
#include <symbols_usrp_server_cs.h>
#include <symbols_usrp_channel.h>
#include <symbols_usrp_low_level_cs.h>
#include <symbols_usrp_rx.h>
static bool verbose = true;
class test_usrp_rx : public mb_mblock
{
mb_port_sptr d_rx;
mb_port_sptr d_cs;
pmt_t d_rx_chan; // returned tx channel handle
enum state_t {
INIT,
OPENING_USRP,
ALLOCATING_CHANNEL,
RECEIVING,
CLOSING_CHANNEL,
CLOSING_USRP,
};
state_t d_state;
std::ofstream d_ofile;
long d_samples_recvd;
long d_samples_to_recv;
public:
test_usrp_rx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
~test_usrp_rx();
void initial_transition();
void handle_message(mb_message_sptr msg);
protected:
void open_usrp();
void close_usrp();
void allocate_channel();
void send_packets();
void enter_receiving();
void build_and_send_next_frame();
void handle_response_recv_raw_samples(pmt_t invocation_handle);
void enter_closing_channel();
};
test_usrp_rx::test_usrp_rx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
: mb_mblock(runtime, instance_name, user_arg),
d_samples_recvd(0),
d_samples_to_recv(20e6)
{
d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
// Pass a dictionary to usrp_server which specifies which interface to use, the stub or USRP
pmt_t usrp_dict = pmt_make_dict();
// To test the application without a USRP
bool fake_usrp_p = false;
if(fake_usrp_p) {
pmt_dict_set(usrp_dict,
pmt_intern("fake-usrp"),
PMT_T);
}
// Specify the RBF to use
pmt_dict_set(usrp_dict,
pmt_intern("rbf"),
pmt_intern("inband_1rxhb_1tx.rbf"));
pmt_dict_set(usrp_dict,
pmt_intern("decim-rx"),
pmt_from_long(64));
// If unspecified, chooses center frequency from range
// pmt_dict_set(usrp_dict,
// pmt_intern("rf-freq"),
// pmt_from_long(10e6));
define_component("server", "usrp_server", usrp_dict);
connect("self", "rx0", "server", "rx0");
connect("self", "cs", "server", "cs");
}
test_usrp_rx::~test_usrp_rx()
{
}
void
test_usrp_rx::initial_transition()
{
open_usrp();
}
void
test_usrp_rx::handle_message(mb_message_sptr msg)
{
pmt_t event = msg->signal();
pmt_t data = msg->data();
pmt_t handle = PMT_F;
pmt_t status = PMT_F;
std::string error_msg;
switch(d_state){
//----------------------------- OPENING_USRP ----------------------------//
// We only expect a response from opening the USRP which should be succesful
// or failed.
case OPENING_USRP:
if (pmt_eq(event, s_response_open)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
allocate_channel();
return;
}
else {
error_msg = "failed to open usrp:";
goto bail;
}
}
goto unhandled;
//----------------------- ALLOCATING CHANNELS --------------------//
// Allocate an RX channel to perform the overrun test.
case ALLOCATING_CHANNEL:
if (pmt_eq(event, s_response_allocate_channel)){
status = pmt_nth(1, data);
d_rx_chan = pmt_nth(2, data);
if (pmt_eq(status, PMT_T)){
enter_receiving();
return;
}
else {
error_msg = "failed to allocate channel:";
goto bail;
}
}
goto unhandled;
//--------------------------- RECEIVING ------------------------------//
// In the receiving state, we receive samples until the specified amount
// while counting the number of overruns.
case RECEIVING:
if (pmt_eq(event, s_response_recv_raw_samples)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
handle_response_recv_raw_samples(data);
return;
}
else {
error_msg = "bad response-xmit-raw-frame:";
goto bail;
}
}
goto unhandled;
//------------------------- CLOSING CHANNEL ----------------------------//
// Check deallocation response for the RX channel
case CLOSING_CHANNEL:
if (pmt_eq(event, s_response_deallocate_channel)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
close_usrp();
return;
}
else {
error_msg = "failed to deallocate channel:";
goto bail;
}
}
// Alternately, we ignore all response recv samples while waiting for the
// channel to actually close
if (pmt_eq(event, s_response_recv_raw_samples))
return;
goto unhandled;
//--------------------------- CLOSING USRP ------------------------------//
// Once we have received a successful USRP close response, we shutdown all
// mblocks and exit.
case CLOSING_USRP:
if (pmt_eq(event, s_response_close)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
fflush(stdout);
shutdown_all(PMT_T);
return;
}
else {
error_msg = "failed to close USRP:";
goto bail;
}
}
goto unhandled;
default:
goto unhandled;
}
return;
// An error occured, print it, and shutdown all m-blocks
bail:
std::cerr << error_msg << data
<< "status = " << status << std::endl;
shutdown_all(PMT_F);
return;
// Received an unhandled message for a specific state
unhandled:
if(verbose && !pmt_eq(event, pmt_intern("%shutdown")))
std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
<< "in state "<< d_state << std::endl;
}
void
test_usrp_rx::open_usrp()
{
pmt_t which_usrp = pmt_from_long(0);
d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, which_usrp));
d_state = OPENING_USRP;
if(verbose)
std::cout << "[TEST_USRP_INBAND_RX] Opening the USRP\n";
}
void
test_usrp_rx::close_usrp()
{
d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
d_state = CLOSING_USRP;
if(verbose)
std::cout << "[TEST_USRP_INBAND_RX] Closing the USRP\n";
}
void
test_usrp_rx::allocate_channel()
{
long capacity = (long) 16e6;
d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
d_state = ALLOCATING_CHANNEL;
if(verbose)
std::cout << "[TEST_USRP_INBAND_RX] Requesting RX channel allocation\n";
}
void
test_usrp_rx::enter_receiving()
{
d_state = RECEIVING;
d_rx->send(s_cmd_start_recv_raw_samples,
pmt_list2(PMT_F,
d_rx_chan));
if(verbose)
std::cout << "[TEST_USRP_INBAND_RX] Receiving...\n";
}
void
test_usrp_rx::handle_response_recv_raw_samples(pmt_t data)
{
pmt_t invocation_handle = pmt_nth(0, data);
pmt_t status = pmt_nth(1, data);
pmt_t v_samples = pmt_nth(2, data);
pmt_t timestamp = pmt_nth(3, data);
pmt_t channel = pmt_nth(4, data);
pmt_t properties = pmt_nth(5, data);
d_samples_recvd += pmt_length(v_samples) / 4;
// Check for overrun
if(!pmt_is_dict(properties)) {
std::cout << "[TEST_USRP_INBAND_RX] Recv samples dictionary is improper\n";
return;
}
// Check if the number samples we have received meets the test
if(d_samples_recvd >= d_samples_to_recv) {
d_rx->send(s_cmd_stop_recv_raw_samples, pmt_list2(PMT_NIL, d_rx_chan));
enter_closing_channel();
return;
}
}
void
test_usrp_rx::enter_closing_channel()
{
d_state = CLOSING_CHANNEL;
d_rx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_rx_chan));
if(verbose)
std::cout << "[TEST_USRP_INBAND_RX] Deallocating RX channel\n";
}
REGISTER_MBLOCK_CLASS(test_usrp_rx);
// ----------------------------------------------------------------
int
main (int argc, char **argv)
{
mb_runtime_sptr rt = mb_make_runtime();
pmt_t result = PMT_NIL;
rt->run("top", "test_usrp_rx", PMT_F, &result);
}

View File

@ -1,506 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,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 <mblock/mblock.h>
#include <mblock/runtime.h>
#include <mblock/protocol_class.h>
#include <mblock/exception.h>
#include <mblock/msg_queue.h>
#include <mblock/message.h>
#include <mblock/msg_accepter.h>
#include <mblock/class_registry.h>
#include <pmt.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <iostream>
#include <ui_nco.h>
#include <symbols_usrp_server_cs.h>
#include <symbols_usrp_channel.h>
#include <symbols_usrp_low_level_cs.h>
#include <symbols_usrp_tx.h>
#include <symbols_usrp_rx.h>
#define NBPING 10
static bool verbose = true;
bool bskip = false;
long bstep = 10000;
long bcurr = 0;
long incr = 0x500;
long ptime = 0x000;
class test_usrp_inband_timestamps : public mb_mblock
{
mb_port_sptr d_tx;
mb_port_sptr d_rx;
mb_port_sptr d_cs;
pmt_t d_tx_chan; // returned tx channel handle
pmt_t d_rx_chan; // returned tx channel handle
struct timeval times[NBPING];
enum state_t {
INIT,
OPENING_USRP,
ALLOCATING_CHANNEL,
TRANSMITTING,
CLOSING_CHANNEL,
CLOSING_USRP,
};
state_t d_state;
long d_nsamples_to_send;
long d_nsamples_xmitted;
long d_nframes_xmitted;
long d_samples_per_frame;
bool d_done_sending;
// for generating sine wave output
ui_nco<float,float> d_nco;
double d_amplitude;
public:
test_usrp_inband_timestamps(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
~test_usrp_inband_timestamps();
void initial_transition();
void handle_message(mb_message_sptr msg);
protected:
void open_usrp();
void close_usrp();
void allocate_channel();
void send_packets();
void enter_receiving();
void enter_transmitting();
void build_and_send_ping();
void build_and_send_next_frame();
void handle_xmit_response(pmt_t invocation_handle);
void enter_closing_channel();
};
test_usrp_inband_timestamps::test_usrp_inband_timestamps(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
: mb_mblock(runtime, instance_name, user_arg),
d_tx_chan(PMT_NIL),
d_rx_chan(PMT_NIL),
d_state(INIT), d_nsamples_to_send((long) 40e6),
d_nsamples_xmitted(0),
d_nframes_xmitted(0),
//d_samples_per_frame((long)(126)),
d_samples_per_frame((long)(126 * 2)), // non-full packet
//d_samples_per_frame((long)(126 * 3.5)), // non-full packet
//d_samples_per_frame((long)(126 * 4)), // full packet
d_done_sending(false),
d_amplitude(16384)
{
if(verbose)
std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Initializing...\n";
d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
bool fake_usrp_p = false;
// Test the TX side
pmt_t usrp_dict = pmt_make_dict();
if(fake_usrp_p) {
pmt_dict_set(usrp_dict,
pmt_intern("fake-usrp"),
PMT_T);
}
// Set TX and RX interpolations
pmt_dict_set(usrp_dict,
pmt_intern("interp-tx"),
pmt_from_long(128));
pmt_dict_set(usrp_dict,
pmt_intern("decim-rx"),
pmt_from_long(16));
// Specify the RBF to use
pmt_dict_set(usrp_dict,
pmt_intern("rbf"),
pmt_intern("inband_1rxhb_1tx.rbf"));
define_component("server", "usrp_server", usrp_dict);
connect("self", "tx0", "server", "tx0");
connect("self", "rx0", "server", "rx0");
connect("self", "cs", "server", "cs");
// initialize NCO
double freq = 100e3;
int interp = 32; // 32 -> 4MS/s
double sample_rate = 128e6 / interp;
d_nco.set_freq(2*M_PI * freq/sample_rate);
}
test_usrp_inband_timestamps::~test_usrp_inband_timestamps()
{
}
void
test_usrp_inband_timestamps::initial_transition()
{
open_usrp();
}
void
test_usrp_inband_timestamps::handle_message(mb_message_sptr msg)
{
pmt_t event = msg->signal();
pmt_t data = msg->data();
pmt_t port_id = msg->port_id();
pmt_t handle = PMT_F;
pmt_t status = PMT_F;
std::string error_msg;
//std::cout << msg << std::endl;
switch(d_state){
case OPENING_USRP:
if (pmt_eq(event, s_response_open)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
allocate_channel();
return;
}
else {
error_msg = "failed to open usrp:";
goto bail;
}
}
goto unhandled;
case ALLOCATING_CHANNEL:
if (pmt_eq(event, s_response_allocate_channel)){
if(pmt_eq(d_tx->port_symbol(), port_id)) {
status = pmt_nth(1, data);
d_tx_chan = pmt_nth(2, data);
if (pmt_eq(status, PMT_T)){
if(verbose)
std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Received allocation for TX\n";
if(!pmt_eqv(d_rx_chan, PMT_NIL)) {
enter_receiving();
enter_transmitting();
}
return;
}
else {
error_msg = "failed to allocate channel:";
goto bail;
}
}
if(pmt_eq(d_rx->port_symbol(), port_id)) {
status = pmt_nth(1, data);
d_rx_chan = pmt_nth(2, data);
if (pmt_eq(status, PMT_T)){
if(verbose)
std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Received allocation for TX\n";
if(!pmt_eqv(d_tx_chan, PMT_NIL)) {
enter_receiving();
enter_transmitting();
}
return;
}
else {
error_msg = "failed to allocate channel:";
goto bail;
}
}
}
goto unhandled;
case TRANSMITTING:
if (pmt_eq(event, s_response_xmit_raw_frame)){
handle = pmt_nth(0, data);
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
handle_xmit_response(handle);
return;
}
else {
error_msg = "bad response-xmit-raw-frame:";
goto bail;
}
}
if (pmt_eq(event, s_response_from_control_channel)) {
std::cout << "ping response!\n";
}
goto unhandled;
case CLOSING_CHANNEL:
if (pmt_eq(event, s_response_deallocate_channel)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
close_usrp();
return;
}
else {
error_msg = "failed to deallocate channel:";
goto bail;
}
}
goto unhandled;
case CLOSING_USRP:
if (pmt_eq(event, s_response_close)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
shutdown_all(PMT_T);
return;
}
else {
error_msg = "failed to close USRP:";
goto bail;
}
}
goto unhandled;
default:
goto unhandled;
}
return;
bail:
std::cerr << error_msg << data
<< "status = " << status << std::endl;
shutdown_all(PMT_F);
return;
unhandled:
if(verbose && 0)
std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
<< "in state "<< d_state << std::endl;
}
void
test_usrp_inband_timestamps::open_usrp()
{
pmt_t which_usrp = pmt_from_long(0);
d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, which_usrp));
d_state = OPENING_USRP;
}
void
test_usrp_inband_timestamps::close_usrp()
{
d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
d_state = CLOSING_USRP;
if(verbose)
std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Closing USRP\n";
}
void
test_usrp_inband_timestamps::allocate_channel()
{
long capacity = (long) 16e6;
d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
d_state = ALLOCATING_CHANNEL;
}
void
test_usrp_inband_timestamps::enter_receiving()
{
d_rx->send(s_cmd_start_recv_raw_samples,
pmt_list2(PMT_F,
d_rx_chan));
}
void
test_usrp_inband_timestamps::enter_transmitting()
{
d_state = TRANSMITTING;
d_nsamples_xmitted = 0;
if(verbose)
std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Beginning transmission\n";
sleep(1);
build_and_send_next_frame();
build_and_send_next_frame();
build_and_send_next_frame();
build_and_send_next_frame();
}
void
test_usrp_inband_timestamps::build_and_send_ping()
{
d_tx->send(s_cmd_to_control_channel,
pmt_list2(PMT_NIL, pmt_list1(pmt_list2(s_op_ping_fixed,
pmt_list2(pmt_from_long(0),
pmt_from_long(0))))));
if(verbose && 0)
std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Ping sent" << std::endl;
}
void
test_usrp_inband_timestamps::build_and_send_next_frame()
{
// allocate the uniform vector for the samples
// FIXME perhaps hold on to this between calls
#if 0
long nsamples_this_frame =
std::min(d_nsamples_to_send - d_nsamples_xmitted,
d_samples_per_frame);
#else
long nsamples_this_frame = d_samples_per_frame;
#endif
if (nsamples_this_frame == 0){
d_done_sending = true;
return;
}
size_t nshorts = 2 * nsamples_this_frame; // 16-bit I & Q
pmt_t uvec = pmt_make_s16vector(nshorts, 0);
size_t ignore;
int16_t *samples = pmt_s16vector_writable_elements(uvec, ignore);
// fill in the complex sinusoid
for (int i = 0; i < nsamples_this_frame; i++){
if (1){
gr_complex s;
d_nco.sincos(&s, 1, d_amplitude);
// write 16-bit i & q
samples[2*i] = (int16_t) s.real();
samples[2*i+1] = (int16_t) s.imag();
}
else {
gr_complex s(d_amplitude, d_amplitude);
// write 16-bit i & q
samples[2*i] = (int16_t) s.real();
samples[2*i+1] = (int16_t) s.imag();
}
}
pmt_t timestamp;
if(bskip) {
timestamp = pmt_from_long(0x0); // throw away
bcurr++;
if(bcurr == bstep) {
bskip = false;
bcurr = 0;
}
} else {
timestamp = pmt_from_long(0xffffffff); // NOW
timestamp = pmt_from_long(ptime);
ptime += incr;
bcurr++;
if(bcurr == bstep) {
//bskip = true;
bcurr = 0;
}
}
std::cout << bskip << " -- " << bcurr << std::endl;
d_tx->send(s_cmd_xmit_raw_frame,
pmt_list4(pmt_from_long(d_nframes_xmitted), // invocation-handle
d_tx_chan, // channel
uvec, // the samples
timestamp));
d_nsamples_xmitted += nsamples_this_frame;
d_nframes_xmitted++;
if(verbose && 0)
std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Transmitted frame\n";
//build_and_send_next_frame();
}
void
test_usrp_inband_timestamps::handle_xmit_response(pmt_t handle)
{
if (d_done_sending &&
pmt_to_long(handle) == (d_nframes_xmitted - 1)){
// We're done sending and have received all responses
enter_closing_channel();
}
build_and_send_next_frame();
//build_and_send_ping();
}
void
test_usrp_inband_timestamps::enter_closing_channel()
{
d_state = CLOSING_CHANNEL;
d_tx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_tx_chan));
if(verbose)
std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Closing channel\n";
}
REGISTER_MBLOCK_CLASS(test_usrp_inband_timestamps);
// ----------------------------------------------------------------
int
main (int argc, char **argv)
{
// handle any command line args here
mb_runtime_sptr rt = mb_make_runtime();
pmt_t result = PMT_NIL;
rt->run("top", "test_usrp_inband_timestamps", PMT_F, &result);
}

View File

@ -1,411 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,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 <mblock/mblock.h>
#include <mblock/runtime.h>
#include <mblock/protocol_class.h>
#include <mblock/exception.h>
#include <mblock/msg_queue.h>
#include <mblock/message.h>
#include <mblock/msg_accepter.h>
#include <mblock/class_registry.h>
#include <pmt.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <ui_nco.h>
#include <symbols_usrp_server_cs.h>
#include <symbols_usrp_channel.h>
#include <symbols_usrp_low_level_cs.h>
#include <symbols_usrp_tx.h>
static bool verbose = true;
class test_usrp_tx : public mb_mblock
{
mb_port_sptr d_tx;
mb_port_sptr d_cs;
pmt_t d_tx_chan; // returned tx channel handle
enum state_t {
INIT,
OPENING_USRP,
ALLOCATING_CHANNEL,
TRANSMITTING,
CLOSING_CHANNEL,
CLOSING_USRP,
};
state_t d_state;
long d_nsamples_to_send;
long d_nsamples_xmitted;
long d_nframes_xmitted;
long d_samples_per_frame;
bool d_done_sending;
// for generating sine wave output
ui_nco<float,float> d_nco;
double d_amplitude;
public:
test_usrp_tx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
~test_usrp_tx();
void initial_transition();
void handle_message(mb_message_sptr msg);
protected:
void open_usrp();
void close_usrp();
void allocate_channel();
void send_packets();
void enter_transmitting();
void build_and_send_next_frame();
void handle_xmit_response(pmt_t invocation_handle);
void enter_closing_channel();
};
test_usrp_tx::test_usrp_tx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
: mb_mblock(runtime, instance_name, user_arg),
d_state(INIT), d_nsamples_to_send((long) 80e6),
d_nsamples_xmitted(0),
d_nframes_xmitted(0),
d_samples_per_frame((long)(126 * 4)), // full packet
d_done_sending(false),
d_amplitude(16384)
{
// std::cout << "[TEST_USRP_TX] Initializing...\n";
d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
//bool fake_usrp_p = true;
bool fake_usrp_p = false;
// Test the TX side
pmt_t usrp_dict = pmt_make_dict();
if(fake_usrp_p) {
pmt_dict_set(usrp_dict,
pmt_intern("fake-usrp"),
PMT_T);
}
// Specify the RBF to use
pmt_dict_set(usrp_dict,
pmt_intern("rbf"),
pmt_intern("inband_1rxhb_1tx.rbf"));
// Set TX and RX interpolations
pmt_dict_set(usrp_dict,
pmt_intern("interp-tx"),
pmt_from_long(64));
// If unspecified, chooses center frequency from range
// pmt_dict_set(usrp_dict,
// pmt_intern("rf-freq"),
// pmt_from_long(10e6));
define_component("server", "usrp_server", usrp_dict);
connect("self", "tx0", "server", "tx0");
connect("self", "cs", "server", "cs");
// initialize NCO
double freq = 100e3;
int interp = 32; // 32 -> 4MS/s
double sample_rate = 128e6 / interp;
d_nco.set_freq(2*M_PI * freq/sample_rate);
// FIXME need to somehow set the interp rate in the USRP.
// for now, we'll have the low-level code hardwire it.
}
test_usrp_tx::~test_usrp_tx()
{
}
void
test_usrp_tx::initial_transition()
{
open_usrp();
}
void
test_usrp_tx::handle_message(mb_message_sptr msg)
{
pmt_t event = msg->signal();
pmt_t data = msg->data();
pmt_t handle = PMT_F;
pmt_t status = PMT_F;
std::string error_msg;
//std::cout << msg << std::endl;
switch(d_state){
case OPENING_USRP:
if (pmt_eq(event, s_response_open)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
allocate_channel();
return;
}
else {
error_msg = "failed to open usrp:";
goto bail;
}
}
goto unhandled;
case ALLOCATING_CHANNEL:
if (pmt_eq(event, s_response_allocate_channel)){
status = pmt_nth(1, data);
d_tx_chan = pmt_nth(2, data);
if (pmt_eq(status, PMT_T)){
enter_transmitting();
return;
}
else {
error_msg = "failed to allocate channel:";
goto bail;
}
}
goto unhandled;
case TRANSMITTING:
if (pmt_eq(event, s_response_xmit_raw_frame)){
handle = pmt_nth(0, data);
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
handle_xmit_response(handle);
return;
}
else {
error_msg = "bad response-xmit-raw-frame:";
goto bail;
}
}
goto unhandled;
case CLOSING_CHANNEL:
if (pmt_eq(event, s_response_deallocate_channel)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
close_usrp();
return;
}
else {
error_msg = "failed to deallocate channel:";
goto bail;
}
}
goto unhandled;
case CLOSING_USRP:
if (pmt_eq(event, s_response_close)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
shutdown_all(PMT_T);
return;
}
else {
error_msg = "failed to close USRP:";
goto bail;
}
}
goto unhandled;
default:
goto unhandled;
}
return;
bail:
std::cerr << error_msg << data
<< "status = " << status << std::endl;
shutdown_all(PMT_F);
return;
unhandled:
std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
<< "in state "<< d_state << std::endl;
}
void
test_usrp_tx::open_usrp()
{
pmt_t which_usrp = pmt_from_long(0);
d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, which_usrp));
d_state = OPENING_USRP;
if(verbose)
std::cout << "[TEST_USRP_INBAND_TX] Opening the USRP\n";
}
void
test_usrp_tx::close_usrp()
{
d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
d_state = CLOSING_USRP;
if(verbose)
std::cout << "[TEST_USRP_INBAND_TX] Closing the USRP\n";
}
void
test_usrp_tx::allocate_channel()
{
long capacity = (long) 16e6;
d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
d_state = ALLOCATING_CHANNEL;
if(verbose)
std::cout << "[TEST_USRP_INBAND_TX] Requesting TX channel allocation\n";
}
void
test_usrp_tx::enter_transmitting()
{
d_state = TRANSMITTING;
d_nsamples_xmitted = 0;
if(verbose)
std::cout << "[TEST_USRP_INBAND_TX] Transmitting...\n";
build_and_send_next_frame(); // fire off 4 to start pipeline
build_and_send_next_frame();
build_and_send_next_frame();
build_and_send_next_frame();
}
void
test_usrp_tx::build_and_send_next_frame()
{
// allocate the uniform vector for the samples
// FIXME perhaps hold on to this between calls
#if 1
long nsamples_this_frame =
std::min(d_nsamples_to_send - d_nsamples_xmitted,
d_samples_per_frame);
#else
long nsamples_this_frame = d_samples_per_frame;
#endif
if (nsamples_this_frame == 0){
d_done_sending = true;
return;
}
size_t nshorts = 2 * nsamples_this_frame; // 16-bit I & Q
pmt_t uvec = pmt_make_s16vector(nshorts, 0);
size_t ignore;
int16_t *samples = pmt_s16vector_writable_elements(uvec, ignore);
// fill in the complex sinusoid
for (int i = 0; i < nsamples_this_frame; i++){
if (1){
gr_complex s;
d_nco.sincos(&s, 1, d_amplitude);
// write 16-bit i & q
samples[2*i] = (int16_t) s.real();
samples[2*i+1] = (int16_t) s.imag();
}
else {
gr_complex s(d_amplitude, d_amplitude);
// write 16-bit i & q
samples[2*i] = (int16_t) s.real();
samples[2*i+1] = (int16_t) s.imag();
}
}
pmt_t tx_properties = pmt_make_dict();
pmt_t timestamp = pmt_from_long(0xffffffff); // NOW
d_tx->send(s_cmd_xmit_raw_frame,
pmt_list5(pmt_from_long(d_nframes_xmitted), // invocation-handle
d_tx_chan, // channel
uvec, // the samples
timestamp,
tx_properties));
d_nsamples_xmitted += nsamples_this_frame;
d_nframes_xmitted++;
if(verbose && 0)
std::cout << "[TEST_USRP_INBAND_TX] Transmitted frame\n";
}
void
test_usrp_tx::handle_xmit_response(pmt_t handle)
{
if (d_done_sending &&
pmt_to_long(handle) == (d_nframes_xmitted - 1)){
// We're done sending and have received all responses
enter_closing_channel();
}
build_and_send_next_frame();
}
void
test_usrp_tx::enter_closing_channel()
{
d_state = CLOSING_CHANNEL;
d_tx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_tx_chan));
if(verbose)
std::cout << "[TEST_USRP_INBAND_tX] Deallocating TX channel\n";
}
REGISTER_MBLOCK_CLASS(test_usrp_tx);
// ----------------------------------------------------------------
int
main (int argc, char **argv)
{
// handle any command line args here
mb_runtime_sptr rt = mb_make_runtime();
pmt_t result = PMT_NIL;
rt->run("top", "test_usrp_tx", PMT_F, &result);
}

View File

@ -1,674 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,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 <mblock/mblock.h>
#include <mblock/runtime.h>
#include <mblock/protocol_class.h>
#include <mblock/exception.h>
#include <mblock/msg_queue.h>
#include <mblock/message.h>
#include <mblock/msg_accepter.h>
#include <mblock/class_registry.h>
#include <pmt.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <iostream>
#include <ui_nco.h>
// Include the symbols needed for communication with USRP server
#include <symbols_usrp_server_cs.h>
#include <symbols_usrp_channel.h>
#include <symbols_usrp_low_level_cs.h>
#include <symbols_usrp_tx.h>
#include <symbols_usrp_rx.h>
static bool verbose = true;
class test_usrp_inband_underrun : public mb_mblock
{
mb_port_sptr d_tx; // Ports connected to the USRP server
mb_port_sptr d_rx;
mb_port_sptr d_cs;
pmt_t d_tx_chan; // Returned channel from TX allocation
pmt_t d_rx_chan; // Returned channel from RX allocation
pmt_t d_which_usrp; // The USRP to use for the test
long d_warm_msgs; // The number of messages to 'warm' the USRP
long d_warm_recvd; // The number of msgs received in the 'warm' state
// Keep track of current state
enum state_t {
INIT,
OPENING_USRP,
ALLOCATING_CHANNELS,
WRITE_REGISTER,
READ_REGISTER,
TRANSMITTING,
CLOSING_CHANNELS,
CLOSING_USRP,
};
state_t d_state;
long d_nsamples_to_send;
long d_nsamples_xmitted;
long d_nframes_xmitted;
long d_samples_per_frame;
bool d_done_sending;
// for generating sine wave output
ui_nco<float,float> d_nco;
double d_amplitude;
long d_n_underruns;
public:
test_usrp_inband_underrun(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
~test_usrp_inband_underrun();
void initial_transition();
void handle_message(mb_message_sptr msg);
protected:
void opening_usrp();
void allocating_channels();
void write_register();
void read_register();
void closing_channels();
void closing_usrp();
void enter_receiving();
void enter_transmitting();
void build_and_send_ping();
void build_and_send_next_frame();
void handle_xmit_response(pmt_t handle);
void handle_recv_response(pmt_t dict);
};
int
main (int argc, char **argv)
{
// handle any command line args here
mb_runtime_sptr rt = mb_make_runtime();
pmt_t result = PMT_NIL;
rt->run("top", "test_usrp_inband_underrun", PMT_F, &result);
}
test_usrp_inband_underrun::test_usrp_inband_underrun(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
: mb_mblock(runtime, instance_name, user_arg),
d_tx_chan(PMT_NIL),
d_rx_chan(PMT_NIL),
d_which_usrp(pmt_from_long(0)),
d_state(INIT),
d_nsamples_to_send((long) 27e6),
d_nsamples_xmitted(0),
d_nframes_xmitted(0),
d_samples_per_frame(d_nsamples_to_send), // full packet
d_done_sending(false),
d_amplitude(16384),
d_n_underruns(0)
{
// A dictionary is used to pass parameters to the USRP
pmt_t usrp_dict = pmt_make_dict();
// Specify the RBF to use
pmt_dict_set(usrp_dict,
pmt_intern("rbf"),
pmt_intern("inband_1rxhb_1tx.rbf"));
// Set TX and RX interpolations
pmt_dict_set(usrp_dict,
pmt_intern("interp-tx"),
pmt_from_long(64));
pmt_dict_set(usrp_dict,
pmt_intern("decim-rx"),
pmt_from_long(128));
d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
// Create an instance of USRP server and connect ports
define_component("server", "usrp_server", usrp_dict);
connect("self", "tx0", "server", "tx0");
connect("self", "rx0", "server", "rx0");
connect("self", "cs", "server", "cs");
// initialize NCO
double freq = 100e3;
int interp = 32; // 32 -> 4MS/s
double sample_rate = 128e6 / interp;
d_nco.set_freq(2*M_PI * freq/sample_rate);
}
test_usrp_inband_underrun::~test_usrp_inband_underrun()
{
}
void
test_usrp_inband_underrun::initial_transition()
{
opening_usrp();
}
// Handle message reads all incoming messages from USRP server which will be
// initialization and ping responses. We perform actions based on the current
// state and the event (ie, ping response)
void
test_usrp_inband_underrun::handle_message(mb_message_sptr msg)
{
pmt_t event = msg->signal();
pmt_t data = msg->data();
pmt_t port_id = msg->port_id();
pmt_t handle = PMT_F;
pmt_t status = PMT_F;
pmt_t dict = PMT_NIL;
std::string error_msg;
// Check the recv sample responses for underruns and count
if(pmt_eq(event, s_response_recv_raw_samples)) {
handle = pmt_nth(0, data);
status = pmt_nth(1, data);
dict = pmt_nth(4, data);
if(pmt_eq(status, PMT_T)) {
handle_recv_response(dict);
return;
}
else {
error_msg = "error while receiving samples:";
goto bail;
}
}
// Dispatch based on state
switch(d_state) {
//----------------------------- OPENING_USRP ----------------------------//
// We only expect a response from opening the USRP which should be succesful
// or failed.
case OPENING_USRP:
if(pmt_eq(event, s_response_open)) {
status = pmt_nth(1, data); // failed/succes
if(pmt_eq(status, PMT_T)) {
allocating_channels();
return;
}
else {
error_msg = "failed to open usrp:";
goto bail;
}
}
goto unhandled; // all other messages not handled in this state
//----------------------- ALLOCATING CHANNELS --------------------//
// When allocating channels, we need to wait for 2 responses from
// USRP server: one for TX and one for RX. Both are initialized to
// NIL so we know to continue to the next state once both are set.
case ALLOCATING_CHANNELS:
// A TX allocation response
if(pmt_eq(event, s_response_allocate_channel)
&& pmt_eq(d_tx->port_symbol(), port_id))
{
status = pmt_nth(1, data);
// If successful response, extract the channel
if(pmt_eq(status, PMT_T)) {
d_tx_chan = pmt_nth(2, data);
if(verbose)
std::cout << "[TEST_USRP_INBAND_UNDERRUN] Received TX allocation"
<< " on channel " << d_tx_chan << std::endl;
// If the RX has also been allocated already, we can continue
if(!pmt_eqv(d_rx_chan, PMT_NIL)) {
enter_receiving();
enter_transmitting();
}
return;
}
else { // TX allocation failed
error_msg = "failed to allocate TX channel:";
goto bail;
}
}
// A RX allocation response
if(pmt_eq(event, s_response_allocate_channel)
&& pmt_eq(d_rx->port_symbol(), port_id))
{
status = pmt_nth(1, data);
// If successful response, extract the channel
if(pmt_eq(status, PMT_T)) {
d_rx_chan = pmt_nth(2, data);
if(verbose)
std::cout << "[TEST_USRP_INBAND_UNDERRUN] Received RX allocation"
<< " on channel " << d_rx_chan << std::endl;
// If the TX has also been allocated already, we can continue
if(!pmt_eqv(d_tx_chan, PMT_NIL)) {
enter_receiving();
enter_transmitting();
}
return;
}
else { // RX allocation failed
error_msg = "failed to allocate RX channel:";
goto bail;
}
}
goto unhandled;
case WRITE_REGISTER:
goto unhandled;
case READ_REGISTER:
goto unhandled;
//-------------------------- TRANSMITTING ----------------------------//
// In the transmit state we count the number of underruns received and
// ballpark the number with an expected count (something >1 for starters)
case TRANSMITTING:
// Check that the transmits are OK
if (pmt_eq(event, s_response_xmit_raw_frame)){
handle = pmt_nth(0, data);
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
handle_xmit_response(handle);
return;
}
else {
error_msg = "bad response-xmit-raw-frame:";
goto bail;
}
}
goto unhandled;
//------------------------- CLOSING CHANNELS ----------------------------//
// Check deallocation responses, once the TX and RX channels are both
// deallocated then we close the USRP.
case CLOSING_CHANNELS:
if (pmt_eq(event, s_response_deallocate_channel)
&& pmt_eq(d_tx->port_symbol(), port_id))
{
status = pmt_nth(1, data);
// If successful, set the port to NIL
if(pmt_eq(status, PMT_T)) {
d_tx_chan = PMT_NIL;
if(verbose)
std::cout << "[TEST_USRP_INBAND_UNDERRUN] Received TX deallocation\n";
// If the RX is also deallocated, we can close the USRP
if(pmt_eq(d_rx_chan, PMT_NIL))
closing_usrp();
return;
} else {
error_msg = "failed to deallocate TX channel:";
goto bail;
}
}
if (pmt_eq(event, s_response_deallocate_channel)
&& pmt_eq(d_rx->port_symbol(), port_id))
{
status = pmt_nth(1, data);
// If successful, set the port to NIL
if(pmt_eq(status, PMT_T)) {
d_rx_chan = PMT_NIL;
if(verbose)
std::cout << "[TEST_USRP_INBAND_UNDERRUN] Received RX deallocation\n";
// If the TX is also deallocated, we can close the USRP
if(pmt_eq(d_tx_chan, PMT_NIL))
closing_usrp();
return;
} else {
error_msg = "failed to deallocate RX channel:";
goto bail;
}
}
goto unhandled;
//--------------------------- CLOSING USRP ------------------------------//
// Once we have received a successful USRP close response, we shutdown all
// mblocks and exit.
case CLOSING_USRP:
if (pmt_eq(event, s_response_close)) {
status = pmt_nth(1, data);
if(pmt_eq(status, PMT_T)) {
if(verbose)
std::cout << "[TEST_USRP_INBAND_UNDERRUN] Successfully closed USRP\n";
std::cout << "\nUnderruns: " << d_n_underruns << std::endl;
fflush(stdout);
shutdown_all(PMT_T);
return;
} else {
error_msg = "failed to close USRP:";
goto bail;
}
}
goto unhandled;
case INIT:
goto unhandled;
}
// An error occured, print it, and shutdown all m-blocks
bail:
std::cerr << error_msg << data
<< "status = " << status << std::endl;
shutdown_all(PMT_F);
return;
// Received an unhandled message for a specific state
unhandled:
if(verbose && !pmt_eq(event, pmt_intern("%shutdown")))
std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
<< "in state "<< d_state << std::endl;
}
// Sends a command to USRP server to open up a connection to the
// specified USRP, which is defaulted to USRP 0 on the system
void
test_usrp_inband_underrun::opening_usrp()
{
if(verbose)
std::cout << "[TEST_USRP_INBAND_UNDERRUN] Opening USRP "
<< d_which_usrp << std::endl;
d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, d_which_usrp));
d_state = OPENING_USRP;
}
// RX and TX channels must be allocated so that the USRP server can
// properly share bandwidth across multiple USRPs. No commands will be
// successful to the USRP through the USRP server on the TX or RX channels until
// a bandwidth allocation has been received.
void
test_usrp_inband_underrun::allocating_channels()
{
d_state = ALLOCATING_CHANNELS;
long capacity = (long) 16e6;
d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
}
// After allocating the channels, a write register command will be sent to the
// USRP.
void
test_usrp_inband_underrun::write_register()
{
d_state = WRITE_REGISTER;
long reg = 0;
d_tx->send(s_cmd_to_control_channel, // C/S packet
pmt_list2(PMT_NIL, // invoc handle
pmt_list1(
pmt_list2(s_op_write_reg,
pmt_list2(
pmt_from_long(reg),
pmt_from_long(0xbeef))))));
if(verbose)
std::cout << "[TEST_USRP_INBAND_REGISTERS] Writing 0xbeef to "
<< reg << std::endl;
read_register(); // immediately transition to read the register
}
// Temporary: for testing pings
void
test_usrp_inband_underrun::build_and_send_ping()
{
d_tx->send(s_cmd_to_control_channel,
pmt_list2(PMT_NIL, pmt_list1(pmt_list2(s_op_ping_fixed,
pmt_list2(pmt_from_long(0),
pmt_from_long(0))))));
std::cout << "[TEST_USRP_INBAND_UNDERRUN] Ping sent" << std::endl;
}
// After writing to the register, we want to read the value back and ensure that
// it is the same value that we wrote.
void
test_usrp_inband_underrun::read_register()
{
d_state = READ_REGISTER;
long reg = 9;
d_tx->send(s_cmd_to_control_channel, // C/S packet
pmt_list2(PMT_NIL, // invoc handle
pmt_list1(
pmt_list2(s_op_read_reg,
pmt_list2(
pmt_from_long(0), // rid
pmt_from_long(reg))))));
if(verbose)
std::cout << "[TEST_USRP_INBAND_UNDERRUN] Reading from register "
<< reg << std::endl;
}
// Used to enter the receiving state
void
test_usrp_inband_underrun::enter_receiving()
{
d_rx->send(s_cmd_start_recv_raw_samples,
pmt_list2(PMT_F,
d_rx_chan));
if(verbose)
std::cout << "[TEST_USRP_INBAND_UNDERRUN] Started RX sample stream\n";
}
void
test_usrp_inband_underrun::enter_transmitting()
{
d_state = TRANSMITTING;
d_nsamples_xmitted = 0;
if(verbose)
std::cout << "[TEST_USRP_INBAND_UNDERRUN] Entering transmit state...\n";
build_and_send_next_frame(); // fire off 4 to start pipeline
build_and_send_next_frame();
build_and_send_next_frame();
build_and_send_next_frame();
}
void
test_usrp_inband_underrun::build_and_send_next_frame()
{
long nsamples_this_frame =
std::min(d_nsamples_to_send - d_nsamples_xmitted,
d_samples_per_frame);
if (nsamples_this_frame == 0){
d_done_sending = true;
return;
}
size_t nshorts = 2 * nsamples_this_frame; // 16-bit I & Q
pmt_t uvec = pmt_make_s16vector(nshorts, 0);
size_t ignore;
int16_t *samples = pmt_s16vector_writable_elements(uvec, ignore);
// fill in the complex sinusoid
for (int i = 0; i < nsamples_this_frame; i++){
if (1){
gr_complex s;
d_nco.sincos(&s, 1, d_amplitude);
// write 16-bit i & q
samples[2*i] = (int16_t) s.real();
samples[2*i+1] = (int16_t) s.imag();
}
else {
gr_complex s(d_amplitude, d_amplitude);
// write 16-bit i & q
samples[2*i] = (int16_t) s.real();
samples[2*i+1] = (int16_t) s.imag();
}
}
if(verbose)
std::cout << "[TEST_USRP_INBAND_TX] Transmitting frame...\n";
pmt_t timestamp = pmt_from_long(0xffffffff); // NOW
d_tx->send(s_cmd_xmit_raw_frame,
pmt_list4(pmt_from_long(d_nframes_xmitted), // invocation-handle
d_tx_chan, // channel
uvec, // the samples
timestamp));
d_nsamples_xmitted += nsamples_this_frame;
d_nframes_xmitted++;
if(verbose)
std::cout << "[TEST_USRP_INBAND_TX] Transmitted frame\n";
}
void
test_usrp_inband_underrun::handle_xmit_response(pmt_t handle)
{
if (d_done_sending &&
pmt_to_long(handle) == (d_nframes_xmitted - 1)){
// We're done sending and have received all responses
closing_channels();
return;
}
build_and_send_next_frame();
}
void
test_usrp_inband_underrun::handle_recv_response(pmt_t dict)
{
if(!pmt_is_dict(dict)) {
std::cout << "[TEST_USRP_INBAND_UNDERRUN] Recv samples dictionary is improper\n";
return;
}
// Read the TX interpolations
if(pmt_t underrun = pmt_dict_ref(dict,
pmt_intern("underrun"),
PMT_NIL)) {
if(pmt_eqv(underrun, PMT_T)) {
d_n_underruns++;
if(verbose && 0)
std::cout << "[TEST_USRP_INBAND_UNDERRUN] Underrun\n";
}
else {
if(verbose && 0)
std::cout << "[TEST_USRP_INBAND_UNDERRUN] No underrun\n" << underrun <<std::endl;
}
} else {
if(verbose && 0)
std::cout << "[TEST_USRP_INBAND_UNDERRUN] No underrun\n";
}
}
void
test_usrp_inband_underrun::closing_channels()
{
d_state = CLOSING_CHANNELS;
d_tx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_tx_chan));
d_rx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_rx_chan));
}
void
test_usrp_inband_underrun::closing_usrp()
{
d_state = CLOSING_USRP;
d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
}
REGISTER_MBLOCK_CLASS(test_usrp_inband_underrun);

View File

@ -1,202 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2002 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_UI_NCO_H
#define INCLUDED_UI_NCO_H
#include <vector>
#include <ui_sincos.h>
#include <cmath>
#include <complex>
typedef std::complex<float> gr_complex;
/*!
* \brief base class template for Numerically Controlled Oscillator (NCO)
*/
//FIXME Eventually generalize this to fixed point
template<class o_type, class i_type>
class ui_nco {
public:
ui_nco () : phase (0), phase_inc(0) {}
virtual ~ui_nco () {}
// radians
void set_phase (double angle) {
phase = angle;
}
void adjust_phase (double delta_phase) {
phase += delta_phase;
}
// angle_rate is in radians / step
void set_freq (double angle_rate){
phase_inc = angle_rate;
}
// angle_rate is a delta in radians / step
void adjust_freq (double delta_angle_rate)
{
phase_inc += delta_angle_rate;
}
// increment current phase angle
void step ()
{
phase += phase_inc;
if (fabs (phase) > M_PI){
while (phase > M_PI)
phase -= 2*M_PI;
while (phase < -M_PI)
phase += 2*M_PI;
}
}
void step (int n)
{
phase += phase_inc * n;
if (fabs (phase) > M_PI){
while (phase > M_PI)
phase -= 2*M_PI;
while (phase < -M_PI)
phase += 2*M_PI;
}
}
// units are radians / step
double get_phase () const { return phase; }
double get_freq () const { return phase_inc; }
// compute sin and cos for current phase angle
void sincos (float *sinx, float *cosx) const;
// compute cos or sin for current phase angle
float cos () const { return std::cos (phase); }
float sin () const { return std::sin (phase); }
// compute a block at a time
void sin (float *output, int noutput_items, double ampl = 1.0);
void cos (float *output, int noutput_items, double ampl = 1.0);
void sincos (gr_complex *output, int noutput_items, double ampl = 1.0);
void sin (short *output, int noutput_items, double ampl = 1.0);
void cos (short *output, int noutput_items, double ampl = 1.0);
void sin (int *output, int noutput_items, double ampl = 1.0);
void cos (int *output, int noutput_items, double ampl = 1.0);
protected:
double phase;
double phase_inc;
};
template<class o_type, class i_type>
void
ui_nco<o_type,i_type>::sincos (float *sinx, float *cosx) const
{
ui_sincosf (phase, sinx, cosx);
}
template<class o_type, class i_type>
void
ui_nco<o_type,i_type>::sin (float *output, int noutput_items, double ampl)
{
for (int i = 0; i < noutput_items; i++){
output[i] = (float)(sin () * ampl);
step ();
}
}
template<class o_type, class i_type>
void
ui_nco<o_type,i_type>::cos (float *output, int noutput_items, double ampl)
{
for (int i = 0; i < noutput_items; i++){
output[i] = (float)(cos () * ampl);
step ();
}
}
template<class o_type, class i_type>
void
ui_nco<o_type,i_type>::sin (short *output, int noutput_items, double ampl)
{
for (int i = 0; i < noutput_items; i++){
output[i] = (short)(sin() * ampl);
step ();
}
}
template<class o_type, class i_type>
void
ui_nco<o_type,i_type>::cos (short *output, int noutput_items, double ampl)
{
for (int i = 0; i < noutput_items; i++){
output[i] = (short)(cos () * ampl);
step ();
}
}
template<class o_type, class i_type>
void
ui_nco<o_type,i_type>::sin (int *output, int noutput_items, double ampl)
{
for (int i = 0; i < noutput_items; i++){
output[i] = (int)(sin () * ampl);
step ();
}
}
template<class o_type, class i_type>
void
ui_nco<o_type,i_type>::cos (int *output, int noutput_items, double ampl)
{
for (int i = 0; i < noutput_items; i++){
output[i] = (int)(cos () * ampl);
step ();
}
}
template<class o_type, class i_type>
void
ui_nco<o_type,i_type>::sincos (gr_complex *output, int noutput_items, double ampl)
{
for (int i = 0; i < noutput_items; i++){
float cosx, sinx;
sincos (&sinx, &cosx);
output[i] = gr_complex(cosx * ampl, sinx * ampl);
step ();
}
}
#endif /* INCLUDED_UI_NCO_H */

View File

@ -1,81 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2004 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
#define _GNU_SOURCE // ask for GNU extensions if available
#include "ui_sincos.h"
#include <math.h>
// ----------------------------------------------------------------
#if defined (HAVE_SINCOS)
void
ui_sincos (double x, double *sinx, double *cosx)
{
sincos (x, sinx, cosx);
}
#else
void
ui_sincos (double x, double *sinx, double *cosx)
{
*sinx = sin (x);
*cosx = cos (x);
}
#endif
// ----------------------------------------------------------------
#if defined (HAVE_SINCOSF)
void
ui_sincosf (float x, float *sinx, float *cosx)
{
sincosf (x, sinx, cosx);
}
#elif defined (HAVE_SINF) && defined (HAVE_COSF)
void
ui_sincosf (float x, float *sinx, float *cosx)
{
*sinx = sinf (x);
*cosx = cosf (x);
}
#else
void
ui_sincosf (float x, float *sinx, float *cosx)
{
*sinx = sin (x);
*cosx = cos (x);
}
#endif

View File

@ -1,39 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2002,2004 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_UI_SINCOS_H
#define INCLUDED_UI_SINCOS_H
#ifdef __cplusplus
extern "C" {
#endif
// compute sine and cosine at the same time
void ui_sincos (double x, double *sin, double *cos);
void ui_sincosf (float x, float *sin, float *cos);
#ifdef __cplusplus
};
#endif
#endif /* INCLUDED_UI_SINCOS_H */

View File

@ -1,20 +0,0 @@
/Makefile
/Makefile.in
/.la
/.lo
/.deps
/.libs
/*.la
/*.lo
/*.swp
/*.dat
/test_fusb
/std_paths.h
/usrp_dbid.py
/usrp_dbid.h
/usrp_dbid.cc
/usrp_server_mbh.cc
/test_inband
/test_usrp_inband
/test_usrp_tx
/*_mbh.cc

View File

@ -1,114 +0,0 @@
#
# Copyright 2007,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.
#
include $(top_srcdir)/Makefile.common
AM_CPPFLAGS = \
$(DEFINES) $(OMNITHREAD_INCLUDES) $(PMT_INCLUDES) $(MBLOCK_INCLUDES) \
$(USRP_INCLUDES) $(BOOST_CPPFLAGS) $(CPPUNIT_INCLUDES) \
-I$(srcdir)/../../apps-inband $(WITH_INCLUDES)
TESTS = test_inband
EXTRA_DIST = \
usrp_server.mbh \
usrp_interface.mbh
lib_LTLIBRARIES = \
libusrp-inband.la \
libusrp-inband-qa.la
# ------------------------------------------------------------------------
# Build the inband library
BUILT_SOURCES = \
usrp_server_mbh.cc \
usrp_interface_mbh.cc
usrp_server_mbh.cc : usrp_server.mbh
$(COMPILE_MBH) $(srcdir)/usrp_server.mbh usrp_server_mbh.cc
usrp_interface_mbh.cc : usrp_interface.mbh
$(COMPILE_MBH) $(srcdir)/usrp_interface.mbh usrp_interface_mbh.cc
libusrp_inband_la_SOURCES = \
$(BUILT_SOURCES) \
$(srcdir)/../../apps-inband/ui_sincos.c \
usrp_inband_usb_packet.cc \
usrp_rx.cc \
usrp_rx_stub.cc \
usrp_server.cc \
usrp_tx.cc \
usrp_tx_stub.cc \
usrp_usb_interface.cc
libusrp_inband_la_LDFLAGS = $(NO_UNDEFINED) -version-info 0:0:0
libusrp_inband_la_LIBADD = \
$(MBLOCK_LA) \
$(USRP_LA) \
-lstdc++
include_HEADERS = \
usrp_inband_usb_packet.h \
usrp_rx.h \
usrp_rx_stub.h \
usrp_server.h \
usrp_tx.h \
usrp_tx_stub.h \
usrp_usb_interface.h
noinst_HEADERS = \
qa_inband.h \
qa_inband_packet_prims.h \
qa_inband_usrp_server.h \
symbols_usrp_channel.h \
symbols_usrp_interface_cs.h \
symbols_usrp_low_level_cs.h \
symbols_usrp_rx.h \
symbols_usrp_rx_cs.h \
symbols_usrp_server_cs.h \
symbols_usrp_tx.h \
symbols_usrp_tx_cs.h
# ------------------------------------------------------------------------
# Build the qa code in its own library
libusrp_inband_qa_la_SOURCES = \
qa_inband.cc \
qa_inband_packet_prims.cc \
qa_inband_usrp_server.cc
# magic flags
libusrp_inband_qa_la_LDFLAGS = $(NO_UNDEFINED) -avoid-version
libusrp_inband_qa_la_LIBADD = \
libusrp-inband.la \
$(PMT_LA) \
$(CPPUNIT_LIBS) \
-lstdc++
# ------------------------------------------------------------------------
noinst_PROGRAMS = \
test_inband
test_inband_SOURCES = test_inband.cc
test_inband_LDADD = libusrp-inband-qa.la

View File

@ -1,65 +0,0 @@
#!/usr/bin/env python
#
# Copyright 2007 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.
#
import sys
import struct
from optparse import OptionParser
from usb_packet import *
def dump_packet(raw_pkt, outfile, dump_payload):
pkt = usb_packet(raw_pkt)
outfile.write(pkt.decoded_flags())
outfile.write(' chan= %2d len= %3d timestamp= 0x%08x rssi= % 2d tag= %2d\n' % (
pkt.chan(), pkt.payload_len(), pkt.timestamp(), pkt.rssi(), pkt.tag()))
if dump_payload:
assert pkt.payload_len() % 4 == 0
shorts = struct.unpack('<%dh' % (pkt.payload_len() // 2), pkt.payload())
for i in range(0, len(shorts), 2):
outfile.write(' %6d, %6d\n' % (shorts[i], shorts[i+1]))
def dump_packets(infile, outfile, dump_payload):
raw_pkt = infile.read(512)
while raw_pkt:
if len(raw_pkt) != 512:
sys.stderr.write("File length is not a multiple of 512 bytes")
raise SystemExit, 1
dump_packet(raw_pkt, outfile, dump_payload)
raw_pkt = infile.read(512)
def main():
parser = OptionParser()
parser.add_option('-p', '--dump-payload', action='store_true', default=False,
help='dump payload in decimal and hex')
(options, files) = parser.parse_args()
if len(files) == 0:
dump_packets(sys.stdin, sys.stdout, options.dump_payload)
else:
for f in files:
dump_packets(open(f, "r"), sys.stdout, options.dump_payload)
if __name__ == '__main__':
main()

View File

@ -1,88 +0,0 @@
#!/usr/bin/env python
import random
import struct
from pprint import pprint
from usb_packet import *
MAX_PAYLOAD = 504
TIME_NOW = 0xffffffff
class sequence_generator(object):
def __init__(self):
self.i = 0
def __call__(self):
t = self.i
self.i += 1
return t
def gen_shuffled_lengths():
valid_lengths = range(0, MAX_PAYLOAD+1, 4) # [0, 4, 8, ... 504]
random.shuffle(valid_lengths)
return valid_lengths
class packet_sequence_generator(object):
def __init__(self, channel, lengths):
self.next = sequence_generator()
self.channel = channel
self.lengths = lengths
def __call__(self, output_file):
gen_packet(output_file, self.channel, self.next, self.lengths[0])
del self.lengths[0]
def gen_packet(output_file, channel, content_generator, payload_len):
assert (payload_len % 4) == 0
payload = []
n_iq = payload_len // 4
for n in range(n_iq):
payload.append(content_generator()) # I
payload.append(content_generator()) # Q
for n in range(MAX_PAYLOAD // 4 - n_iq):
payload.append(0x0000)
payload.append(0xffff)
assert (len(payload) == MAX_PAYLOAD // 2)
#print "\npayload_len =", payload_len
#pprint(payload)
output_file.write(make_header(FL_START_OF_BURST|FL_END_OF_BURST,
channel, payload_len, TIME_NOW))
output_file.write(struct.pack('<252h', *payload))
def gen_all_valid_packet_lengths_1_channel(output_file):
lengths = gen_shuffled_lengths()
npkts = len(lengths) # number of packets we'll generator on each stream
pkt_gen_0 = packet_sequence_generator(0, lengths)
for i in range(npkts):
pkt_gen_0(output_file)
assert pkt_gen_0.next() == 16002 # 2*sum(1, 2, ..., 126) == 126 * 127
def gen_all_valid_packet_lengths_2_channels(output_file):
lengths = gen_shuffled_lengths()
npkts = len(lengths) # number of packets we'll generator on each stream
pkt_gen_0 = packet_sequence_generator(0, lengths)
pkt_gen_1 = packet_sequence_generator(0x1f, gen_shuffled_lengths())
pkt_gen = (pkt_gen_0, pkt_gen_1)
which_gen = (npkts * [0]) + (npkts * [1])
random.shuffle(which_gen)
for i in which_gen:
pkt_gen[i](output_file)
assert pkt_gen_0.next() == 16002 # 2*sum(1, 2, ..., 126) == 126 * 127
assert pkt_gen_1.next() == 16002 # 2*sum(1, 2, ..., 126) == 126 * 127
if __name__ == '__main__':
random.seed(0)
gen_all_valid_packet_lengths_1_channel(open("all_valid_packet_lengths_1_channel.dat", "w"))
gen_all_valid_packet_lengths_2_channels(open("all_valid_packet_lengths_2_channels.dat", "w"))

View File

@ -1,35 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 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.
*/
#include <qa_inband.h>
#include <qa_inband_packet_prims.h>
#include <qa_inband_usrp_server.h>
CppUnit::TestSuite *
qa_inband::suite()
{
CppUnit::TestSuite *s = new CppUnit::TestSuite("inband");
s->addTest (qa_inband_packet_prims::suite());
s->addTest (qa_inband_usrp_server::suite());
return s;
}

View File

@ -1,35 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 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.
*/
#ifndef INCLUDED_QA_INBAND_H
#define INCLUDED_QA_INBAND_H
#include <cppunit/TestSuite.h>
//! collect all the tests for the user server
class qa_inband {
public:
//! return suite of tests for all of usrp server
static CppUnit::TestSuite *suite();
};
#endif /* INCLUDED_QA_INBAND_H */

View File

@ -1,162 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 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 <qa_inband_packet_prims.h>
#include <cppunit/TestAssert.h>
#include <stdio.h>
#include <string.h>
#include <usrp_inband_usb_packet.h> // will change on gigabit crossover
typedef usrp_inband_usb_packet transport_pkt;
void
qa_inband_packet_prims::test_flags()
{
transport_pkt pkt;
// Test each one of the flags while ensuring no other fields become set in the process
pkt.set_header(pkt.FL_START_OF_BURST,0,0,0);
CPPUNIT_ASSERT_EQUAL(1, pkt.start_of_burst());
CPPUNIT_ASSERT_EQUAL(0, pkt.end_of_burst());
CPPUNIT_ASSERT_EQUAL(0, pkt.overrun());
CPPUNIT_ASSERT_EQUAL(0, pkt.underrun());
CPPUNIT_ASSERT_EQUAL(0, pkt.dropped());
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
pkt.set_header(pkt.FL_END_OF_BURST,0,0,0);
CPPUNIT_ASSERT_EQUAL(0, pkt.start_of_burst());
CPPUNIT_ASSERT_EQUAL(1, pkt.end_of_burst());
CPPUNIT_ASSERT_EQUAL(0, pkt.overrun());
CPPUNIT_ASSERT_EQUAL(0, pkt.underrun());
CPPUNIT_ASSERT_EQUAL(0, pkt.dropped());
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
pkt.set_header(pkt.FL_OVERRUN,0,0,0);
CPPUNIT_ASSERT_EQUAL(0, pkt.start_of_burst());
CPPUNIT_ASSERT_EQUAL(0, pkt.end_of_burst());
CPPUNIT_ASSERT_EQUAL(1, pkt.overrun());
CPPUNIT_ASSERT_EQUAL(0, pkt.underrun());
CPPUNIT_ASSERT_EQUAL(0, pkt.dropped());
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
pkt.set_header(pkt.FL_UNDERRUN,0,0,0);
CPPUNIT_ASSERT_EQUAL(0, pkt.start_of_burst());
CPPUNIT_ASSERT_EQUAL(0, pkt.end_of_burst());
CPPUNIT_ASSERT_EQUAL(0, pkt.overrun());
CPPUNIT_ASSERT_EQUAL(1, pkt.underrun());
CPPUNIT_ASSERT_EQUAL(0, pkt.dropped());
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
pkt.set_header(pkt.FL_DROPPED,0,0,0);
CPPUNIT_ASSERT_EQUAL(0, pkt.start_of_burst());
CPPUNIT_ASSERT_EQUAL(0, pkt.end_of_burst());
CPPUNIT_ASSERT_EQUAL(0, pkt.overrun());
CPPUNIT_ASSERT_EQUAL(0, pkt.underrun());
CPPUNIT_ASSERT_EQUAL(1, pkt.dropped());
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
// test of all fields set
pkt.set_header(
pkt.FL_START_OF_BURST |
pkt.FL_END_OF_BURST |
pkt.FL_UNDERRUN |
pkt.FL_OVERRUN |
pkt.FL_DROPPED
,0,0,0);
CPPUNIT_ASSERT_EQUAL(1, pkt.start_of_burst());
CPPUNIT_ASSERT_EQUAL(1, pkt.end_of_burst());
CPPUNIT_ASSERT_EQUAL(1, pkt.overrun());
CPPUNIT_ASSERT_EQUAL(1, pkt.underrun());
CPPUNIT_ASSERT_EQUAL(1, pkt.dropped());
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
}
//////////////////////////////////////////////////////////////////////
void
qa_inband_packet_prims::test_fields()
{
transport_pkt pkt;
void * payload;
// test word0 field exclusiveness
//
// I want to test max values of each field to ensure field boundaries
// but these max values could change based on technology? The
// max payload is returned by a private method so the code is not
// technology dependent
pkt.set_header(0,16,0,0);
CPPUNIT_ASSERT_EQUAL(16, pkt.chan());
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
pkt.set_header(0,0,8,0);
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
CPPUNIT_ASSERT_EQUAL(8, pkt.tag());
CPPUNIT_ASSERT_EQUAL(0,pkt.payload_len());
pkt.set_header(0,0,0,pkt.max_payload());
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
CPPUNIT_ASSERT_EQUAL(pkt.max_payload(), pkt.payload_len());
// test timestamp, shouldn't have to test other fields since
// setting the timestamp only has the ability to affect one word
pkt.set_timestamp(54);
CPPUNIT_ASSERT_EQUAL(uint32_t(54), pkt.timestamp());
// test the payload, ensure no other fields overwritten
//
// is there a better test for this?
pkt.set_header(0,0,0,0);
payload = malloc(pkt.payload_len());
memset(payload, 'f', pkt.payload_len());
memcpy(pkt.payload(), payload, pkt.payload_len());
CPPUNIT_ASSERT_EQUAL(0, memcmp(pkt.payload(), payload, pkt.payload_len()));
CPPUNIT_ASSERT_EQUAL(0, pkt.start_of_burst());
CPPUNIT_ASSERT_EQUAL(0, pkt.end_of_burst());
CPPUNIT_ASSERT_EQUAL(0, pkt.overrun());
CPPUNIT_ASSERT_EQUAL(0, pkt.underrun());
CPPUNIT_ASSERT_EQUAL(0, pkt.dropped());
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
free(payload);
}
//////////////////////////////////////////////////////////////////////

View File

@ -1,41 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 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.
*/
#ifndef QA_INBAND_PACKET_PRIMS_H
#define QA_INBAND_PACKET_PRIMS_H
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestCase.h>
class qa_inband_packet_prims : public CppUnit::TestCase {
CPPUNIT_TEST_SUITE(qa_inband_packet_prims);
CPPUNIT_TEST(test_flags);
CPPUNIT_TEST(test_fields);
CPPUNIT_TEST_SUITE_END();
private:
void test_flags();
void test_fields();
};
#endif /* INCLUDED_QA_INBAND_PACKET_PRIMS_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,50 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 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.
*/
#ifndef QA_INBAND_USRP_SERVER_H
#define QA_INBAND_USRP_SERVER_H
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestCase.h>
class qa_inband_usrp_server : public CppUnit::TestCase {
CPPUNIT_TEST_SUITE(qa_inband_usrp_server);
CPPUNIT_TEST(test_open_close);
CPPUNIT_TEST(test_chan_allocation);
CPPUNIT_TEST(test_chan_deallocation);
CPPUNIT_TEST(test_tx);
CPPUNIT_TEST(test_rx);
CPPUNIT_TEST(test_cs);
CPPUNIT_TEST(test_rid);
CPPUNIT_TEST_SUITE_END();
private:
void test_chan_allocation();
void test_chan_deallocation();
void test_open_close();
void test_tx();
void test_rx();
void test_cs();
void test_rid();
};
#endif /* INCLUDED_QA_INBAND_USRP_SERVER_H */

View File

@ -1,40 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 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.
*/
#ifndef INCLUDED_SYMBOLS_USRP_CHANNEL_H
#define INCLUDED_SYMBOLS_USRP_CHANNEL_H
#include <pmt.h>
// Outgoing
static pmt_t s_cmd_allocate_channel = pmt_intern("cmd-allocate-channel");
static pmt_t s_cmd_deallocate_channel = pmt_intern("cmd-deallocate-channel");
// Incoming
static pmt_t s_response_allocate_channel = pmt_intern("response-allocate-channel");
static pmt_t s_response_deallocate_channel = pmt_intern("response-deallocate-channel");
// Errors
static pmt_t s_err_requested_capacity_unavailable = pmt_intern("err-requested-capacity-unavailable");
static pmt_t s_err_channel_unavailable = pmt_intern("err-channel-unavailable");
static pmt_t s_err_channel_invalid = pmt_intern("err-channel-invalid");
static pmt_t s_err_channel_permission_denied = pmt_intern("err-channel-permission-denied");
#endif /* INCLUDED_SYMBOLS_USRP_CHANNEL_H */

View File

@ -1,43 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 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.
*/
#ifndef INCLUDED_SYMBOLS_USRP_INTERFACE_CS_H
#define INCLUDED_SYMBOLS_USRP_INTERFACE_CS_H
#include <pmt.h>
// Outgoing
static pmt_t s_cmd_usrp_open = pmt_intern("cmd-usrp-open");
static pmt_t s_cmd_usrp_close = pmt_intern("cmd-usrp-close");
static pmt_t s_cmd_usrp_ntx_chan = pmt_intern("cmd-usrp-ntx-chan");
static pmt_t s_cmd_usrp_nrx_chan = pmt_intern("cmd-usrp-nrx-chan");
static pmt_t s_cmd_usrp_write = pmt_intern("cmd-usrp-write");
static pmt_t s_cmd_usrp_start_reading = pmt_intern("cmd-usrp-start-reading");
static pmt_t s_cmd_usrp_stop_reading = pmt_intern("cmd-usrp-stop-reading");
// Incoming
static pmt_t s_response_usrp_open = pmt_intern("response-usrp-open");
static pmt_t s_response_usrp_close = pmt_intern("response-usrp-close");
static pmt_t s_response_usrp_ntx_chan = pmt_intern("response-usrp-ntx-chan");
static pmt_t s_response_usrp_nrx_chan = pmt_intern("response-usrp-nrx-chan");
static pmt_t s_response_usrp_write = pmt_intern("response-usrp-write");
static pmt_t s_response_usrp_read = pmt_intern("response-usrp-read");
#endif /* INCLUDED_SYMBOLS_USRP_INTERFACE_CS_H */

View File

@ -1,47 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 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.
*/
#ifndef INCLUDED_SYMBOLS_USRP_LOW_LEVEL_CS_H
#define INCLUDED_SYMBOLS_USRP_LOW_LEVEL_CS_H
#include <pmt.h>
// Outgoing
static pmt_t s_cmd_to_control_channel = pmt_intern("cmd-to-control-channel");
// Incoming
static pmt_t s_response_from_control_channel = pmt_intern("response-from-control-channel");
// Subpackets
static pmt_t s_op_ping_fixed = pmt_intern("op-ping-fixed");
static pmt_t s_op_ping_fixed_reply = pmt_intern("op-ping-fixed-reply");
static pmt_t s_op_write_reg = pmt_intern("op-write-reg");
static pmt_t s_op_write_reg_masked = pmt_intern("op-write-reg-masked");
static pmt_t s_op_read_reg = pmt_intern("op-read-reg");
static pmt_t s_op_read_reg_reply = pmt_intern("op-read-reg-reply");
static pmt_t s_op_i2c_write = pmt_intern("op-i2c-write");
static pmt_t s_op_i2c_read = pmt_intern("op-i2c-read");
static pmt_t s_op_i2c_read_reply = pmt_intern("op-i2c-read-reply");
static pmt_t s_op_spi_write = pmt_intern("op-spi-write");
static pmt_t s_op_spi_read = pmt_intern("op-spi-read");
static pmt_t s_op_spi_read_reply = pmt_intern("op-spi-read-reply");
static pmt_t s_op_delay = pmt_intern("op-delay");
#endif /* INCLUDED_SYMBOLS_USRP_LOW_LEVEL_CS_H */

View File

@ -1,36 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 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.
*/
#ifndef INCLUDED_SYMBOLS_USRP_RX_H
#define INCLUDED_SYMBOLS_USRP_RX_H
#include <pmt.h>
// Outgoing
static pmt_t s_cmd_start_recv_raw_samples = pmt_intern("cmd-start-recv-raw-samples");
static pmt_t s_cmd_stop_recv_raw_samples = pmt_intern("cmd-stop-recv-raw-samples");
// Incoming
static pmt_t s_response_recv_raw_samples = pmt_intern("response-recv-raw-samples");
// Errors
static pmt_t s_err_already_receiving = pmt_intern("err-already-receiving");
#endif /* INCLUDED_SYMBOLS_USRP_RX_H */

View File

@ -1,32 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 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.
*/
#ifndef INCLUDED_SYMBOLS_USRP_RX_CS_H
#define INCLUDED_SYMBOLS_USRP_RX_CS_H
#include <pmt.h>
// Outgoing
static pmt_t s_cmd_usrp_rx_start_reading = pmt_intern("cmd-usrp-rx-start-reading");
// Incoming
static pmt_t s_response_usrp_rx_read = pmt_intern("response-usrp-rx-read");
#endif /* INCLUDED_SYMBOLS_USRP_RX_CS_H */

View File

@ -1,47 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 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.
*/
#ifndef INCLUDED_SYMBOLS_USRP_SERVER_CS_H
#define INCLUDED_SYMBOLS_USRP_SERVER_CS_H
#include <pmt.h>
// Outgoing
static pmt_t s_cmd_open = pmt_intern("cmd-open");
static pmt_t s_cmd_close = pmt_intern("cmd-close");
static pmt_t s_cmd_max_capacity = pmt_intern("cmd-max-capacity");
static pmt_t s_cmd_ntx_chan = pmt_intern("cmd-ntx-chan");
static pmt_t s_cmd_nrx_chan = pmt_intern("cmd-nrx-chan");
static pmt_t s_cmd_current_capacity_allocation = pmt_intern("cmd-current-capacity-allocation");
// Incoming
static pmt_t s_response_open = pmt_intern("response-open");
static pmt_t s_response_close = pmt_intern("response-close");
static pmt_t s_response_max_capacity = pmt_intern("response-max-capacity");
static pmt_t s_response_ntx_chan = pmt_intern("response-ntx-chan");
static pmt_t s_response_nrx_chan = pmt_intern("response-nrx-chan");
static pmt_t s_response_current_capacity_allocation = pmt_intern("response-current-capacity-allocation");
// Errors
static pmt_t s_err_usrp_not_opened = pmt_intern("err-usrp-not-opened");
static pmt_t s_err_usrp_already_opened = pmt_intern("err-usrp-already-opened");
static pmt_t s_err_usrp_already_closed = pmt_intern("err-usrp-already-closed");
#endif /* INCLUDED_SYMBOLS_USRP_SERVER_CS_H */

View File

@ -1,32 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 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.
*/
#ifndef INCLUDED_SYMBOLS_USRP_TX_H
#define INCLUDED_SYMBOLS_USRP_TX_H
#include <pmt.h>
// Outgoing
static pmt_t s_cmd_xmit_raw_frame = pmt_intern("cmd-xmit-raw-frame");
// Incoming
static pmt_t s_response_xmit_raw_frame = pmt_intern("response-xmit-raw-frame");
#endif /* INCLUDED_SYMBOLS_USRP_TX_H */

View File

@ -1,32 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 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.
*/
#ifndef INCLUDED_SYMBOLS_USRP_TX_CS_H
#define INCLUDED_SYMBOLS_USRP_TX_CS_H
#include <pmt.h>
// Outgoing
static pmt_t s_cmd_usrp_tx_write = pmt_intern("cmd-usrp-tx-write");
// Incoming
static pmt_t s_response_usrp_tx_write = pmt_intern("response-usrp-tx-write");
#endif /* INCLUDED_SYMBOLS_USRP_TX_CS_H */

View File

@ -1,36 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 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.
*/
#include <cppunit/TextTestRunner.h>
#include <qa_inband.h>
int
main(int argc, char **argv)
{
CppUnit::TextTestRunner runner;
runner.addTest(qa_inband::suite ());
bool was_successful = runner.run("", false);
return was_successful ? 0 : 1;
}

View File

@ -1,115 +0,0 @@
#
# Copyright 2007 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.
#
import struct
FL_OVERRUN = 0x80000000
FL_UNDERRUN = 0x40000000
FL_DROPPED = 0x20000000
FL_END_OF_BURST = 0x10000000
FL_START_OF_BURST = 0x08000000
FL_ALL_FLAGS = 0xf8000000
FL_OVERRUN_SHIFT = 31
FL_UNDERRUN_SHIFT = 30
FL_DROPPED_SHIFT = 29
FL_END_OF_BURST_SHIFT = 28
FL_START_OF_BURST_SHIFT = 27
RSSI_MASK = 0x3f
RSSI_SHIFT = 21
CHAN_MASK = 0x1f
CHAN_SHIFT = 16
TAG_MASK = 0xf
TAG_SHIFT = 9
PAYLOAD_LEN_MASK = 0x1ff
PAYLOAD_LEN_SHIFT = 0
def make_header(flags, chan, payload_len, timestamp, rssi=0, tag=0):
word0 = ((flags & FL_ALL_FLAGS)
| ((rssi & RSSI_MASK) << RSSI_SHIFT)
| ((chan & CHAN_MASK) << CHAN_SHIFT)
| ((tag & TAG_MASK) << TAG_SHIFT)
| ((payload_len & PAYLOAD_LEN_MASK) << PAYLOAD_LEN_SHIFT))
word1 = timestamp
return struct.pack('<2I', word0, word1)
def _decode(pred, indicator):
if pred:
return indicator
else:
return '-'
class usb_packet(object):
def __init__(self, raw_pkt):
assert isinstance(raw_pkt, str) and len(raw_pkt) == 512
self._raw_pkt = raw_pkt;
(self._word0, self._word1) = struct.unpack('<2I', self._raw_pkt[0:8])
def timestamp(self):
return self._word1
def rssi(self):
return (self._word0 >> RSSI_SHIFT) & RSSI_MASK
def chan(self):
return (self._word0 >> CHAN_SHIFT) & CHAN_MASK
def tag(self):
return (self._word0 >> TAG_SHIFT) & TAG_MASK
def payload_len(self):
return (self._word0 >> PAYLOAD_LEN_SHIFT) & PAYLOAD_LEN_MASK
def flags(self):
return self._word0 & FL_ALL_FLAGS
def overrun(self):
return (self._word0 >> FL_OVERRUN_SHIFT) & 0x1
def underrun(self):
return (self._word0 >> FL_UNDERRUN_SHIFT) & 0x1
def start_of_burst(self):
return (self._word0 >> FL_START_OF_BURST_SHIFT) & 0x1
def end_of_burst(self):
return (self._word0 >> FL_END_OF_BURST_SHIFT) & 0x1
def dropped(self):
return (self._word0 >> FL_DROPPED_SHIFT) & 0x1
def payload(self):
return self._raw_pkt[8:8+self.payload_len()]
def decoded_flags(self):
s = (_decode(self.overrun(), 'O')
+ _decode(self.underrun(), 'U')
+ _decode(self.dropped(), 'D')
+ _decode(self.end_of_burst(), 'E')
+ _decode(self.start_of_burst(), 'S'))
return s

View File

@ -1,793 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 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 <usrp_inband_usb_packet.h>
#include <usrp_bytesex.h>
#include <iostream>
#include <stdio.h>
#include <string.h>
/*!
* \brief Aligns the packet payload on a 32 bit boundary. This is essential to
* all control/status packets so that the inband FPGA code can parse them
* easily.
*
* \returns true if successful or if the packet was already aligned; false if it
* cannot be aligned.
*/
bool usrp_inband_usb_packet::align32()
{
int p_len = payload_len();
int bytes_needed = 4 - (p_len % 4);
if(bytes_needed == 4)
return true;
// If the room left in the packet is less than the number of bytes
// needed, return false to indicate no room to align
if((MAX_PAYLOAD - p_len) < bytes_needed)
return false;
incr_header_len(bytes_needed);
return true;
}
/*!
* \brief Adds a ping command to the current control packet.
*
* The \p rid is the rid to be associated with the ping response and \p ping_val
* is currently unused.
*
* \returns true if adding the ping command was successful, false otherwise
* (i.e. no space in the current packet).
*/
bool usrp_inband_usb_packet::cs_ping(long rid, long ping_val)
{
if(!align32())
return false;
int p_len = payload_len();
if((MAX_PAYLOAD - p_len) < (CS_PING_LEN + CS_FIXED_LEN))
return false;
uint32_t ping = (
((OP_PING_FIXED & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
| ((CS_PING_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
| ((rid & CS_RID_MASK) << CS_RID_SHIFT)
| (ping_val & CS_PINGVAL_MASK)
);
uint32_t *payload = (uint32_t *) (d_payload + p_len);
*payload = host_to_usrp_u32(ping);
// Update payload length
incr_header_len(CS_FIXED_LEN + CS_PING_LEN);
return true;
}
/*!
* \brief Adds a ping response to the packet. This is used by the fake USRP
* code to generate fake responses for pings.
*
* The \p rid is the RID to be associated with the response and \p ping_val is
* currently unused.
*
* \returns true if the ping reply was added successfully, false otherwise.
*/
bool usrp_inband_usb_packet::cs_ping_reply(long rid, long ping_val)
{
if(!align32())
return false;
int p_len = payload_len();
if((MAX_PAYLOAD - p_len) < (CS_PING_LEN + CS_FIXED_LEN))
return false;
uint32_t ping = (
((OP_PING_FIXED_REPLY & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
| ((CS_PING_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
| ((rid & CS_RID_MASK) << CS_RID_SHIFT)
| ((ping_val & CS_PINGVAL_MASK) << CS_PINGVAL_SHIFT)
);
uint32_t *payload = (uint32_t *) (d_payload + p_len);
*payload = host_to_usrp_u32(ping);
// Update payload length
incr_header_len(CS_FIXED_LEN + CS_PING_LEN);
return true;
}
/*!
* \brief Adds a write register command to the packet.
*
* The \p reg_num is the register number for which the value \p val will be
* written to.
*
* \returns true if the command was added to the packet successfully, false
* otherwise.
*/
bool usrp_inband_usb_packet::cs_write_reg(long reg_num, long val)
{
if(!align32())
return false;
int p_len = payload_len();
if((MAX_PAYLOAD - p_len) < (CS_WRITEREG_LEN + CS_FIXED_LEN))
return false;
uint32_t word0 = 0;
// Build the first word which includes the register number
word0 = (
((OP_WRITE_REG & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
| ((CS_WRITEREG_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
| ((reg_num & CS_REGNUM_MASK) << CS_REGNUM_SHIFT)
);
uint32_t *payload = (uint32_t *) (d_payload + p_len);
*payload = host_to_usrp_u32(word0);
// The second word is solely the register value to be written
// FIXME: should this be unsigned?
payload += 1;
*payload = host_to_usrp_u32((uint32_t) val);
// Rebuild the header to update the payload length
incr_header_len(CS_FIXED_LEN + CS_WRITEREG_LEN);
return true;
}
/*!
* \brief Adds a write register masked command to the packet.
*
* The \p reg_num is the register number for which the value \p val will be
* written, masked by \p mask
*
* \returns true if the command was added to the packet, false otherwise.
*/
bool usrp_inband_usb_packet::cs_write_reg_masked(long reg_num, long val, long mask)
{
if(!align32())
return false;
int p_len = payload_len();
if((MAX_PAYLOAD - p_len) < (CS_WRITEREGMASKED_LEN + CS_FIXED_LEN))
return false;
uint32_t word0 = 0;
// Build the first word which includes the register number
word0 = (
((OP_WRITE_REG_MASKED & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
| ((CS_WRITEREGMASKED_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
| ((reg_num & CS_REGNUM_MASK) << CS_REGNUM_SHIFT)
);
uint32_t *payload = (uint32_t *) (d_payload + p_len);
*payload = host_to_usrp_u32(word0);
// Skip over the first word and write the register value
payload += 1;
*payload = host_to_usrp_u32((uint32_t) val);
// Skip over the register value and write the mask
payload += 1;
*payload = host_to_usrp_u32((uint32_t) mask);
// Rebuild the header to update the payload length
incr_header_len(CS_FIXED_LEN + CS_WRITEREGMASKED_LEN);
return true;
}
/*!
* \brief Adds a read register message to the packet.
*
* The \p rid will be the associated RID returned with the response, and \p
* reg_num is the register to be read.
*
* \returns true if the command was added to the packet, false otherwise.
*/
bool usrp_inband_usb_packet::cs_read_reg(long rid, long reg_num)
{
if(!align32())
return false;
int p_len = payload_len();
if((MAX_PAYLOAD - p_len) < (CS_READREG_LEN + CS_FIXED_LEN))
return false;
uint32_t read_reg = (
((OP_READ_REG & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
| ((CS_READREG_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
| ((rid & CS_RID_MASK) << CS_RID_SHIFT)
| ((reg_num & CS_REGNUM_MASK) << CS_REGNUM_SHIFT)
);
uint32_t *payload = (uint32_t *) (d_payload + p_len);
*payload = host_to_usrp_u32(read_reg);
// Update payload length
incr_header_len(CS_FIXED_LEN + CS_READREG_LEN);
return true;
}
/*!
* \brief Adds a read register reply response to the current packet. This is
* used by the fake USRP code to generate fake register read responses for
* testing.
*
* The \p rid is the associated RID to be included in the response, \p reg_num
* is the register the read is coming from, and \p reg_val is the value of the
* read.
*
* \returns true if the command was added to the packet, false otherwise.
*/
bool usrp_inband_usb_packet::cs_read_reg_reply(long rid, long reg_num, long reg_val)
{
if(!align32())
return false;
int p_len = payload_len();
if((MAX_PAYLOAD - p_len) < (CS_READREGREPLY_LEN + CS_FIXED_LEN))
return false;
uint32_t word0 = (
((OP_READ_REG_REPLY & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
| ((CS_READREGREPLY_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
| ((rid & CS_RID_MASK) << CS_RID_SHIFT)
| ((reg_num & CS_REGNUM_MASK) << CS_REGNUM_SHIFT)
);
uint32_t *payload = (uint32_t *) (d_payload + p_len);
*payload = host_to_usrp_u32(word0);
// Hop to the next word and write the reg value
payload += 1;
*payload = host_to_usrp_u32((uint32_t) reg_val);
// Update payload length
incr_header_len(CS_FIXED_LEN + CS_READREGREPLY_LEN);
return true;
}
/*!
* \brief Adds a delay command to the current packet.
*
* The \p ticks parameter is the number of clock ticks the FPGA should delay
* parsing for, which is added to the packet.
*
* \returns true if the command was added to the packet, false otherwise.
*/
bool usrp_inband_usb_packet::cs_delay(long ticks)
{
if(!align32())
return false;
int p_len = payload_len();
if((MAX_PAYLOAD - p_len) < (CS_DELAY_LEN + CS_FIXED_LEN))
return false;
uint32_t delay = (
((OP_DELAY & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
| ((CS_DELAY_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
| ((ticks & CS_DELAY_MASK) << CS_DELAY_SHIFT)
);
uint32_t *payload = (uint32_t *) (d_payload + p_len);
*payload = host_to_usrp_u32(delay);
// Update payload length
incr_header_len(CS_FIXED_LEN + CS_DELAY_LEN);
return true;
}
/*!
* \brief
*
* \returns true if the command was added to the packet, false otherwise.
*/
bool usrp_inband_usb_packet::cs_i2c_write(long i2c_addr, uint8_t *i2c_data, size_t data_len)
{
if(!align32())
return false;
int p_len = payload_len();
int i2c_len = data_len + 2; // 2 bytes between mbz and addr
if((MAX_PAYLOAD - p_len) < (i2c_len + CS_FIXED_LEN))
return false;
uint32_t word0 = 0;
word0 = (
((OP_I2C_WRITE & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
| ((i2c_len & CS_LEN_MASK) << CS_LEN_SHIFT)
| ((i2c_addr & CS_I2CADDR_MASK) << CS_I2CADDR_SHIFT)
);
uint32_t *payload = (uint32_t *) (d_payload + p_len);
*payload = host_to_usrp_u32(word0);
// Jump over the first word and write the data
// FIXME: Should the data be changed to usrp byte order?
payload += 1;
memcpy(payload, i2c_data, data_len);
// Update payload length
incr_header_len(CS_FIXED_LEN + i2c_len);
return true;
}
/*!
* \brief Adds an I2C read command to the current packet.
*
* The \p rid is the associated RID to return with the read response, \p
* i2c_addr is the address to read from on the I2C bus, and \p n_bytes is the
* number of bytes to be read from the bus.
*
* \returns true if the command was added to the packet, false otherwise.
*/
bool usrp_inband_usb_packet::cs_i2c_read(long rid, long i2c_addr, long n_bytes)
{
if(!align32())
return false;
int p_len = payload_len();
if((MAX_PAYLOAD - p_len) < (CS_I2CREAD_LEN + CS_FIXED_LEN))
return false;
uint32_t word0 = 0;
word0 = (
((OP_I2C_READ & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
| ((CS_I2CREAD_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
| ((rid & CS_RID_MASK) << CS_RID_SHIFT)
| ((i2c_addr & CS_I2CADDR_MASK) << CS_I2CADDR_SHIFT)
);
uint32_t *payload = (uint32_t *) (d_payload + p_len);
*payload = host_to_usrp_u32(word0);
// Jump a word and write the number of bytes to read
payload += 1;
uint32_t word1 =
(n_bytes & CS_I2CREADBYTES_MASK) << CS_I2CREADBYTES_SHIFT;
*payload = host_to_usrp_u32(word1);
// Update payload length
incr_header_len(CS_FIXED_LEN + CS_I2CREAD_LEN);
return true;
}
/*!
* \brief Adds an I2C read reply response to the current packet. This is used
* by the fake USRP code to generate fake I2C responses.
*
* The \p rid is the RID to be associated with the response, \p i2c_addr is the
* address on the I2C bus that the \p i2c_data of \p i2c_data_len was read from.
*
* \returns true if the command was added to the packet, false otherwise.
*/
bool usrp_inband_usb_packet::cs_i2c_read_reply(long rid, long i2c_addr, uint8_t *i2c_data, long i2c_data_len)
{
if(!align32())
return false;
int p_len = payload_len();
int i2c_len = i2c_data_len + 2;
if((MAX_PAYLOAD - p_len) < (i2c_len + CS_FIXED_LEN))
return false;
uint32_t word0 = 0;
word0 = (
((OP_I2C_READ_REPLY & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
| ((i2c_len & CS_LEN_MASK) << CS_LEN_SHIFT)
| ((rid & CS_RID_MASK) << CS_RID_SHIFT)
| ((i2c_addr & CS_I2CADDR_MASK) << CS_I2CADDR_SHIFT)
);
uint32_t *payload = (uint32_t *) (d_payload + p_len);
*payload = host_to_usrp_u32(word0);
// Jump a word and write the actual data
payload += 1;
memcpy(payload, i2c_data, i2c_data_len);
// Update payload length
incr_header_len(CS_FIXED_LEN + i2c_len);
return true;
}
/*!
* \brief Adds a SPI write command to the current packet.
*
* \returns true if the command was added to the packet, false otherwise.
*/
bool usrp_inband_usb_packet::cs_spi_write(long enables, long format, long opt_header_bytes, uint8_t *spi_data, long spi_data_len)
{
if(!align32())
return false;
int p_len = payload_len();
int spi_len = spi_data_len + 6;
if((MAX_PAYLOAD - p_len) < (spi_len + CS_FIXED_LEN))
return false;
uint32_t word = 0;
// First word contains the opcode and length, then mbz
word = (
((OP_SPI_WRITE & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
| ((spi_len & CS_LEN_MASK) << CS_LEN_SHIFT)
);
uint32_t *payload = (uint32_t *) (d_payload + p_len);
*payload = host_to_usrp_u32(word);
payload += 1;
// Second word contains the enables, format, and optional tx bytes
word = 0;
word = (
((enables & CS_SPIENABLES_MASK) << CS_SPIENABLES_SHIFT)
| ((format & CS_SPIFORMAT_MASK) << CS_SPIFORMAT_SHIFT)
| ((opt_header_bytes & CS_SPIOPT_MASK) << CS_SPIOPT_SHIFT)
);
payload = (uint32_t *) (d_payload + p_len);
*payload = host_to_usrp_u32(word);
payload += 1;
memcpy(payload, spi_data, spi_data_len);
// Update payload length
incr_header_len(CS_FIXED_LEN + spi_len);
return true;
}
/*!
* \brief Adds a SPI bus read command to the packet.
*
* \returns true if the command was added to the packet, false otherwise.
*/
bool usrp_inband_usb_packet::cs_spi_read(long rid, long enables, long format, long opt_header_bytes, long n_bytes)
{
if(!align32())
return false;
int p_len = payload_len();
if((MAX_PAYLOAD - p_len) < (CS_SPIREAD_LEN + CS_FIXED_LEN))
return false;
uint32_t word = 0;
// First word contains the opcode, length, and RID
word = (
((OP_SPI_READ & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
| ((CS_SPIREAD_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
| ((rid & CS_RID_MASK) << CS_RID_SHIFT)
);
uint32_t *payload = (uint32_t *) (d_payload + p_len);
*payload = host_to_usrp_u32(word);
payload += 1;
// Second word contains the enables, format, and optional tx bytes
word = 0;
word = (
((enables & CS_SPIENABLES_MASK) << CS_SPIENABLES_SHIFT)
| ((format & CS_SPIFORMAT_MASK) << CS_SPIFORMAT_SHIFT)
| ((opt_header_bytes & CS_SPIOPT_MASK) << CS_SPIOPT_SHIFT)
);
payload = (uint32_t *) (d_payload + p_len);
*payload = host_to_usrp_u32(word);
payload += 1;
// The third word contains the number of bytes
word = 0;
word = (
((n_bytes & CS_SPINBYTES_MASK) << CS_SPINBYTES_SHIFT)
);
payload = (uint32_t *) (d_payload + p_len);
*payload = host_to_usrp_u32(word);
// Update payload length
incr_header_len(CS_FIXED_LEN + CS_SPIREAD_LEN);
return true;
}
/*!
* \brief Adds an SPI read reply to the current packet. This is used by the
* fake USRP code to generate fake responses for SPI reads.
*
* \returns true if the command was added to the packet, false otherwise.
*/
bool usrp_inband_usb_packet::cs_spi_read_reply(long rid, uint8_t *spi_data, long spi_data_len)
{
if(!align32())
return false;
int p_len = payload_len();
int spi_len = spi_data_len + 2;
if((MAX_PAYLOAD - p_len) < (spi_len + CS_FIXED_LEN))
return false;
uint32_t word = 0;
// First word contains the opcode, length, and RID
word = (
((OP_SPI_READ_REPLY & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
| ((spi_len & CS_LEN_MASK) << CS_LEN_SHIFT)
| ((rid & CS_RID_MASK) << CS_RID_SHIFT)
);
uint32_t *payload = (uint32_t *) (d_payload + p_len);
*payload = host_to_usrp_u32(word);
// Jump a word and write the actual data
payload += 1;
memcpy(payload, spi_data, spi_data_len);
// Update payload length
incr_header_len(CS_FIXED_LEN + spi_len);
return true;
}
/*!
* \brief Since all control packets contain subpackets which have the length of
* the subpacket at a uniform location in the subpacket, this will return the
* subpacket length given a byte offset of the start of the subpacket from the beginning of the packet.
*
* \returns the length of the subpacket
*/
int usrp_inband_usb_packet::cs_len(int payload_offset) {
uint32_t subpkt = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset)));
return (subpkt >> CS_LEN_SHIFT) & CS_LEN_MASK;
}
/*!
* \brief The following method takes an offset within the packet payload to
* extract a control/status subpacket and constructs a pmt response which
* includes the proper signal and arguments specified by usrp-low-level-cs. The
* USRP server could therefore use this to read subpackets and pass them
* responses back up to the application. It's arguable that only reply packets
* should be parsed here, however we parse others for use in debugging or
* failure reporting on the transmit side of packets.
*/
pmt_t usrp_inband_usb_packet::read_subpacket(int payload_offset) {
uint32_t subpkt = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset)));
uint32_t opcode = (subpkt >> CS_OPCODE_SHIFT) & CS_OPCODE_MASK;
uint32_t len = (subpkt >> CS_LEN_SHIFT) & CS_LEN_MASK;
switch(opcode) {
case OP_PING_FIXED_REPLY:
{
pmt_t rid = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
pmt_t pingval = pmt_from_long((subpkt >> CS_PINGVAL_SHIFT) & CS_PINGVAL_MASK);
return pmt_list3(s_op_ping_fixed_reply, rid, pingval);
}
case OP_READ_REG_REPLY:
{
pmt_t rid = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
pmt_t reg_num = pmt_from_long((subpkt >> CS_REGNUM_SHIFT) & CS_REGNUM_MASK);
// To get the register value we just read the next 32 bits
uint32_t val = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 4)));
pmt_t reg_val = pmt_from_long(val);
return pmt_list4(s_op_read_reg_reply, rid, reg_num, reg_val);
}
case OP_I2C_READ_REPLY:
{
pmt_t rid = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
pmt_t i2c_addr = pmt_from_long((subpkt >> CS_I2CADDR_SHIFT) & CS_I2CADDR_MASK);
// Make a u8 vector to dump the data from the packet into
size_t i2c_data_len;
pmt_t i2c_data = pmt_make_u8vector(len - 2, 0); // skip rid+mbz+addr = 2 bytes
uint8_t *w_data =
(uint8_t *) pmt_u8vector_writable_elements(i2c_data, i2c_data_len);
memcpy(w_data, d_payload + payload_offset + 4, i2c_data_len); // skip first word
return pmt_list4(s_op_i2c_read_reply, rid, i2c_addr, i2c_data);
}
case OP_SPI_READ_REPLY:
{
pmt_t rid = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
// Make a u8 vector to dump the data from the packet into
size_t spi_data_len;
pmt_t spi_data = pmt_make_u8vector(len - 2, 0); // skip rid+mbz+addr = 2 bytes
uint8_t *w_data =
(uint8_t *) pmt_u8vector_writable_elements(spi_data, spi_data_len);
memcpy(w_data, d_payload + payload_offset + 4, spi_data_len); // skip first word
return pmt_list3(s_op_spi_read_reply, rid, spi_data);
}
case OP_PING_FIXED:
{
pmt_t rid = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
pmt_t pingval = pmt_from_long((subpkt >> CS_PINGVAL_SHIFT) & CS_PINGVAL_MASK);
return pmt_list3(s_op_ping_fixed, rid, pingval);
}
case OP_WRITE_REG:
{
pmt_t reg_num = pmt_from_long((subpkt >> CS_REGNUM_SHIFT) & CS_REGNUM_MASK);
// To get the register value we just read the next 32 bits
uint32_t val = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 4)));
pmt_t reg_val = pmt_from_long(val);
return pmt_list3(s_op_write_reg, reg_num, reg_val);
}
case OP_WRITE_REG_MASKED:
{
pmt_t reg_num = pmt_from_long((subpkt >> CS_REGNUM_SHIFT) & CS_REGNUM_MASK);
// To get the register value we just read the next 32 bits
uint32_t val = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 4)));
pmt_t reg_val = pmt_from_long(val);
// The mask is the next 32 bits
uint32_t mask = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 8)));
pmt_t reg_mask = pmt_from_long(mask);
return pmt_list4(s_op_write_reg_masked, reg_num, reg_val, reg_mask);
}
case OP_READ_REG:
{
pmt_t rid = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
pmt_t reg_num = pmt_from_long((subpkt >> CS_REGNUM_SHIFT) & CS_REGNUM_MASK);
return pmt_list3(s_op_read_reg, rid, reg_num);
}
case OP_I2C_WRITE:
{
pmt_t i2c_addr = pmt_from_long((subpkt >> CS_I2CADDR_SHIFT) & CS_I2CADDR_MASK);
// The length includes an extra 2 bytes for storing the mbz and addr
pmt_t i2c_data = pmt_make_u8vector(len-2, 0);
// Get a writable address to copy the data from the packet
size_t ignore;
uint8_t *w_data = (uint8_t *) pmt_u8vector_writable_elements(i2c_data, ignore);
memcpy(w_data, d_payload + payload_offset + 4, len-2);
return pmt_list3(s_op_i2c_write, i2c_addr, i2c_data);
}
case OP_I2C_READ:
{
pmt_t rid = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
pmt_t i2c_addr = pmt_from_long((subpkt >> CS_I2CADDR_SHIFT) & CS_I2CADDR_MASK);
// The number of bytes is in the next word
uint32_t bytes = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 4)));
bytes = (bytes >> CS_I2CREADBYTES_SHIFT) & CS_I2CREADBYTES_MASK;
pmt_t i2c_bytes = pmt_from_long(bytes);
return pmt_list4(s_op_i2c_read, rid, i2c_addr, i2c_bytes);
}
case OP_SPI_WRITE:
{
// Nothing interesting in the first word, skip to the next
uint32_t word = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 4)));
pmt_t enables = pmt_from_long((word >> CS_SPIENABLES_SHIFT) & CS_SPIENABLES_MASK);
pmt_t format = pmt_from_long((word >> CS_SPIFORMAT_SHIFT) & CS_SPIFORMAT_MASK);
pmt_t opt = pmt_from_long((word >> CS_SPIOPT_SHIFT) & CS_SPIOPT_MASK);
// From the next word and on is data
size_t spi_data_len;
pmt_t spi_data = pmt_make_u8vector(len - 6, 0); // skip rid+mbz+addr = 2 bytes
uint8_t *w_data =
(uint8_t *) pmt_u8vector_writable_elements(spi_data, spi_data_len);
memcpy(w_data, d_payload + payload_offset + 8, spi_data_len); // skip first 2 words
return pmt_list5(s_op_spi_write, enables, format, opt, spi_data);
}
case OP_SPI_READ:
{
// Read the RID from the first word, the rest is mbz
pmt_t rid = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
// Continue at the next word...
uint32_t word = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 4)));
pmt_t enables = pmt_from_long((word >> CS_SPIENABLES_SHIFT) & CS_SPIENABLES_MASK);
pmt_t format = pmt_from_long((word >> CS_SPIFORMAT_SHIFT) & CS_SPIFORMAT_MASK);
pmt_t opt = pmt_from_long((word >> CS_SPIOPT_SHIFT) & CS_SPIOPT_MASK);
// The number of bytes is the only thing to read in the next word
word = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 8)));
pmt_t n_bytes = pmt_from_long((word >> CS_SPINBYTES_SHIFT) & CS_SPINBYTES_MASK);
return pmt_list6(s_op_spi_read, rid, enables, format, opt, n_bytes);
}
case OP_DELAY:
{
pmt_t ticks = pmt_from_long((subpkt >> CS_DELAY_SHIFT) & CS_DELAY_MASK);
return pmt_list2(s_op_delay, ticks);
}
default:
return PMT_NIL;
}
}

View File

@ -1,240 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,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.
*/
#ifndef INCLUDED_USRP_INBAND_USB_PACKET_H_
#define INCLUDED_USRP_INBAND_USB_PACKET_H_
#include <usrp_bytesex.h>
#include <mblock/mblock.h>
#include <pmt.h>
#include <iostream>
#include <symbols_usrp_low_level_cs.h>
static const int USB_PKT_SIZE = 512; // bytes
static const int MAX_PAYLOAD = USB_PKT_SIZE-2*sizeof(uint32_t);
static const int CONTROL_CHAN = 0x1f;
class usrp_inband_usb_packet {
//
// keep raw packet in USRP-endian order
//
uint32_t d_word0;
uint32_t d_timestamp;
unsigned char d_payload[MAX_PAYLOAD];
public:
enum opcodes {
OP_PING_FIXED = 0x00,
OP_PING_FIXED_REPLY = 0x01,
OP_WRITE_REG = 0x02,
OP_WRITE_REG_MASKED = 0x03,
OP_READ_REG = 0x04,
OP_READ_REG_REPLY = 0x05,
OP_I2C_WRITE = 0x06,
OP_I2C_READ = 0x07,
OP_I2C_READ_REPLY = 0x08,
OP_SPI_WRITE = 0x09,
OP_SPI_READ = 0x0a,
OP_SPI_READ_REPLY = 0x0b,
OP_DELAY = 0x0c
};
enum flags {
FL_OVERRUN = 0x80000000,
FL_UNDERRUN = 0x40000000,
FL_DROPPED = 0x20000000,
FL_START_OF_BURST = 0x10000000,
FL_END_OF_BURST = 0x08000000,
FL_CARRIER_SENSE = 0x04000000,
FL_ALL_FLAGS = 0xfc000000
};
static const int FL_OVERRUN_SHIFT = 31;
static const int FL_UNDERRUN_SHIFT = 30;
static const int FL_DROPPED_SHIFT = 29;
static const int FL_END_OF_BURST_SHIFT = 27;
static const int FL_START_OF_BURST_SHIFT = 28;
static const int RSSI_MASK = 0x3f;
static const int RSSI_SHIFT = 21;
static const int CHAN_MASK = 0x1f;
static const int CHAN_SHIFT = 16;
static const int TAG_MASK = 0xf;
static const int TAG_SHIFT = 9;
static const int PAYLOAD_LEN_MASK = 0x1ff;
static const int PAYLOAD_LEN_SHIFT = 0;
// Fixed size for opcode and length fields
static const int CS_FIXED_LEN = 2;
static const int CS_OPCODE_MASK = 0xff;
static const int CS_OPCODE_SHIFT = 24;
static const int CS_LEN_MASK = 0xff;
static const int CS_LEN_SHIFT = 16;
static const int CS_RID_MASK = 0x3f;
static const int CS_RID_SHIFT = 10;
static const int CS_PING_LEN = 2;
static const int CS_PINGVAL_MASK = 0x3ff;
static const int CS_PINGVAL_SHIFT = 0;
static const int CS_WRITEREG_LEN = 6;
static const int CS_WRITEREGMASKED_LEN = 10;
static const int CS_READREG_LEN = 2;
static const int CS_READREGREPLY_LEN = 6;
static const int CS_REGNUM_MASK = 0x3ff;
static const int CS_REGNUM_SHIFT = 0;
static const int CS_DELAY_LEN = 2;
static const int CS_DELAY_MASK = 0xffff;
static const int CS_DELAY_SHIFT = 0;
static const int CS_I2CADDR_MASK = 0x7f;
static const int CS_I2CADDR_SHIFT = 0;
static const int CS_I2CREAD_LEN = 3;
static const int CS_I2CREADBYTES_MASK = 0x7f;
static const int CS_I2CREADBYTES_SHIFT = 24;
static const int CS_SPIOPT_MASK = 0xffff;
static const int CS_SPIOPT_SHIFT = 0;
static const int CS_SPIFORMAT_MASK = 0xff;
static const int CS_SPIFORMAT_SHIFT = 16;
static const int CS_SPIENABLES_MASK = 0xff;
static const int CS_SPIENABLES_SHIFT = 24;
static const int CS_SPIREAD_LEN = 7;
static const int CS_SPINBYTES_MASK = 0xff;
static const int CS_SPINBYTES_SHIFT = 24;
public:
void set_timestamp(uint32_t timestamp){
d_timestamp = host_to_usrp_u32(timestamp);
}
void set_end_of_burst() {
uint32_t word0 = usrp_to_host_u32(d_word0);
word0 |= 1<<FL_END_OF_BURST_SHIFT;
d_word0 = host_to_usrp_u32(word0);
}
void set_header(int flags, int chan, int tag, int payload_len){
uint32_t word0 = ((flags & FL_ALL_FLAGS)
| ((chan & CHAN_MASK) << CHAN_SHIFT)
| ((tag & TAG_MASK) << TAG_SHIFT)
| ((payload_len & PAYLOAD_LEN_MASK) << PAYLOAD_LEN_SHIFT));
d_word0 = host_to_usrp_u32(word0);
}
void incr_header_len(int val) {
set_header(flags(), chan(), tag(), payload_len() + val);
}
uint32_t timestamp() const {
return usrp_to_host_u32(d_timestamp);
}
int rssi() const {
uint32_t word0 = usrp_to_host_u32(d_word0);
return (word0 >> RSSI_SHIFT) & RSSI_MASK;
}
int chan() const {
uint32_t word0 = usrp_to_host_u32(d_word0);
return (word0 >> CHAN_SHIFT) & CHAN_MASK;
}
int tag() const {
uint32_t word0 = usrp_to_host_u32(d_word0);
return (word0 >> TAG_SHIFT) & TAG_MASK;
}
int payload_len() const {
uint32_t word0 = usrp_to_host_u32(d_word0);
return (word0 >> PAYLOAD_LEN_SHIFT) & PAYLOAD_LEN_MASK;
}
int flags() const {
return usrp_to_host_u32(d_word0) & FL_ALL_FLAGS;
}
int overrun() const {
return (usrp_to_host_u32(d_word0) & FL_OVERRUN) >> FL_OVERRUN_SHIFT;
}
int underrun() const {
return (usrp_to_host_u32(d_word0) & FL_UNDERRUN) >> FL_UNDERRUN_SHIFT;
}
int start_of_burst() const {
return (usrp_to_host_u32(d_word0) & FL_START_OF_BURST) >> FL_START_OF_BURST_SHIFT;
}
int end_of_burst() const {
return (usrp_to_host_u32(d_word0) & FL_END_OF_BURST) >> FL_END_OF_BURST_SHIFT;
}
int dropped() const {
return (usrp_to_host_u32(d_word0) & FL_DROPPED) >> FL_DROPPED_SHIFT;
}
unsigned char *payload() {
return d_payload;
}
static int max_payload() {
return MAX_PAYLOAD;
}
static int max_pkt_size() {
return USB_PKT_SIZE;
}
// C/S methods
bool align32();
bool cs_ping(long rid, long ping_val);
bool cs_ping_reply(long rid, long ping_val);
bool cs_write_reg(long reg_num, long val);
bool cs_write_reg_masked(long reg_num, long val, long mask);
bool cs_read_reg(long rid, long reg_num);
bool cs_read_reg_reply(long rid, long reg_num, long reg_val);
bool cs_delay(long ticks);
bool cs_i2c_write(long i2c_addr, uint8_t *i2c_data, size_t data_len);
bool cs_i2c_read(long rid, long i2c_addr, long n_bytes);
bool cs_i2c_read_reply(long rid, long i2c_addr, uint8_t *i2c_data, long i2c_data_len);
bool cs_spi_write(long enables, long format, long opt_header_bytes, uint8_t *spi_data, long spi_data_len);
bool cs_spi_read(long rid, long enables, long format, long opt_header_bytes, long n_bytes);
bool cs_spi_read_reply(long rid, uint8_t *spi_data, long spi_data_len);
int cs_len(int payload_offset);
pmt_t read_subpacket(int payload_offset);
};
#endif

View File

@ -1,88 +0,0 @@
;; -*- scheme -*- ; not really, but tells emacs how to format this
;;
;; Copyright 2007 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 2, 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.
;;
;; ----------------------------------------------------------------
;; This is an mblock header file
;;
;; The format is very much a work-in-progress.
;; It'll be compiled to C++.
;; ----------------------------------------------------------------
;; ----------------------------------------------------------------
;; usrp-interface-cs
;;
;; Handles interaction between the usrp_sever and the USB interface
(define-protocol-class usrp-interface-cs
(:outgoing
(cmd-usrp-open invocation-handle which-usrp)
(cmd-usrp-close invocation-handle)
(cmd-usrp-ntx-chan invocation-handle)
(cmd-usrp-nrx-chan invocation-handle)
(cmd-usrp-write invocation-handle channel data)
(cmd-usrp-start-reading invocation-handle channel)
)
(:incoming
(response-usrp-open invocation-handle status)
(response-usrp-close invocation-handle status)
(response-usrp-ntx-chan invocation-handle ntx-chan)
(response-usrp-nrx-chan invocation-handle nrx-chan)
(response-usrp-write invocation-handle status channel)
(response-usrp-read invocation-handle status data)
)
)
;; ----------------------------------------------------------------
;; usrp-tx-cs
;;
;; Handles interaction between the USB interface and TX interface
(define-protocol-class usrp-tx-cs
(:outgoing
(cmd-usrp-tx-write invocation-handle channel data tx-handle)
)
(:incoming
(response-usrp-tx-write invocation-handle status channel)
)
)
;; ----------------------------------------------------------------
;; usrp-rx-cs
;;
;; Handles interaction between the USB interface and RX interface
(define-protocol-class usrp-rx-cs
(:outgoing
(cmd-usrp-rx-start-reading invocation-handle rx-handle)
(cmd-usrp-rx-stop-reading invocation-handle)
)
(:incoming
(response-usrp-rx-read invocation-handle status data)
;; There is currently no response to a stop reading
)
)

View File

@ -1,184 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 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 <usrp_rx.h>
#include <usrp_standard.h>
#include <iostream>
#include <vector>
#include <usb.h>
#include <mblock/class_registry.h>
#include <usrp_inband_usb_packet.h>
#include <fpga_regs_common.h>
#include <stdio.h>
#include <symbols_usrp_rx_cs.h>
typedef usrp_inband_usb_packet transport_pkt;
static const bool verbose = false;
bool usrp_rx_stop;
usrp_rx::usrp_rx(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg)
: mb_mblock(rt, instance_name, user_arg),
d_disk_write(false),
d_disk_write_pkt(false) // if true, writes full packet, else just the payload
{
d_cs = define_port("cs", "usrp-rx-cs", true, mb_port::EXTERNAL);
if(d_disk_write) {
d_ofile0.open("rx_data_chan0.dat",std::ios::binary|std::ios::out);
d_ofile1.open("rx_data_chan1.dat",std::ios::binary|std::ios::out);
d_cs_ofile.open("rx_cs.dat",std::ios::binary|std::ios::out);
}
usrp_rx_stop = false;
}
usrp_rx::~usrp_rx()
{
if(d_disk_write) {
d_ofile0.close();
d_ofile1.close();
d_cs_ofile.close();
}
}
void
usrp_rx::initial_transition()
{
}
/*!
* \brief Handles incoming signals to to the m-block, wihch should only ever be
* a single message: cmd-usrrp-rx-start-reading. There is no signal to stop
* reading as the m-block goes in to a forever loop to read inband packets from
* the bus.
*/
void
usrp_rx::handle_message(mb_message_sptr msg)
{
pmt_t event = msg->signal();
pmt_t port_id = msg->port_id();
pmt_t data = msg->data();
// Theoretically only have 1 message to ever expect, but
// want to make sure its at least what we want
if(pmt_eq(port_id, d_cs->port_symbol())) {
if(pmt_eqv(event, s_cmd_usrp_rx_start_reading))
read_and_respond(data);
}
}
/*!
* \brief Performs the actual reading of data from the USB bus, called by
* handle_message() when a cmd-usrp-rx-start-reading signal is received.
*
* The method enters a forever loop where it continues to read data from the bus
* and generate read responses to the higher layer. Currently, shared memory is
* used to exit this loop.
*
* The \p data parameter is a PMT list which contains only a single element, an
* invocation handle which will be returned with all read respones.
*/
void
usrp_rx::read_and_respond(pmt_t data)
{
size_t ignore;
bool underrun;
unsigned int n_read;
unsigned int pkt_size = sizeof(transport_pkt);
pmt_t invocation_handle = pmt_nth(0, data);
// Need the handle to the RX port to send responses, this is passed
// by the USRP interface m-block
pmt_t handle = pmt_nth(1, data);
d_urx =
boost::any_cast<usrp_standard_rx_sptr>(pmt_any_ref(handle));
if(verbose)
std::cout << "[usrp_rx] Waiting for packets..\n";
// Read by 512 which is packet size and send them back up
while(!usrp_rx_stop) {
pmt_t v_pkt = pmt_make_u8vector(pkt_size, 0);
transport_pkt *pkt =
(transport_pkt *) pmt_u8vector_writable_elements(v_pkt, ignore);
n_read = d_urx->read(pkt, pkt_size, &underrun);
if(n_read != pkt_size) {
std::cerr << "[usrp_rx] Error reading packet, shutting down\n";
d_cs->send(s_response_usrp_rx_read,
pmt_list3(PMT_NIL, PMT_F, PMT_NIL));
return;
}
if(underrun && verbose && 0)
std::cout << "[usrp_rx] Underrun\n";
d_cs->send(s_response_usrp_rx_read,
pmt_list3(PMT_NIL, PMT_T, v_pkt));
if(verbose && 0)
std::cout << "[usrp_rx] Read 1 packet\n";
if(d_disk_write) {
if(pkt->chan() == CONTROL_CHAN)
d_cs_ofile.write((const char *)pkt, transport_pkt::max_pkt_size());
else {
if(d_disk_write_pkt) {
if(pkt->chan() == 0)
d_ofile0.write((const char *)pkt, transport_pkt::max_pkt_size());
else if(pkt->chan() == 1)
d_ofile1.write((const char *)pkt, transport_pkt::max_pkt_size());
} else {
if(pkt->chan() == 0)
d_ofile0.write((const char *)pkt->payload(), transport_pkt::max_payload());
else if(pkt->chan() == 1)
d_ofile1.write((const char *)pkt->payload(), transport_pkt::max_payload());
}
}
d_cs_ofile.flush();
d_ofile0.flush();
d_ofile1.flush();
}
}
usrp_rx_stop = false;
if(verbose) {
std::cout << "[USRP_RX] Stopping...\n";
fflush(stdout);
}
}
REGISTER_MBLOCK_CLASS(usrp_rx);

View File

@ -1,58 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,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.
*/
#ifndef INCLUDED_USRP_RX_H
#define INCLUDED_USRP_RX_H
#include <mblock/mblock.h>
#include <fstream>
#include "usrp_standard.h"
extern bool usrp_rx_stop; // used to communicate a 'stop' to the RX stub
/*!
* \brief Implements the low level usb interface to the USRP
*/
class usrp_rx : public mb_mblock
{
mb_port_sptr d_cs;
usrp_standard_rx_sptr d_urx;
bool d_disk_write;
bool d_disk_write_pkt;
std::ofstream d_ofile0;
std::ofstream d_ofile1;
std::ofstream d_cs_ofile;
public:
usrp_rx(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
~usrp_rx();
void initial_transition();
void handle_message(mb_message_sptr msg);
private:
void read_and_respond(pmt_t data);
void read_data();
};
#endif /* INCLUDED_USRP_RX_H */

View File

@ -1,227 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,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 <usrp_rx_stub.h>
#include <iostream>
#include <vector>
#include <usb.h>
#include <mblock/class_registry.h>
#include <usrp_inband_usb_packet.h>
#include <fpga_regs_common.h>
#include "usrp_standard.h"
#include <stdio.h>
#include <string.h>
#include <ui_nco.h>
#include <fstream>
#include <symbols_usrp_rx_cs.h>
typedef usrp_inband_usb_packet transport_pkt;
static const bool verbose = false;
bool usrp_rx_stop_stub;
// Used for the fake control packet response code to send the responses back up
// the RX. The TX stub dumps responses in to this queue.
std::queue<pmt_t> d_cs_queue;
usrp_rx_stub::usrp_rx_stub(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg)
: mb_mblock(rt, instance_name, user_arg),
d_samples_per_frame((long)(126)),
d_decim_rx(128),
d_amplitude(16384),
d_disk_write(false)
{
// Information about the rates are passed all the way from the app in the form
// of a dictionary. We use this to read the RX decimation rate and compute
// the approximate number of MS/s as a form of flow control for the stub.
pmt_t usrp_dict = user_arg;
if (pmt_is_dict(usrp_dict)) {
// Read the RX decimation rate
if(pmt_t decim_rx = pmt_dict_ref(usrp_dict,
pmt_intern("decim-rx"),
PMT_NIL)) {
if(!pmt_eqv(decim_rx, PMT_NIL))
d_decim_rx = pmt_to_long(decim_rx);
}
}
d_cs = define_port("cs", "usrp-rx-cs", true, mb_port::EXTERNAL);
// initialize NCO
double freq = 100e3;
int interp = 32; // 32 -> 4MS/s
double sample_rate = 64e6 / interp;
d_nco.set_freq(2*M_PI * freq/sample_rate);
//d_disk_write = true;
if(d_disk_write)
d_ofile.open("raw_rx.dat",std::ios::binary|std::ios::out);
usrp_rx_stop_stub = false;
}
usrp_rx_stub::~usrp_rx_stub()
{
if(d_disk_write)
d_ofile.close();
}
void
usrp_rx_stub::initial_transition()
{
}
void
usrp_rx_stub::handle_message(mb_message_sptr msg)
{
pmt_t event = msg->signal();
pmt_t port_id = msg->port_id();
pmt_t data = msg->data();
if (pmt_eq(msg->signal(), s_timeout)
&& !pmt_eq(msg->data(), s_done)) {
if(!usrp_rx_stop_stub)
read_and_respond();
else { // requested to stop
cancel_timeout(msg->metadata());
usrp_rx_stop_stub=false;
if(verbose)
std::cout << "[USRP_RX_STUB] Stopping RX stub\n";
}
}
// Theoretically only have 1 message to ever expect, but
// want to make sure its at least what we want
if(pmt_eq(port_id, d_cs->port_symbol())
&& pmt_eqv(event, s_cmd_usrp_rx_start_reading)) {
if(verbose)
std::cout << "[USRP_RX_STUB] Starting with decim @ "
<< d_decim_rx << std::endl;
start_packet_timer();
}
}
// Setup a periodic timer which will drive packet generation
void
usrp_rx_stub::start_packet_timer()
{
d_t0 = mb_time::time(); // current time
// Calculate the inter-packet arrival time.
double samples_per_sec = (64.0/(double)d_decim_rx)*1000000.0;
double frames_per_sec = samples_per_sec / (double)d_samples_per_frame;
double frame_rate = 1.0 / frames_per_sec;
if(verbose) {
std::cout << "[USRP_RX_STUB] Scheduling periodic packet generator\n";
std::cout << "\tsamples_per_sec: " << samples_per_sec << std::endl;
std::cout << "\tframes_per_sec: " << frames_per_sec << std::endl;
std::cout << "\tframe_rate: " << frame_rate << std::endl;
}
schedule_periodic_timeout(d_t0 + frame_rate, mb_time(frame_rate), PMT_T);
}
void
usrp_rx_stub::read_and_respond()
{
long nsamples_this_frame = d_samples_per_frame;
size_t nshorts = 2 * nsamples_this_frame; // 16-bit I & Q
long channel = 0;
long n_bytes = nshorts*2;
pmt_t uvec = pmt_make_s16vector(nshorts, 0);
size_t ignore;
int16_t *samples = pmt_s16vector_writable_elements(uvec, ignore);
// fill in the complex sinusoid
for (int i = 0; i < nsamples_this_frame; i++){
if (1){
gr_complex s;
d_nco.sincos(&s, 1, d_amplitude);
// write 16-bit i & q
samples[2*i] = (int16_t) s.real();
samples[2*i+1] = (int16_t) s.imag();
}
else {
gr_complex s(d_amplitude, d_amplitude);
// write 16-bit i & q
samples[2*i] = (int16_t) s.real();
samples[2*i+1] = (int16_t) s.imag();
}
}
if(d_disk_write)
d_ofile.write((const char *)samples, n_bytes);
pmt_t v_pkt = pmt_make_u8vector(sizeof(transport_pkt), 0);
transport_pkt *pkt =
(transport_pkt *) pmt_u8vector_writable_elements(v_pkt, ignore);
pkt->set_header(0, channel, 0, n_bytes);
pkt->set_timestamp(0xffffffff);
memcpy(pkt->payload(), samples, n_bytes);
d_cs->send(s_response_usrp_rx_read, pmt_list3(PMT_NIL, PMT_T, v_pkt));
// Now lets check the shared CS queue between the TX and RX stub. Each
// element in a queue is a list where the first element is an invocation
// handle and the second element is a PMT u8 vect representation of the
// CS packet response which can just be passed transparently.
while(!d_cs_queue.empty()) {
pmt_t cs_pkt = d_cs_queue.front();
d_cs_queue.pop();
pmt_t invocation_handle = pmt_nth(0, cs_pkt);
pmt_t v_pkt = pmt_nth(1, cs_pkt);
d_cs->send(s_response_usrp_rx_read,
pmt_list3(invocation_handle,
PMT_T,
v_pkt)); // Take the front CS pkt
if(verbose)
std::cout << "[USRP_RX_STUB] Received CS response from TX stub\n";
}
}
REGISTER_MBLOCK_CLASS(usrp_rx_stub);

View File

@ -1,79 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,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.
*/
#ifndef INCLUDED_USRP_RX_STUB_H
#define INCLUDED_USRP_RX_STUB_H
#include <mblock/mblock.h>
#include <vector>
#include "usrp_standard.h"
#include <ui_nco.h>
#include <fstream>
#include <queue>
#include <usrp_inband_usb_packet.h>
typedef usrp_inband_usb_packet transport_pkt;
extern bool usrp_rx_stop_stub; // used to communicate a 'stop' to the RX stub
extern std::queue<pmt_t> d_cs_queue;
static pmt_t s_timeout = pmt_intern("%timeout");
static pmt_t s_done = pmt_intern("done");
/*!
* \brief Implements the low level usb interface to the USRP
*/
class usrp_rx_stub : public mb_mblock
{
public:
mb_port_sptr d_cs;
usrp_standard_rx* d_urx;
long d_samples_per_frame;
long d_decim_rx;
mb_time d_t0;
double d_delta_t;
// for generating sine wave output
ui_nco<float,float> d_nco;
double d_amplitude;
bool d_disk_write;
std::ofstream d_ofile;
public:
usrp_rx_stub(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
~usrp_rx_stub();
void initial_transition();
void handle_message(mb_message_sptr msg);
private:
void read_and_respond();
void read_data();
void start_packet_timer();
};
#endif /* INCLUDED_USRP_RX_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,131 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,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.
*/
#ifndef INCLUDED_USRP_SERVER_H
#define INCLUDED_USRP_SERVER_H
#include <mblock/mblock.h>
#include <vector>
#include <queue>
#include <fstream>
#include <usrp_inband_usb_packet.h>
typedef usrp_inband_usb_packet transport_pkt; // makes conversion to gigabit easy
/*!
* \brief Implements the lowest-level mblock usb_interface to the USRP
*/
class usrp_server : public mb_mblock
{
public:
// our ports
enum port_types {
RX_PORT = 0,
TX_PORT = 1
};
static const int N_PORTS = 4;
std::vector<mb_port_sptr> d_tx, d_rx;
mb_port_sptr d_cs;
mb_port_sptr d_cs_usrp;
static const int D_USB_CAPACITY = 32 * 1024 * 1024;
static const int D_MAX_CHANNELS = 16;
long d_ntx_chan;
long d_nrx_chan;
pmt_t d_usrp_dict;
bool d_fpga_debug;
long d_interp_tx;
long d_decim_rx;
// Keep track of the request IDs
struct rid_info {
pmt_t owner;
long user_rid;
rid_info() {
owner = PMT_NIL;
user_rid = 0;
}
};
static const long D_MAX_RID = 64;
std::vector<rid_info> d_rids;
struct channel_info {
long assigned_capacity; // the capacity currently assignedby the channel
pmt_t owner; // port ID of the owner of the channel
channel_info() {
assigned_capacity = 0;
owner = PMT_NIL;
}
};
long d_rx_chan_mask; // A bitmask representing the channels in the
// receiving state
std::vector<struct channel_info> d_chaninfo_tx;
std::vector<struct channel_info> d_chaninfo_rx;
std::queue<mb_message_sptr> d_defer_queue;
bool d_defer;
bool d_opened;
bool d_fake_rx;
public:
usrp_server(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
~usrp_server();
void initial_transition();
void handle_message(mb_message_sptr msg);
protected:
static int max_capacity() { return D_USB_CAPACITY; }
private:
void handle_cmd_allocate_channel(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data);
void handle_cmd_deallocate_channel(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data);
void handle_cmd_xmit_raw_frame(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data);
void handle_cmd_to_control_channel(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data);
void handle_cmd_start_recv_raw_samples(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data);
void handle_cmd_stop_recv_raw_samples(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data);
int rx_port_index(pmt_t port_id);
int tx_port_index(pmt_t port_id);
long current_capacity_allocation();
void recall_defer_queue();
void reset_channels();
void handle_response_usrp_read(pmt_t data);
bool check_valid(mb_port_sptr port, long channel, std::vector<struct channel_info> &chan_info, pmt_t signal_info);
void parse_control_pkt(pmt_t invocation_handle, transport_pkt *pkt);
long next_rid();
void initialize_registers();
void set_register(long reg, long val);
void read_register(long reg);
void check_register_initialization();
void reset_all_registers();
};
#endif /* INCLUDED_USRP_SERVER_H */

View File

@ -1,255 +0,0 @@
;; -*- scheme -*- ; not really, but tells emacs how to format this
;;
;; Copyright 2007 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.
;;
;; ----------------------------------------------------------------
;; This is an mblock header file
;;
;; The format is very much a work-in-progress.
;; It'll be compiled to C++.
;; ----------------------------------------------------------------
;; In the outgoing messages described below, invocation-handle is an
;; identifier provided by the client to tag the method invocation.
;; The identifier will be returned with the response, to provide the
;; client with a mechanism to match asynchronous responses with the
;; commands that generate them. The value of the invocation-handle is
;; opaque the the server, and is not required by the server to be
;; unique.
;;
;; In the incoming messages described below, invocation-handle is the
;; identifier provided by the client in the prompting invocation. The
;; identifier is returned with the response, so that the client has a
;; mechanism to match asynchronous responses with the commands that
;; generated them.
;;
;; status is either #t, indicating success, or a symbol indicating an error.
;; All symbol's names shall begin with %error-
;; ----------------------------------------------------------------
;; usrp-channel
;;
;; The protocol class is defined from the client's point-of-view.
;; (The client port is unconjugated, the server port is conjugated.)
(define-protocol-class usrp-channel
(:outgoing
(cmd-allocate-channel invocation-handle capacity-reservation)
;; The cmd-allocate-channel message requests that the server
;; allocates a logical channel in the FPGA for use.
;; capacity-reservation specifies the number of bytes/s of
;; interconnect capacity (USB or ethernet) to reserve for this
;; channel. (The reservation is just a sanity check, no OS
;; specific mechanism is used.)
(cmd-deallocate-channel invocation-handle channel)
;; The integer channel specifies the channel to deallocate.
)
(:incoming
(response-allocate-channel invocation-handle status channel)
;; If successful, a channel the specified capacity was allocated.
;; channel, an integer, indicates which channel was allocated.
(response-deallocate-channel invocation-handle status)
;; If successful, the specified channel and associated interconnect
;; capacity were deallocated.
)
)
;; ----------------------------------------------------------------
;; usrp-low-level-cs
;;
;; The protocol class is defined from the client's point-of-view.
;; (The client port is unconjugated, the server port is conjugated.)
;;
;; This defines a low level control and status interface to the usrp.
;; This will probably be replaced (or at least augmented) with a
;; higher level interface. For now, this will allow us to get on
;; the air.
;;
;; The subpackets are lists containing the relevant parameters. The
;; server will marshall them appropriately. Below is a list of
;; subpackets. See inband-signaling-usb for details. The opcodes are
;; symbols; unless otherwise indicated the remaining parameters are
;; integers. rid values are limited to 3-bits.
;;
;; (op-ping-fixed rid ping-value)
;; (op-ping-fixed-reply rid ping-value)
;; (op-write-reg reg-number reg-value)
;; (op-write-reg-masked reg-number reg-value mask-value)
;; (op-read-reg rid reg-number)
;; (op-read-reg-reply rid reg-number reg-value)
;; (op-i2c-write i2c-addr u8-vec)
;; (op-i2c-read rid i2c-addr nbytes)
;; (op-i2c-read-reply rid i2c-addr u8-vec)
;; (op-spi-write enables format opt-header-bytes u8-vec)
;; (op-spi-read rid enables format opt-header-bytes nbytes)
;; (op-spi-read-reply rid u8-vec)
;; (op-delay ticks)
(define-protocol-class usrp-low-level-cs
(:outgoing
(cmd-to-control-channel invocation-handle list-of-subpackets)
)
(:incoming
(response-from-control-channel invocation-handle status list-of-subpackets timestamp)
)
)
;; ----------------------------------------------------------------
;; usrp-tx
;;
;; The protocol class is defined from the client's point-of-view.
;; (The client port is unconjugated, the server port is conjugated.)
(define-protocol-class usrp-tx
(:include usrp-channel)
(:include usrp-low-level-cs)
(:outgoing
(cmd-xmit-raw-frame invocation-handle channel samples timestamp properties)
;; The argument channel must be an integer. It specifies the
;; channel on which the frame of samples will be be sent.
;;
;; samples must be a uniform numeric vector. The contents of the
;; sample vector is treated as opaque and is passed on to the FPGA
;; unmodified. It is the responsibility of the sender to ensure
;; that the binary format is sensible for the current FPGA
;; configuration.
;;
;; timestamp is a 32-bit integer that specifies the time at which
;; the first sample in samples shall be sent to the D/A converter.
;; The format and interpration of time is specified in the file
;; inband-signaling-usb
)
(:incoming
(response-xmit-raw-frame invocation-handle status)
;; If successful, the samples of the associated frame have been
;; transmitted to the USRP. This message may be used to implement
;; Tx flow control. The client could for example implement a
;; policy of never having more than 4 unacknowledged
;; cmd-xmit-raw-frame's outstanding.
)
)
;; ----------------------------------------------------------------
;; usrp-rx
;;
;; The protocol class is defined from the client's point-of-view.
;; (The client port is unconjugated, the server port is conjugated.)
(define-protocol-class usrp-rx
(:include usrp-channel)
(:include usrp-low-level-cs)
(:outgoing
(cmd-start-recv-raw-samples invocation-handle channel)
;; The argument channel must be an integer. It specifies the
;; channel from which frames of samples will be be received. The
;; server will return response-recv-raw-samples messages until a
;; cmd-stop-recv-raw-samples message is received.
(cmd-stop-recv-raw-samples invocation-handle channel)
;; The argument channel must be an integer. There is no reply to
;; this message.
)
(:incoming
(response-recv-raw-samples invocation-handle status samples timestamp channel properties)
;; samples is a uniform numeric vector. The contents of the sample
;; vector is treated as opaque and is passed from the FPGA
;; unmodified. It is the responsibility of the receiver to decode
;; the binary format as appropriate for the current FPGA
;; configuration.
;;
;; timestamp is a 32-bit integer that specifies the time at which
;; the first sample in samples was received from the A/D converter.
;; The format and interpretation of time is as specified in the
;; file inband-signaling-usb.
;;
;; properties is a dictionary containing additional (key, value)
;; pairs associated with the reception of these samples. In
;; particular, the map may contain the Received Signal Strength
;; Indication (RSSI) reported by the front end at the time the
;; first sample was received from the A/D.
)
)
;; ----------------------------------------------------------------
;; usrp-server-cs
;;
;; Control and status port for usrp-server
;;
;; The protocol class is defined from the client's point-of-view.
;; (The client port is unconjugated, the server port is conjugated.)
(define-protocol-class usrp-server-cs
(:outgoing
(cmd-open invocation-handle which-usrp)
(cmd-close invocation-handle)
(cmd-max-capacity invocation-handle)
(cmd-ntx-chan invocation-handle)
(cmd-nrx-chan invocation-handle)
(cmd-current-capacity-allocation invocation-handle)
)
(:incoming
(response-open invocation-handle status)
(response-close invocation-handle status)
(response-max-capacity invocation-handle status capacity)
(response-ntx-chan invocation-handle status ntx-chan)
(response-nrx-chan invocation-handle status nrx-chan)
(response-current-capacity-allocation invocation-handle status capacity)
)
)

View File

@ -1,150 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,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 <usrp_tx.h>
#include <iostream>
#include <usb.h>
#include <mblock/class_registry.h>
#include <usrp_inband_usb_packet.h>
#include <fpga_regs_common.h>
#include <usrp_standard.h>
#include <stdio.h>
#include <symbols_usrp_tx_cs.h>
typedef usrp_inband_usb_packet transport_pkt;
static const bool verbose = false;
usrp_tx::usrp_tx(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg)
: mb_mblock(rt, instance_name, user_arg),
d_disk_write(false)
{
d_cs = define_port("cs", "usrp-tx-cs", true, mb_port::EXTERNAL);
//d_disk_write=true;
if(d_disk_write) {
d_ofile.open("tx_data.dat",std::ios::binary|std::ios::out);
d_cs_ofile.open("tx_cs.dat",std::ios::binary|std::ios::out);
}
}
usrp_tx::~usrp_tx()
{
if(d_disk_write) {
d_ofile.close();
d_cs_ofile.close();
}
}
void
usrp_tx::initial_transition()
{
}
/*!
* \brief Handles incoming signals to to the m-block, wihch should only ever be
* a single message: cmd-usrp-tx-write.
*/
void
usrp_tx::handle_message(mb_message_sptr msg)
{
pmt_t event = msg->signal();
pmt_t port_id = msg->port_id();
pmt_t data = msg->data();
// Theoretically only have 1 message to ever expect, but
// want to make sure its at least what we want
if(pmt_eq(port_id, d_cs->port_symbol())) {
if(pmt_eqv(event, s_cmd_usrp_tx_write))
write(data);
}
}
/*!
* \brief Performs the actual writing of data to the USB bus, called by
* handle_message() when a cmd-usrp-tx-write signal is received.
*
* The \p data parameter is a PMT list which contains three mandatory elements,
* in the following order: an invocation handle, a channel, and a uniform vector
* of memory which contains the packets to be written to the bus.
*/
void
usrp_tx::write(pmt_t data)
{
pmt_t invocation_handle = pmt_nth(0, data);
pmt_t channel = pmt_nth(1, data);
pmt_t v_packets = pmt_nth(2, data);
d_utx = boost::any_cast<usrp_standard_tx_sptr>(pmt_any_ref(pmt_nth(3, data)));
size_t n_bytes;
bool underrun; // this will need to go, as it is taken care of in the packet headers
transport_pkt *pkts = (transport_pkt *) pmt_u8vector_writable_elements(v_packets, n_bytes);
int ret = d_utx->write (pkts, n_bytes, &underrun);
if (0 && underrun)
fprintf(stderr, "uU");
if (ret == (int) n_bytes) {
if (verbose)
std::cout << "[usrp_server] Write of " << n_bytes << " successful\n";
// need to respond with the channel so the USRP server knows who to forward the result of
// the write to by looking up the owner of the channel
d_cs->send(s_response_usrp_tx_write,
pmt_list3(invocation_handle, PMT_T, channel));
}
else {
if (verbose)
std::cout << "[usrp_server] Error writing " << n_bytes << " bytes to USB bus\n";
d_cs->send(s_response_usrp_tx_write,
pmt_list3(invocation_handle, PMT_F, channel));
}
long n_packets =
static_cast<long>(std::ceil(n_bytes / (double)transport_pkt::max_pkt_size()));
for(int i=0; i < n_packets; i++) {
if(d_disk_write) {
if(pkts[i].chan() == CONTROL_CHAN)
d_cs_ofile.write((const char *)&pkts[i], transport_pkt::max_pkt_size());
else
d_ofile.write((const char *)&pkts[i], transport_pkt::max_pkt_size());
d_cs_ofile.flush();
d_ofile.flush();
}
}
return;
}
REGISTER_MBLOCK_CLASS(usrp_tx);

View File

@ -1,52 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,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.
*/
#ifndef INCLUDED_USRP_TX_H
#define INCLUDED_USRP_TX_H
#include <mblock/mblock.h>
#include <fstream>
#include "usrp_standard.h"
/*!
* \brief Implements the low level usb interface to the USRP
*/
class usrp_tx : public mb_mblock
{
mb_port_sptr d_cs;
usrp_standard_tx_sptr d_utx;
bool d_disk_write;
std::ofstream d_ofile;
std::ofstream d_cs_ofile;
public:
usrp_tx(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
~usrp_tx();
void initial_transition();
void handle_message(mb_message_sptr msg);
private:
void write(pmt_t data);
};
#endif /* INCLUDED_USRP_TX_H */

View File

@ -1,344 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,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 <iostream>
#include <vector>
#include <usb.h>
#include <mblock/class_registry.h>
#include <usrp_tx_stub.h>
#include <usrp_inband_usb_packet.h>
#include <fpga_regs_common.h>
#include "usrp_standard.h"
#include <stdio.h>
#include <fstream>
#include <usrp_rx_stub.h>
#include <symbols_usrp_tx_cs.h>
typedef usrp_inband_usb_packet transport_pkt;
static const bool verbose = false;
usrp_tx_stub::usrp_tx_stub(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg)
: mb_mblock(rt, instance_name, user_arg),
d_disk_write(false)
{
d_cs = define_port("cs", "usrp-tx-cs", true, mb_port::EXTERNAL);
//d_disk_write=true;
if(d_disk_write) {
d_ofile.open("tx_stub_data.dat",std::ios::binary|std::ios::out);
d_cs_ofile.open("tx_stub_cs.dat",std::ios::binary|std::ios::out);
}
}
usrp_tx_stub::~usrp_tx_stub()
{
if(d_disk_write) {
d_ofile.close();
d_cs_ofile.close();
}
}
void
usrp_tx_stub::initial_transition()
{
}
void
usrp_tx_stub::handle_message(mb_message_sptr msg)
{
pmt_t event = msg->signal();
pmt_t port_id = msg->port_id();
pmt_t data = msg->data();
// Theoretically only have 1 message to ever expect, but
// want to make sure its at least what we want
if(pmt_eq(port_id, d_cs->port_symbol())) {
if(pmt_eqv(event, s_cmd_usrp_tx_write))
write(data);
}
}
void
usrp_tx_stub::write(pmt_t data)
{
pmt_t invocation_handle = pmt_nth(0, data);
pmt_t channel = pmt_nth(1, data);
pmt_t v_packets = pmt_nth(2, data);
d_utx = boost::any_cast<usrp_standard_tx *>(pmt_any_ref(pmt_nth(3, data)));
size_t n_bytes;
transport_pkt *pkts = (transport_pkt *) pmt_u8vector_writable_elements(v_packets, n_bytes);
long n_packets = static_cast<long>(std::ceil(n_bytes / (double)transport_pkt::max_pkt_size()));
// Parse the packets looking for C/S packets and dump them to a disk if
// necessary
for(long i=0; i<n_packets; i++) {
if(d_disk_write) {
if(pkts[i].chan() == CONTROL_CHAN)
d_cs_ofile.write((const char *)&pkts[i], transport_pkt::max_pkt_size());
else
d_ofile.write((const char *)&pkts[i], transport_pkt::max_pkt_size());
d_cs_ofile.flush();
d_ofile.flush();
}
if(pkts[i].chan() == CONTROL_CHAN)
parse_cs(invocation_handle, pkts[i]);
}
d_cs->send(s_response_usrp_tx_write,
pmt_list3(invocation_handle, PMT_T, channel));
return;
}
void
usrp_tx_stub::parse_cs(pmt_t invocation_handle, transport_pkt pkt)
{
long payload_len = pkt.payload_len();
long curr_payload = 0;
size_t ignore;
// There is the possibility that the responses for a single USB packet full of
// CS packets will not fit back in a single USB packet, considering some
// responses are greater than their commands (read registers).
new_packet:
pmt_t v_pkt = pmt_make_u8vector(sizeof(transport_pkt), 0);
transport_pkt *q_pkt =
(transport_pkt *) pmt_u8vector_writable_elements(v_pkt, ignore);
q_pkt->set_header(0, CONTROL_CHAN, 0, 0);
q_pkt->set_timestamp(0xffffffff);
// We dispatch based on the control packet type, however we can extract the
// opcode and the length immediately which is consistent in all responses.
//
// Since each control packet can have multiple responses, we keep reading the
// lengths of each subpacket until we reach the payload length.
while(curr_payload < payload_len) {
pmt_t sub_packet = pkt.read_subpacket(curr_payload);
pmt_t op_symbol = pmt_nth(0, sub_packet);
int len = pkt.cs_len(curr_payload);
if(verbose)
std::cout << "[USRP_TX_STUB] Parsing subpacket "
<< op_symbol << " ... length " << len << std::endl;
//----------------- PING FIXED ------------------//
if(pmt_eq(op_symbol, s_op_ping_fixed)) {
long rid = pmt_to_long(pmt_nth(1, sub_packet));
long pingval = pmt_to_long(pmt_nth(2, sub_packet));
// Generate a reply and put it in the queue for the RX stub to read
if(!q_pkt->cs_ping_reply(rid, pingval))
goto new_packet;
if(verbose)
std::cout << "[USRP_TX_STUB] Generated ping response "
<< "("
<< "RID: " << rid << ", "
<< "VAL: " << pingval
<< ")\n";
}
//----------------- READ REG ------------------//
if(pmt_eq(op_symbol, s_op_read_reg)) {
long rid = pmt_to_long(pmt_nth(1, sub_packet));
long reg_num = pmt_to_long(pmt_nth(2, sub_packet));
long reg_val = 0xdeef;
// Generate a reply and put it in the queue for the RX stub to read
if(!q_pkt->cs_read_reg_reply(rid, reg_num, reg_val))
goto new_packet;
if(verbose)
std::cout << "[USRP_TX_STUB] Generated read register response "
<< "("
<< "RID: " << rid << ", "
<< "REG: " << reg_num << ", "
<< "VAL: " << reg_val
<< ")\n";
}
//----------------- DELAY ------------------//
if(pmt_eq(op_symbol, s_op_delay)) {
long ticks = pmt_to_long(pmt_nth(1, sub_packet));
if(verbose)
std::cout << "[USRP_TX_STUB] Received delay command "
<< "("
<< "Ticks: " << ticks
<< ")\n";
}
//----------------- WRITE REG ------------------//
if(pmt_eq(op_symbol, s_op_write_reg)) {
pmt_t reg_num = pmt_nth(1, sub_packet);
pmt_t reg_val = pmt_nth(2, sub_packet);
if(verbose)
std::cout << "[USRP_TX_STUB] Received write register command "
<< "("
<< "RegNum: " << reg_num << ", "
<< "Val: " << reg_val
<< ")\n";
}
//----------------- WRITE REG MASK ---------------//
if(pmt_eq(op_symbol, s_op_write_reg_masked)) {
pmt_t reg_num = pmt_nth(1, sub_packet);
pmt_t reg_val = pmt_nth(2, sub_packet);
pmt_t mask = pmt_nth(3, sub_packet);
if(verbose)
std::cout << "[USRP_TX_STUB] Received write register command "
<< "("
<< "RegNum: " << reg_num << ", "
<< "Val: " << reg_val << ", "
<< "Mask: " << mask
<< ")\n";
}
//---------------- I2C WRITE ------------------//
if(pmt_eq(op_symbol, s_op_i2c_write)) {
pmt_t i2c_addr = pmt_nth(1, sub_packet);
pmt_t i2c_data = pmt_nth(2, sub_packet);
if(verbose)
std::cout << "[USRP_TX_STUB] Received i2c write command "
<< "("
<< "Addr: " << i2c_addr << ", "
<< "Data: " << i2c_data
<< ")\n";
}
//---------------- I2C READ ------------------//
if(pmt_eq(op_symbol, s_op_i2c_read)) {
long rid = pmt_to_long(pmt_nth(1, sub_packet));
long i2c_addr = pmt_to_long(pmt_nth(2, sub_packet));
long i2c_bytes = pmt_to_long(pmt_nth(3, sub_packet));
// Create data to place as a response, filled with 0xff
size_t ignore;
pmt_t i2c_data = pmt_make_u8vector(i2c_bytes, 0xff);
uint8_t *w_data = (uint8_t *) pmt_u8vector_writable_elements(i2c_data, ignore);
// Generate a reply and put it in the queue for the RX stub to read
if(!q_pkt->cs_i2c_read_reply(rid, i2c_addr, w_data, i2c_bytes))
goto new_packet;
if(verbose)
std::cout << "[USRP_TX_STUB] Received i2c read "
<< "("
<< "RID: " << rid << ", "
<< "Addr: " << i2c_addr << ", "
<< "Bytes: " << i2c_bytes
<< ")\n";
}
//---------------- SPI WRITE ------------------//
if(pmt_eq(op_symbol, s_op_spi_write)) {
long enables = pmt_to_long(pmt_nth(1, sub_packet));
long format = pmt_to_long(pmt_nth(2, sub_packet));
long opt = pmt_to_long(pmt_nth(3, sub_packet));
pmt_t data = pmt_nth(4, sub_packet);
if(verbose)
std::cout << "[USRP_TX_STUB] Received spi write command "
<< "("
<< "Enables: " << enables << ", "
<< "Format: " << format << ", "
<< "Options: " << opt << ", "
<< "Data: " << data
<< ")\n";
}
//---------------- SPI READ ------------------//
if(pmt_eq(op_symbol, s_op_spi_read)) {
long rid = pmt_to_long(pmt_nth(1, sub_packet));
long enables = pmt_to_long(pmt_nth(2, sub_packet));
long format = pmt_to_long(pmt_nth(3, sub_packet));
long opt = pmt_to_long(pmt_nth(4, sub_packet));
long n_bytes = pmt_to_long(pmt_nth(5, sub_packet));
// Create data to place as a fake response
size_t ignore;
pmt_t spi_data = pmt_make_u8vector(n_bytes, 0xff);
uint8_t *w_data = (uint8_t *) pmt_u8vector_writable_elements(spi_data, ignore);
// Generate a reply and put it in the queue for the RX stub to read
if(!q_pkt->cs_spi_read_reply(rid, w_data, n_bytes))
goto new_packet;
if(verbose)
std::cout << "[USRP_TX_STUB] Received spi read command "
<< "("
<< "RID: " << rid << ", "
<< "Enables: " << enables << ", "
<< "Format: " << format << ", "
<< "Options: " << opt << ", "
<< "Bytes: " << n_bytes
<< ")\n";
}
// Each subpacket has an unaccounted for 2 bytes which is the opcode
// and the length field
curr_payload += len + 2;
// All subpackets are 32-bit aligned
int align_offset = 4 - (curr_payload % 4);
if(align_offset != 4)
curr_payload += align_offset;
}
// If the packet has data in the payload, it needs queued
if(q_pkt->payload_len() > 0)
d_cs_queue.push(pmt_list2(invocation_handle, v_pkt));
return;
}
REGISTER_MBLOCK_CLASS(usrp_tx_stub);

View File

@ -1,61 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,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.
*/
#ifndef INCLUDED_USRP_TX_STUB_H
#define INCLUDED_USRP_TX_STUB_H
#include <mblock/mblock.h>
#include <vector>
#include "usrp_standard.h"
#include <fstream>
#include <usrp_inband_usb_packet.h>
typedef usrp_inband_usb_packet transport_pkt;
/*!
* \brief Implements the low level usb interface to the USRP
*/
class usrp_tx_stub : public mb_mblock
{
public:
mb_port_sptr d_cs;
usrp_standard_tx* d_utx;
std::ofstream d_ofile;
std::ofstream d_cs_ofile;
bool d_disk_write;
public:
usrp_tx_stub(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
~usrp_tx_stub();
void initial_transition();
void handle_message(mb_message_sptr msg);
private:
void write(pmt_t data);
void parse_cs(pmt_t invocation_handle, transport_pkt pkt);
};
#endif /* INCLUDED_USRP_TX_STUB_H */

View File

@ -1,601 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,2008,2009 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 <usrp_usb_interface.h>
#include <iostream>
#include <vector>
#include <usb.h>
#include <mblock/class_registry.h>
#include <usrp_inband_usb_packet.h>
#include <fpga_regs_common.h>
#include "usrp_rx.h"
#include <usrp_rx_stub.h>
#include "usrp_tx.h"
#include "usrp_standard.h"
#include <stdio.h>
#include <usrp_dbid.h>
typedef usrp_inband_usb_packet transport_pkt;
#include <symbols_usrp_interface_cs.h>
#include <symbols_usrp_tx_cs.h>
#include <symbols_usrp_rx_cs.h>
static pmt_t s_shutdown = pmt_intern("%shutdown");
static const bool verbose = false;
/*!
* \brief Initializes the USB interface m-block.
*
* The \p user_arg should be a PMT dictionary which can contain optional
* arguments for the block, such as the decimatoin and interpolation rate.
*/
usrp_usb_interface::usrp_usb_interface(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg)
: mb_mblock(rt, instance_name, user_arg),
d_fake_usrp(false),
d_rx_reading(false),
d_interp_tx(128),
d_decim_rx(128),
d_rf_freq(-1),
d_rbf("inband_tx_rx.rbf")
{
// Dictionary for arguments to all of the components
pmt_t usrp_dict = user_arg;
// Default TX/RX interface
std::string tx_interface = "usrp_tx";
std::string rx_interface = "usrp_rx";
if (pmt_is_dict(usrp_dict)) {
// The 'fake-usrp' key enables the TX and RX stubs if PMT_T
if(pmt_t fake_usrp = pmt_dict_ref(usrp_dict,
pmt_intern("fake-usrp"),
PMT_NIL)) {
if(pmt_eqv(fake_usrp, PMT_T)) {
tx_interface = "usrp_tx_stub";
rx_interface = "usrp_rx_stub";
d_fake_usrp=true;
}
}
// Read the TX interpolations
if(pmt_t interp_tx = pmt_dict_ref(usrp_dict,
pmt_intern("interp-tx"),
PMT_NIL)) {
if(!pmt_eqv(interp_tx, PMT_NIL))
d_interp_tx = pmt_to_long(interp_tx);
}
// Read the RX decimation rate
if(pmt_t decim_rx = pmt_dict_ref(usrp_dict,
pmt_intern("decim-rx"),
PMT_NIL)) {
if(!pmt_eqv(decim_rx, PMT_NIL))
d_decim_rx = pmt_to_long(decim_rx);
}
// Read the RBF
if(pmt_t rbf = pmt_dict_ref(usrp_dict,
pmt_intern("rbf"),
PMT_NIL)) {
if(!pmt_eqv(rbf, PMT_NIL))
d_rbf = pmt_symbol_to_string(rbf);
}
// The RF center frequency
if(pmt_t rf_freq = pmt_dict_ref(usrp_dict,
pmt_intern("rf-freq"),
PMT_NIL)) {
if(!pmt_eqv(rf_freq, PMT_NIL))
d_rf_freq = pmt_to_double(rf_freq);
}
}
if (verbose) {
std::cout << "[USRP_USB_INTERFACE] Setting USRP RBF to "
<< d_rbf << std::endl;
std::cout << "[USRP_USB_INTERFACE] Setting TX interpolation to "
<< d_interp_tx << std::endl;
std::cout << "[USRP_USB_INTERFACE] Setting RX interpolation to "
<< d_decim_rx << std::endl;
std::cout << "[USRP_USB_INTERFACE] Using TX interface: "
<< tx_interface << "\n";
std::cout << "[USRP_USB_INTERFACE] Using RX interface: "
<< rx_interface << "\n";
}
d_cs = define_port("cs", "usrp-interface-cs", true, mb_port::EXTERNAL);
d_rx_cs = define_port("rx_cs", "usrp-rx-cs", false, mb_port::INTERNAL);
d_tx_cs = define_port("tx_cs", "usrp-tx-cs", false, mb_port::INTERNAL);
// Connect to TX and RX
define_component("tx", tx_interface, usrp_dict);
define_component("rx", rx_interface, usrp_dict);
connect("self", "rx_cs", "rx", "cs");
connect("self", "tx_cs", "tx", "cs");
// FIXME: the code should query the FPGA to retrieve the number of channels and such
d_ntx_chan = 2;
d_nrx_chan = 2;
}
usrp_usb_interface::~usrp_usb_interface()
{
}
void
usrp_usb_interface::initial_transition()
{
}
/*!
* \brief Handles all incoming signals to the block from the lowest m-blocks
* which read/write to the bus, or the higher m-block which is the USRP server.
*/
void
usrp_usb_interface::handle_message(mb_message_sptr msg)
{
pmt_t event = msg->signal(); // the "name" of the message
pmt_t port_id = msg->port_id(); // which port it came in on
pmt_t data = msg->data();
pmt_t invocation_handle;
if (pmt_eq(event, s_shutdown)) // ignore (for now)
return;
//------------- CONTROL / STATUS -------------//
if (pmt_eq(port_id, d_cs->port_symbol())) {
//------------ OPEN --------------//
if (pmt_eq(event, s_cmd_usrp_open)){
handle_cmd_open(data);
return;
}
//----------- CLOSE -------------//
else if (pmt_eq(event, s_cmd_usrp_close)) {
handle_cmd_close(data);
return;
}
//---------- NTX CHAN ----------//
else if (pmt_eq(event, s_cmd_usrp_ntx_chan)) {
invocation_handle = pmt_nth(0, data);
d_cs->send(s_response_usrp_ntx_chan,
pmt_list2(invocation_handle,
pmt_from_long(d_ntx_chan)));
return;
}
//---------- NRX CHAN ----------//
else if (pmt_eq(event, s_cmd_usrp_nrx_chan)) {
invocation_handle = pmt_nth(0, data);
d_cs->send(s_response_usrp_nrx_chan,
pmt_list2(invocation_handle,
pmt_from_long(d_nrx_chan)));
return;
}
//------------ WRITE -----------//
else if(pmt_eq(event, s_cmd_usrp_write)) {
handle_cmd_write(data);
return;
}
//-------- START READING --------//
else if(pmt_eq(event, s_cmd_usrp_start_reading)) {
handle_cmd_start_reading(data);
return;
}
//-------- STOP READING --------//
else if(pmt_eq(event, s_cmd_usrp_stop_reading)) {
handle_cmd_stop_reading(data);
return;
}
goto unhandled;
}
//---------------- RX ------------------//
if (pmt_eq(port_id, d_rx_cs->port_symbol())) {
// Relay reads back up
if(pmt_eq(event, s_response_usrp_rx_read)) {
d_cs->send(s_response_usrp_read, data);
return;
}
goto unhandled;
}
//---------------- TX ------------------//
if (pmt_eq(port_id, d_tx_cs->port_symbol())) {
if(pmt_eq(event, s_response_usrp_tx_write)) {
pmt_t invocation_handle = pmt_nth(0, data);
pmt_t status = pmt_nth(1, data);
pmt_t channel = pmt_nth(2, data);
d_cs->send(s_response_usrp_write,
pmt_list3(invocation_handle,
status,
channel));
return;
}
goto unhandled;
}
unhandled:
std::cout << "[USRP_USB_INTERFACE] unhandled msg: " << msg << std::endl;
}
/*!
* \brief Called by the handle_message() method when the incoming signal is to
* open a USB connection to the USRP (cmd-usrp-open).
*
* The \p data parameter is a PMT list, where the elements are an invocation
* handle and the USRP number.
*/
void
usrp_usb_interface::handle_cmd_open(pmt_t data)
{
pmt_t invocation_handle = pmt_nth(0, data);
long which_usrp = pmt_to_long(pmt_nth(1, data));
pmt_t reply_data;
if(d_fake_usrp) {
d_cs->send(s_response_usrp_open, pmt_list2(invocation_handle, PMT_T));
return;
}
if (verbose)
std::cout << "[USRP_USB_INTERFACE] Handling open request for USRP " << which_usrp << "\n";
// Open up a standard RX and TX for communication with the USRP
d_utx = usrp_standard_tx::make(which_usrp,
d_interp_tx,
1, // 1 channel
-1, // mux
4096, // USB block size
16, // nblocks for async transfers
d_rbf
);
if(d_utx==0) {
if (verbose)
std::cout << "[USRP_USB_INTERFACE] Failed to open TX\n";
reply_data = pmt_list2(invocation_handle, PMT_F);
d_cs->send(s_response_usrp_open, reply_data);
return;
}
// Perform TX daughterboard tuning
double target_freq;
unsigned int mux;
int tgain, rgain;
float input_rate;
bool ok;
usrp_tune_result r;
// Cast to usrp_basic and then detect daughterboards
d_ub_tx = d_utx;
usrp_subdev_spec tspec = pick_tx_subdevice();
db_base_sptr tsubdev = d_ub_tx->selected_subdev(tspec);
// Set the TX mux value
mux = d_utx->determine_tx_mux_value(tspec);
d_utx->set_mux(mux);
// Set the TX gain and determine rate
tgain = tsubdev->gain_max();
tsubdev->set_gain(tgain);
input_rate = d_ub_tx->converter_rate() / d_utx->interp_rate();
// Perform the actual tuning, if no frequency specified then pick
if(d_rf_freq==-1)
target_freq = tsubdev->freq_min()+((tsubdev->freq_max()-tsubdev->freq_min())/2.0);
else
target_freq = d_rf_freq;
ok = d_utx->tune(tsubdev->which(), tsubdev, target_freq, &r);
tsubdev->set_enable(true);
if(verbose) {
printf("TX Subdevice name is %s\n", tsubdev->name().c_str());
printf("TX Subdevice freq range: (%g, %g)\n",
tsubdev->freq_min(), tsubdev->freq_max());
printf("mux: %#08x\n", mux);
printf("target_freq: %f\n", target_freq);
printf("ok: %s\n", ok ? "true" : "false");
printf("gain: %d\n", tgain);
printf("r.baseband_freq: %f\n", r.baseband_freq);
printf("r.dxc_freq: %f\n", r.dxc_freq);
printf("r.residual_freq: %f\n", r.residual_freq);
printf("r.inverted: %d\n", r.inverted);
}
if(!ok) {
std::cerr << "[USRP_USB_INTERFACE] Failed to set center frequency on TX\n";
reply_data = pmt_list2(invocation_handle, PMT_F);
d_cs->send(s_response_usrp_open, reply_data);
return;
}
d_utx->start();
if (verbose)
std::cout << "[USRP_USB_INTERFACE] Setup TX channel\n";
d_urx =
usrp_standard_rx::make (which_usrp,
d_decim_rx,
1, // nchan
-1, // mux
0, // set blank mode to start
4096, // USB block size
16, // number of blocks for async transfers
d_rbf);
if(!d_urx) {
if (verbose)
std::cout << "[usrp_server] Failed to open RX\n";
reply_data = pmt_list2(invocation_handle, PMT_F);
d_cs->send(s_response_usrp_open, reply_data);
return;
}
// Cast to usrp_basic and then detect daughterboards
d_ub_rx = d_urx;
usrp_subdev_spec rspec = pick_rx_subdevice();
db_base_sptr rsubdev = d_ub_rx->selected_subdev(rspec);
// Set the RX mux value
mux = d_urx->determine_rx_mux_value(rspec);
d_urx->set_mux(mux);
// Set the RX gain and determine rate
rgain = rsubdev->gain_max()/2.0;
rsubdev->set_gain(rgain);
input_rate = d_ub_rx->converter_rate() / d_urx->decim_rate();
ok = d_urx->tune(rsubdev->which(), rsubdev, target_freq, &r);
rsubdev->set_enable(true);
if(verbose) {
printf("RX Subdevice name is %s\n", rsubdev->name().c_str());
printf("RX Subdevice freq range: (%g, %g)\n",
rsubdev->freq_min(), rsubdev->freq_max());
printf("mux: %#08x\n", mux);
printf("target_freq: %f\n", target_freq);
printf("ok: %s\n", ok ? "true" : "false");
printf("gain: %d\n", rgain);
printf("r.baseband_freq: %f\n", r.baseband_freq);
printf("r.dxc_freq: %f\n", r.dxc_freq);
printf("r.residual_freq: %f\n", r.residual_freq);
printf("r.inverted: %d\n", r.inverted);
}
if(!ok) {
std::cerr << "[USRP_USB_INTERFACE] Failed to set center frequency on RX\n";
reply_data = pmt_list2(invocation_handle, PMT_F);
d_cs->send(s_response_usrp_open, reply_data);
return;
}
if (verbose)
std::cout << "[USRP_USB_INTERFACE] Setup RX channel\n";
// d_utx->_write_fpga_reg(FR_DEBUG_EN,0xf);
// d_utx->_write_oe(0, 0xffff, 0xffff);
// d_urx->_write_oe(0, 0xffff, 0xffff);
// d_utx->_write_oe(1, 0xffff, 0xffff);
// d_urx->_write_oe(1, 0xffff, 0xffff);
d_cs->send(s_response_usrp_open, pmt_list2(invocation_handle, PMT_T));
}
/*!
* \brief Called by the handle_message() method when the incoming signal is to
* write data to the USB bus (cmd-usrp-write).
*
* The \p data parameter is a PMT list containing 3 mandatory elements in the
* following order: an invocation handle, channel, and a uniform vector
* representation of the packets.
*/
void
usrp_usb_interface::handle_cmd_write(pmt_t data)
{
pmt_t invocation_handle = pmt_nth(0, data);
pmt_t channel = pmt_nth(1, data);
pmt_t pkts = pmt_nth(2, data);
pmt_t tx_handle = pmt_make_any(d_utx);
d_tx_cs->send(s_cmd_usrp_tx_write,
pmt_list4(invocation_handle,
channel,
pkts,
tx_handle));
}
/*!
* \brief Called by the handle_message() method when the incoming signal is to
* start reading data from the USB bus (cmd-usrp-start-reading).
*
* The \p data parameter is a PMT list with a single element: an invocation
* handle which can be returned with the response.
*/
void
usrp_usb_interface::handle_cmd_start_reading(pmt_t data)
{
pmt_t invocation_handle = pmt_nth(0, data);
if(verbose)
std::cout << "[USRP_USB_INTERFACE] Starting RX...\n";
if(!d_fake_usrp)
d_urx->start();
pmt_t rx_handle = pmt_make_any(d_urx);
d_rx_cs->send(s_cmd_usrp_rx_start_reading, pmt_list2(PMT_NIL, rx_handle));
d_rx_reading = true;
return;
}
/*!
* \brief Called by the handle_message() method when the incoming signal is to
* stop reading data from the USB bus (cmd-usrp-stop-reading).
*
* The \p data parameter is a PMT list with a single element: an invocation
* handle which can be returned with the response.
*/
void
usrp_usb_interface::handle_cmd_stop_reading(pmt_t data)
{
pmt_t invocation_handle = pmt_nth(0, data);
if(!d_fake_usrp) {
if(verbose)
std::cout << "[USRP_USB_INTERFACE] Stopping RX...\n";
usrp_rx_stop = true;
// Used to allow a read() being called by a lower layer to complete before
// stopping, else there can be partial data left on the bus and can generate
// errors.
while(usrp_rx_stop) {usleep(1);}
d_urx->stop();
}
else {
if(verbose)
std::cout << "[USRP_USB_INTERFACE] Stopping fake RX...\n";
usrp_rx_stop_stub = true; // extern to communicate with stub to wait
}
d_rx_reading = false;
return;
}
/*!
* \brief Called by the handle_message() method when the incoming signal is to
* close the USB connection to the USRP.
*
* The \p data parameter is a PMT list with a single element: an invocation
* handle which can be returned with the response.
*/
void
usrp_usb_interface::handle_cmd_close(pmt_t data)
{
pmt_t invocation_handle = pmt_nth(0, data);
if(d_rx_reading)
handle_cmd_stop_reading(PMT_NIL);
if(d_fake_usrp) {
d_cs->send(s_response_usrp_close, pmt_list2(invocation_handle, PMT_T));
return;
}
if (verbose)
std::cout << "[USRP_USB_INTERFACE] Handling close request for USRP\n";
d_utx.reset();
d_urx.reset();
d_cs->send(s_response_usrp_close, pmt_list2(invocation_handle, PMT_T));
// FIXME This seems like a _very_ strange place to be calling shutdown_all.
// That decision should be left to high-level code, not low-level code like this.
shutdown_all(PMT_T);
}
usrp_subdev_spec
usrp_usb_interface::pick_rx_subdevice()
{
int dbids[] = {
USRP_DBID_FLEX_400_RX,
USRP_DBID_FLEX_900_RX,
USRP_DBID_FLEX_1200_RX,
USRP_DBID_FLEX_2400_RX,
USRP_DBID_TV_RX,
USRP_DBID_TV_RX_REV_2,
USRP_DBID_DBS_RX,
USRP_DBID_BASIC_RX
};
std::vector<int> candidates(dbids, dbids+(sizeof(dbids)/sizeof(int)));
return pick_subdev(d_ub_rx, candidates);
}
usrp_subdev_spec
usrp_usb_interface::pick_tx_subdevice()
{
int dbids[] = {
USRP_DBID_FLEX_400_TX,
USRP_DBID_FLEX_900_TX,
USRP_DBID_FLEX_1200_TX,
USRP_DBID_FLEX_2400_TX,
USRP_DBID_BASIC_TX
};
std::vector<int> candidates(dbids, dbids+(sizeof(dbids)/sizeof(int)));
return pick_subdev(d_ub_tx, candidates);
}
usrp_subdev_spec
usrp_usb_interface::pick_subdev(boost::shared_ptr<usrp_basic> d_usrp_basic, std::vector<int> candidates)
{
int dbid0 = d_usrp_basic->selected_subdev(usrp_subdev_spec(0, 0))->dbid();
int dbid1 = d_usrp_basic->selected_subdev(usrp_subdev_spec(1, 0))->dbid();
for (int i = 0; i < candidates.size(); i++) {
int dbid = candidates[i];
if (dbid0 == dbid)
return usrp_subdev_spec(0, 0);
if (dbid1 == dbid)
return usrp_subdev_spec(1, 0);
}
if (dbid0 >= 0)
return usrp_subdev_spec(0, 0);
if (dbid1 >= 0)
return usrp_subdev_spec(1, 0);
throw std::runtime_error("No suitable daughterboard found!");
}
REGISTER_MBLOCK_CLASS(usrp_usb_interface);

View File

@ -1,78 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,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.
*/
#ifndef INCLUDED_USRP_USB_INTERFACE_H
#define INCLUDED_USRP_USB_INTERFACE_H
#include <mblock/mblock.h>
#include <vector>
#include "usrp_standard.h"
/*!
* \brief Implements the low level usb interface to the USRP
*/
class usrp_usb_interface : public mb_mblock
{
public:
usrp_standard_tx_sptr d_utx;
usrp_standard_rx_sptr d_urx;
boost::shared_ptr<usrp_basic> d_ub_tx;
boost::shared_ptr<usrp_basic> d_ub_rx;
mb_port_sptr d_cs;
mb_port_sptr d_rx_cs;
mb_port_sptr d_tx_cs;
long d_ntx_chan;
long d_nrx_chan;
bool d_fake_usrp;
bool d_rx_reading;
long d_interp_tx;
long d_decim_rx;
double d_rf_freq;
std::string d_rbf;
public:
usrp_usb_interface(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
~usrp_usb_interface();
void initial_transition();
void handle_message(mb_message_sptr msg);
usrp_subdev_spec pick_rx_subdevice();
usrp_subdev_spec pick_tx_subdevice();
usrp_subdev_spec pick_subdev(boost::shared_ptr<usrp_basic> d_usrp_basic, std::vector<int> candidates);
private:
void handle_cmd_open(pmt_t data);
void handle_cmd_close(pmt_t data);
void handle_cmd_write(pmt_t data);
void handle_cmd_start_reading(pmt_t data);
void handle_cmd_stop_reading(pmt_t data);
};
#endif /* INCLUDED_USRP_USB_INTERFACE_H */

View File

@ -5,7 +5,7 @@ includedir=@includedir@
Name: usrp
Description: USRP Client Side C++ interface
Requires: @LIBUSB_PKG_CONFIG_NAME@ @usrp_darwin_omnithread_pc_requires@
Requires: @LIBUSB_PKG_CONFIG_NAME@
Version: @VERSION@
Libs: -L${libdir} -lusrp
Cflags: -I${includedir}