mirror of https://gerrit.osmocom.org/libusrp
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:
commit
fa46b23ddb
|
@ -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/
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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 ();
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -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); };
|
||||
};
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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_ */
|
|
@ -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
|
|
@ -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)
|
|
@ -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();
|
||||
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
|
@ -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);
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
|
@ -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 */
|
||||
|
|
@ -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
|
|
@ -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 */
|
|
@ -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
|
|
@ -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
|
|
@ -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()
|
|
@ -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"))
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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);
|
||||
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
|
@ -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
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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
|
||||
)
|
||||
)
|
|
@ -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);
|
|
@ -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 */
|
||||
|
|
@ -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);
|
|
@ -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
|
@ -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 */
|
|
@ -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)
|
||||
)
|
||||
)
|
|
@ -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);
|
|
@ -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 */
|
||||
|
|
@ -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);
|
|
@ -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 */
|
||||
|
|
@ -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);
|
|
@ -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 */
|
|
@ -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}
|
||||
|
|
Loading…
Reference in New Issue