Remove mblock library. We hardly knew 'ye.

This commit is contained in:
Johnathan Corgan 2010-04-26 22:41:19 -07:00
parent 6ef29ec6b2
commit 1815e30065
51 changed files with 0 additions and 12328 deletions

View File

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

View File

@ -1,77 +0,0 @@
#
# Copyright 2003,2006,2008 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# GNU Radio is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
#
include $(top_srcdir)/Makefile.common
AM_CPPFLAGS = \
$(DEFINES) $(OMNITHREAD_INCLUDES) $(PMT_INCLUDES) $(MBLOCK_INCLUDES) \
$(USRP_INCLUDES) $(USRP_INBAND_INCLUDES) $(BOOST_CPPFLAGS) \
$(CPPUNIT_INCLUDES) $(WITH_INCLUDES) -I$(top_srcdir)/mblock/src/lib
bin_PROGRAMS =
noinst_PROGRAMS = \
test_usrp_inband_ping \
test_usrp_inband_registers \
test_usrp_inband_rx \
test_usrp_inband_2rx \
test_usrp_inband_tx \
test_usrp_inband_2tx \
test_usrp_inband_timestamps \
test_usrp_inband_overrun \
test_usrp_inband_underrun \
read_packets
noinst_HEADERS = \
ui_nco.h \
ui_sincos.h
test_usrp_inband_ping_SOURCES = test_usrp_inband_ping.cc
test_usrp_inband_ping_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
test_usrp_inband_tx_SOURCES = test_usrp_inband_tx.cc ui_sincos.c
test_usrp_inband_tx_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
test_usrp_inband_2tx_SOURCES = test_usrp_inband_2tx.cc ui_sincos.c
test_usrp_inband_2tx_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
test_usrp_inband_timestamps_SOURCES = test_usrp_inband_timestamps.cc ui_sincos.c
test_usrp_inband_timestamps_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
test_usrp_inband_registers_SOURCES = test_usrp_inband_registers.cc ui_sincos.c
test_usrp_inband_registers_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
test_usrp_inband_overrun_SOURCES = test_usrp_inband_overrun.cc
test_usrp_inband_overrun_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
test_usrp_inband_underrun_SOURCES = test_usrp_inband_underrun.cc
test_usrp_inband_underrun_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
test_usrp_inband_rx_SOURCES = test_usrp_inband_rx.cc ui_sincos.c
test_usrp_inband_rx_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
test_usrp_inband_2rx_SOURCES = test_usrp_inband_2rx.cc ui_sincos.c
test_usrp_inband_2rx_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
read_packets_SOURCES = read_packets.cc
read_packets_LDADD = $(USRP_LA) $(USRP_INBAND_LA)

View File

@ -1,109 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,2008 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <iostream>
#include <usrp_inband_usb_packet.h>
#include <mblock/class_registry.h>
#include <vector>
#include <usrp_usb_interface.h>
#include <fstream>
typedef usrp_inband_usb_packet transport_pkt; // makes conversion to gigabit easy
int main(int argc, char *argv[]) {
if(argc !=2) {
std::cout << "Usage: ./read_packets <data_file>\n";
return -1;
}
std::ifstream infile;
std::ofstream outfile;
unsigned int pkt_size = transport_pkt::max_pkt_size();
unsigned int pkt_num=0;
transport_pkt *pkt;
char pkt_data[pkt_size]; // allocate the number of bytes for a single packet
pkt = (transport_pkt *)pkt_data; // makes operations cleaner to read
// Open the file and read the packets, dumping information
infile.open(argv[1], std::ios::binary|std::ios::in);
if(!infile.is_open())
exit(-1);
//outfile.open("dump.dat",std::ios::out|std::ios::binary);
// read 1 packet in to the memory
infile.read(pkt_data, pkt_size);
while(!infile.eof()) {
printf("Packet %u\n", pkt_num);
if(pkt->start_of_burst())
printf("\tstart of burst\n");
if(pkt->end_of_burst())
printf("\tend of burst\n");
// if(pkt->carrier_sense())
// printf("\tcarrier sense\n");
if(pkt->underrun())
printf("\tunderrun\n");
if(pkt->overrun())
printf("\toverrun\n");
printf("\tchannel: \t0x%x\n", pkt->chan());
printf("\ttimestamp: \t0x%x\n", pkt->timestamp());
//printf("\ttimestamp: \t%u\n", pkt->timestamp());
printf("\tlength: \t%u\n", pkt->payload_len());
printf("\trssi: \t%u\n", pkt->rssi());
printf("\tpayload: \n");
for(int i=0; i < pkt->payload_len(); i++)
//for(int i=0; i < pkt->max_payload(); i++)
{
printf("\t%d\t0x%x\n", i, *(pkt->payload()+i));
//outfile.write((const char*)(pkt->payload()+i),1);
//printf("\t\t0x%x\n", pkt->payload()+i);
}
printf("\n\n");
pkt_num++;
// read 1 packet in to the memory
infile.read(pkt_data, pkt_size);
}
infile.close();
//outfile.close();
}

View File

@ -1,371 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,2008 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <mblock/mblock.h>
#include <mblock/runtime.h>
#include <mb_runtime_nop.h> // QA only
#include <mblock/protocol_class.h>
#include <mblock/exception.h>
#include <mblock/msg_queue.h>
#include <mblock/message.h>
#include <mb_mblock_impl.h>
#include <mblock/msg_accepter.h>
#include <mblock/class_registry.h>
#include <pmt.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <fstream>
// Include the symbols needed for communication with USRP server
#include <symbols_usrp_server_cs.h>
#include <symbols_usrp_channel.h>
#include <symbols_usrp_low_level_cs.h>
#include <symbols_usrp_rx.h>
static bool verbose = true;
class test_usrp_rx : public mb_mblock
{
mb_port_sptr d_rx;
mb_port_sptr d_cs;
pmt_t d_rx_chan0, d_rx_chan1;
enum state_t {
INIT,
OPENING_USRP,
ALLOCATING_CHANNEL,
RECEIVING,
CLOSING_CHANNEL,
CLOSING_USRP,
};
state_t d_state;
std::ofstream d_ofile;
long d_samples_recvd;
long d_samples_to_recv;
public:
test_usrp_rx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
~test_usrp_rx();
void initial_transition();
void handle_message(mb_message_sptr msg);
protected:
void open_usrp();
void close_usrp();
void allocate_channel();
void send_packets();
void enter_receiving();
void build_and_send_next_frame();
void handle_response_recv_raw_samples(pmt_t invocation_handle);
void enter_closing_channel();
};
test_usrp_rx::test_usrp_rx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
: mb_mblock(runtime, instance_name, user_arg),
d_rx_chan0(PMT_NIL), d_rx_chan1(PMT_NIL),
d_samples_recvd(0),
d_samples_to_recv(20e6)
{
d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
// Pass a dictionary to usrp_server which specifies which interface to use, the stub or USRP
pmt_t usrp_dict = pmt_make_dict();
// To test the application without a USRP
bool fake_usrp_p = false;
if(fake_usrp_p) {
pmt_dict_set(usrp_dict,
pmt_intern("fake-usrp"),
PMT_T);
}
// Specify the RBF to use
pmt_dict_set(usrp_dict,
pmt_intern("rbf"),
pmt_intern("inband_2rxhb_2tx.rbf"));
pmt_dict_set(usrp_dict,
pmt_intern("decim-rx"),
pmt_from_long(64));
define_component("server", "usrp_server", usrp_dict);
connect("self", "rx0", "server", "rx0");
connect("self", "cs", "server", "cs");
}
test_usrp_rx::~test_usrp_rx()
{
}
void
test_usrp_rx::initial_transition()
{
open_usrp();
}
void
test_usrp_rx::handle_message(mb_message_sptr msg)
{
pmt_t event = msg->signal();
pmt_t data = msg->data();
pmt_t handle = PMT_F;
pmt_t status = PMT_F;
std::string error_msg;
switch(d_state){
//----------------------------- OPENING_USRP ----------------------------//
// We only expect a response from opening the USRP which should be succesful
// or failed.
case OPENING_USRP:
if (pmt_eq(event, s_response_open)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
allocate_channel();
return;
}
else {
error_msg = "failed to open usrp:";
goto bail;
}
}
goto unhandled;
//----------------------- ALLOCATING CHANNELS --------------------//
// Allocate an RX channel to perform the overrun test.
case ALLOCATING_CHANNEL:
if (pmt_eq(event, s_response_allocate_channel)){
status = pmt_nth(1, data);
if(pmt_eqv(d_rx_chan0, PMT_NIL))
d_rx_chan0 = pmt_nth(2, data);
else
d_rx_chan1 = pmt_nth(2, data);
if (pmt_eq(status, PMT_T) && !pmt_eqv(d_rx_chan1, PMT_NIL)){
enter_receiving();
return;
}
else if(pmt_eq(status, PMT_F)){
error_msg = "failed to allocate channel:";
goto bail;
}
return;
}
goto unhandled;
//--------------------------- RECEIVING ------------------------------//
// In the receiving state, we receive samples until the specified amount
// while counting the number of overruns.
case RECEIVING:
if (pmt_eq(event, s_response_recv_raw_samples)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
handle_response_recv_raw_samples(data);
return;
}
else {
error_msg = "bad response-xmit-raw-frame:";
goto bail;
}
}
goto unhandled;
//------------------------- CLOSING CHANNEL ----------------------------//
// Check deallocation response for the RX channel
case CLOSING_CHANNEL:
if (pmt_eq(event, s_response_deallocate_channel)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
close_usrp();
return;
}
else {
error_msg = "failed to deallocate channel:";
goto bail;
}
}
// Alternately, we ignore all response recv samples while waiting for the
// channel to actually close
if (pmt_eq(event, s_response_recv_raw_samples))
return;
goto unhandled;
//--------------------------- CLOSING USRP ------------------------------//
// Once we have received a successful USRP close response, we shutdown all
// mblocks and exit.
case CLOSING_USRP:
if (pmt_eq(event, s_response_close)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
fflush(stdout);
shutdown_all(PMT_T);
return;
}
else {
error_msg = "failed to close USRP:";
goto bail;
}
}
goto unhandled;
default:
goto unhandled;
}
return;
// An error occured, print it, and shutdown all m-blocks
bail:
std::cerr << error_msg << data
<< "status = " << status << std::endl;
shutdown_all(PMT_F);
return;
// Received an unhandled message for a specific state
unhandled:
if(verbose && !pmt_eq(event, pmt_intern("%shutdown")))
std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
<< "in state "<< d_state << std::endl;
}
void
test_usrp_rx::open_usrp()
{
pmt_t which_usrp = pmt_from_long(0);
d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, which_usrp));
d_state = OPENING_USRP;
if(verbose)
std::cout << "[TEST_USRP_INBAND_RX] Opening the USRP\n";
}
void
test_usrp_rx::close_usrp()
{
d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
d_state = CLOSING_USRP;
if(verbose)
std::cout << "[TEST_USRP_INBAND_RX] Closing the USRP\n";
}
void
test_usrp_rx::allocate_channel()
{
long capacity = (long) 16e6;
d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
d_state = ALLOCATING_CHANNEL;
if(verbose)
std::cout << "[TEST_USRP_INBAND_RX] Requesting RX channel allocation\n";
}
void
test_usrp_rx::enter_receiving()
{
d_state = RECEIVING;
d_rx->send(s_cmd_start_recv_raw_samples,
pmt_list2(PMT_F,
d_rx_chan0));
d_rx->send(s_cmd_start_recv_raw_samples,
pmt_list2(PMT_F,
d_rx_chan1));
if(verbose)
std::cout << "[TEST_USRP_INBAND_RX] Receiving...\n";
}
void
test_usrp_rx::handle_response_recv_raw_samples(pmt_t data)
{
pmt_t invocation_handle = pmt_nth(0, data);
pmt_t status = pmt_nth(1, data);
pmt_t v_samples = pmt_nth(2, data);
pmt_t timestamp = pmt_nth(3, data);
pmt_t channel = pmt_nth(4, data);
pmt_t properties = pmt_nth(5, data);
d_samples_recvd += pmt_length(v_samples) / 4;
// Check for overrun
if(!pmt_is_dict(properties)) {
std::cout << "[TEST_USRP_INBAND_RX] Recv samples dictionary is improper\n";
return;
}
// Check if the number samples we have received meets the test
if(d_samples_recvd >= d_samples_to_recv) {
d_rx->send(s_cmd_stop_recv_raw_samples, pmt_list2(PMT_NIL, d_rx_chan0));
d_rx->send(s_cmd_stop_recv_raw_samples, pmt_list2(PMT_NIL, d_rx_chan1));
enter_closing_channel();
return;
}
}
void
test_usrp_rx::enter_closing_channel()
{
d_state = CLOSING_CHANNEL;
d_rx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_rx_chan0));
d_rx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_rx_chan1));
if(verbose)
std::cout << "[TEST_USRP_INBAND_RX] Deallocating RX channel\n";
}
REGISTER_MBLOCK_CLASS(test_usrp_rx);
// ----------------------------------------------------------------
int
main (int argc, char **argv)
{
mb_runtime_sptr rt = mb_make_runtime();
pmt_t result = PMT_NIL;
rt->run("top", "test_usrp_rx", PMT_F, &result);
}

View File

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

View File

@ -1,375 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,2008 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <mblock/mblock.h>
#include <mblock/runtime.h>
#include <mblock/protocol_class.h>
#include <mblock/exception.h>
#include <mblock/msg_queue.h>
#include <mblock/message.h>
#include <mblock/msg_accepter.h>
#include <mblock/class_registry.h>
#include <pmt.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <fstream>
// Include the symbols needed for communication with USRP server
#include <symbols_usrp_server_cs.h>
#include <symbols_usrp_channel.h>
#include <symbols_usrp_low_level_cs.h>
#include <symbols_usrp_rx.h>
static bool verbose = true;
class test_usrp_rx : public mb_mblock
{
mb_port_sptr d_rx;
mb_port_sptr d_cs;
pmt_t d_rx_chan; // returned tx channel handle
enum state_t {
INIT,
OPENING_USRP,
ALLOCATING_CHANNEL,
RECEIVING,
CLOSING_CHANNEL,
CLOSING_USRP,
};
state_t d_state;
std::ofstream d_ofile;
long d_n_overruns;
long d_samples_recvd;
long d_samples_to_recv;
public:
test_usrp_rx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
~test_usrp_rx();
void initial_transition();
void handle_message(mb_message_sptr msg);
protected:
void open_usrp();
void close_usrp();
void allocate_channel();
void send_packets();
void enter_receiving();
void build_and_send_next_frame();
void handle_response_recv_raw_samples(pmt_t invocation_handle);
void enter_closing_channel();
};
test_usrp_rx::test_usrp_rx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
: mb_mblock(runtime, instance_name, user_arg),
d_n_overruns(0),
d_samples_recvd(0),
d_samples_to_recv(10e6)
{
d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
// Pass a dictionary to usrp_server which specifies which interface to use, the stub or USRP
pmt_t usrp_dict = pmt_make_dict();
// Specify the RBF to use
pmt_dict_set(usrp_dict,
pmt_intern("rbf"),
pmt_intern("inband_1rxhb_1tx.rbf"));
pmt_dict_set(usrp_dict,
pmt_intern("decim-rx"),
pmt_from_long(128));
define_component("server", "usrp_server", usrp_dict);
connect("self", "rx0", "server", "rx0");
connect("self", "cs", "server", "cs");
}
test_usrp_rx::~test_usrp_rx()
{
}
void
test_usrp_rx::initial_transition()
{
open_usrp();
}
void
test_usrp_rx::handle_message(mb_message_sptr msg)
{
pmt_t event = msg->signal();
pmt_t data = msg->data();
pmt_t handle = PMT_F;
pmt_t status = PMT_F;
std::string error_msg;
switch(d_state){
//----------------------------- OPENING_USRP ----------------------------//
// We only expect a response from opening the USRP which should be succesful
// or failed.
case OPENING_USRP:
if (pmt_eq(event, s_response_open)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
allocate_channel();
return;
}
else {
error_msg = "failed to open usrp:";
goto bail;
}
}
goto unhandled;
//----------------------- ALLOCATING CHANNELS --------------------//
// Allocate an RX channel to perform the overrun test.
case ALLOCATING_CHANNEL:
if (pmt_eq(event, s_response_allocate_channel)){
status = pmt_nth(1, data);
d_rx_chan = pmt_nth(2, data);
if (pmt_eq(status, PMT_T)){
enter_receiving();
return;
}
else {
error_msg = "failed to allocate channel:";
goto bail;
}
}
goto unhandled;
//--------------------------- RECEIVING ------------------------------//
// In the receiving state, we receive samples until the specified amount
// while counting the number of overruns.
case RECEIVING:
if (pmt_eq(event, s_response_recv_raw_samples)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
handle_response_recv_raw_samples(data);
return;
}
else {
error_msg = "bad response-xmit-raw-frame:";
goto bail;
}
}
goto unhandled;
//------------------------- CLOSING CHANNEL ----------------------------//
// Check deallocation response for the RX channel
case CLOSING_CHANNEL:
if (pmt_eq(event, s_response_deallocate_channel)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
close_usrp();
return;
}
else {
error_msg = "failed to deallocate channel:";
goto bail;
}
}
// Alternately, we ignore all response recv samples while waiting for the
// channel to actually close
if (pmt_eq(event, s_response_recv_raw_samples))
return;
goto unhandled;
//--------------------------- CLOSING USRP ------------------------------//
// Once we have received a successful USRP close response, we shutdown all
// mblocks and exit.
case CLOSING_USRP:
if (pmt_eq(event, s_response_close)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
std::cout << "\nOverruns: " << d_n_overruns << std::endl;
fflush(stdout);
shutdown_all(PMT_T);
return;
}
else {
error_msg = "failed to close USRP:";
goto bail;
}
}
goto unhandled;
default:
goto unhandled;
}
return;
// An error occured, print it, and shutdown all m-blocks
bail:
std::cerr << error_msg << data
<< "status = " << status << std::endl;
shutdown_all(PMT_F);
return;
// Received an unhandled message for a specific state
unhandled:
if(verbose && !pmt_eq(event, pmt_intern("%shutdown")))
std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
<< "in state "<< d_state << std::endl;
}
void
test_usrp_rx::open_usrp()
{
pmt_t which_usrp = pmt_from_long(0);
d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, which_usrp));
d_state = OPENING_USRP;
if(verbose)
std::cout << "[TEST_USRP_INBAND_OVERRUN] Opening the USRP\n";
}
void
test_usrp_rx::close_usrp()
{
d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
d_state = CLOSING_USRP;
if(verbose)
std::cout << "[TEST_USRP_INBAND_OVERRUN] Closing the USRP\n";
}
void
test_usrp_rx::allocate_channel()
{
long capacity = (long) 16e6;
d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
d_state = ALLOCATING_CHANNEL;
if(verbose)
std::cout << "[TEST_USRP_INBAND_OVERRUN] Requesting RX channel allocation\n";
}
void
test_usrp_rx::enter_receiving()
{
d_state = RECEIVING;
d_rx->send(s_cmd_start_recv_raw_samples,
pmt_list2(PMT_F,
d_rx_chan));
if(verbose)
std::cout << "[TEST_USRP_INBAND_OVERRUN] Receiving...\n";
}
void
test_usrp_rx::handle_response_recv_raw_samples(pmt_t data)
{
pmt_t invocation_handle = pmt_nth(0, data);
pmt_t status = pmt_nth(1, data);
pmt_t v_samples = pmt_nth(2, data);
pmt_t timestamp = pmt_nth(3, data);
pmt_t channel = pmt_nth(4, data);
pmt_t properties = pmt_nth(5, data);
d_samples_recvd += pmt_length(v_samples) / 4;
// Check for overrun
if(!pmt_is_dict(properties)) {
std::cout << "[TEST_USRP_INBAND_OVERRUN] Recv samples dictionary is improper\n";
return;
}
if(pmt_t overrun = pmt_dict_ref(properties,
pmt_intern("overrun"),
PMT_NIL)) {
if(pmt_eqv(overrun, PMT_T)) {
d_n_overruns++;
if(verbose && 0)
std::cout << "[TEST_USRP_INBAND_OVERRUN] Underrun\n";
}
else {
if(verbose && 0)
std::cout << "[TEST_USRP_INBAND_OVERRUN] No overrun\n" << overrun <<std::endl;
}
} else {
if(verbose && 0)
std::cout << "[TEST_USRP_INBAND_OVERRUN] No overrun\n";
}
// Check if the number samples we have received meets the test
if(d_samples_recvd >= d_samples_to_recv) {
d_rx->send(s_cmd_stop_recv_raw_samples, pmt_list2(PMT_NIL, d_rx_chan));
enter_closing_channel();
return;
}
}
void
test_usrp_rx::enter_closing_channel()
{
d_state = CLOSING_CHANNEL;
sleep(2);
d_rx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_rx_chan));
if(verbose)
std::cout << "[TEST_USRP_INBAND_OVERRUN] Deallocating RX channel\n";
}
REGISTER_MBLOCK_CLASS(test_usrp_rx);
// ----------------------------------------------------------------
int
main (int argc, char **argv)
{
// handle any command line args here
mb_runtime_sptr rt = mb_make_runtime();
pmt_t result = PMT_NIL;
rt->run("top", "test_usrp_rx", PMT_F, &result);
}

View File

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

View File

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

View File

@ -1,362 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <mblock/mblock.h>
#include <mblock/runtime.h>
#include <mblock/protocol_class.h>
#include <mblock/exception.h>
#include <mblock/msg_queue.h>
#include <mblock/message.h>
#include <mblock/msg_accepter.h>
#include <mblock/class_registry.h>
#include <pmt.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <fstream>
// Include the symbols needed for communication with USRP server
#include <symbols_usrp_server_cs.h>
#include <symbols_usrp_channel.h>
#include <symbols_usrp_low_level_cs.h>
#include <symbols_usrp_rx.h>
static bool verbose = true;
class test_usrp_rx : public mb_mblock
{
mb_port_sptr d_rx;
mb_port_sptr d_cs;
pmt_t d_rx_chan; // returned tx channel handle
enum state_t {
INIT,
OPENING_USRP,
ALLOCATING_CHANNEL,
RECEIVING,
CLOSING_CHANNEL,
CLOSING_USRP,
};
state_t d_state;
std::ofstream d_ofile;
long d_samples_recvd;
long d_samples_to_recv;
public:
test_usrp_rx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
~test_usrp_rx();
void initial_transition();
void handle_message(mb_message_sptr msg);
protected:
void open_usrp();
void close_usrp();
void allocate_channel();
void send_packets();
void enter_receiving();
void build_and_send_next_frame();
void handle_response_recv_raw_samples(pmt_t invocation_handle);
void enter_closing_channel();
};
test_usrp_rx::test_usrp_rx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
: mb_mblock(runtime, instance_name, user_arg),
d_samples_recvd(0),
d_samples_to_recv(20e6)
{
d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
// Pass a dictionary to usrp_server which specifies which interface to use, the stub or USRP
pmt_t usrp_dict = pmt_make_dict();
// To test the application without a USRP
bool fake_usrp_p = false;
if(fake_usrp_p) {
pmt_dict_set(usrp_dict,
pmt_intern("fake-usrp"),
PMT_T);
}
// Specify the RBF to use
pmt_dict_set(usrp_dict,
pmt_intern("rbf"),
pmt_intern("inband_1rxhb_1tx.rbf"));
pmt_dict_set(usrp_dict,
pmt_intern("decim-rx"),
pmt_from_long(64));
// If unspecified, chooses center frequency from range
// pmt_dict_set(usrp_dict,
// pmt_intern("rf-freq"),
// pmt_from_long(10e6));
define_component("server", "usrp_server", usrp_dict);
connect("self", "rx0", "server", "rx0");
connect("self", "cs", "server", "cs");
}
test_usrp_rx::~test_usrp_rx()
{
}
void
test_usrp_rx::initial_transition()
{
open_usrp();
}
void
test_usrp_rx::handle_message(mb_message_sptr msg)
{
pmt_t event = msg->signal();
pmt_t data = msg->data();
pmt_t handle = PMT_F;
pmt_t status = PMT_F;
std::string error_msg;
switch(d_state){
//----------------------------- OPENING_USRP ----------------------------//
// We only expect a response from opening the USRP which should be succesful
// or failed.
case OPENING_USRP:
if (pmt_eq(event, s_response_open)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
allocate_channel();
return;
}
else {
error_msg = "failed to open usrp:";
goto bail;
}
}
goto unhandled;
//----------------------- ALLOCATING CHANNELS --------------------//
// Allocate an RX channel to perform the overrun test.
case ALLOCATING_CHANNEL:
if (pmt_eq(event, s_response_allocate_channel)){
status = pmt_nth(1, data);
d_rx_chan = pmt_nth(2, data);
if (pmt_eq(status, PMT_T)){
enter_receiving();
return;
}
else {
error_msg = "failed to allocate channel:";
goto bail;
}
}
goto unhandled;
//--------------------------- RECEIVING ------------------------------//
// In the receiving state, we receive samples until the specified amount
// while counting the number of overruns.
case RECEIVING:
if (pmt_eq(event, s_response_recv_raw_samples)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
handle_response_recv_raw_samples(data);
return;
}
else {
error_msg = "bad response-xmit-raw-frame:";
goto bail;
}
}
goto unhandled;
//------------------------- CLOSING CHANNEL ----------------------------//
// Check deallocation response for the RX channel
case CLOSING_CHANNEL:
if (pmt_eq(event, s_response_deallocate_channel)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
close_usrp();
return;
}
else {
error_msg = "failed to deallocate channel:";
goto bail;
}
}
// Alternately, we ignore all response recv samples while waiting for the
// channel to actually close
if (pmt_eq(event, s_response_recv_raw_samples))
return;
goto unhandled;
//--------------------------- CLOSING USRP ------------------------------//
// Once we have received a successful USRP close response, we shutdown all
// mblocks and exit.
case CLOSING_USRP:
if (pmt_eq(event, s_response_close)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
fflush(stdout);
shutdown_all(PMT_T);
return;
}
else {
error_msg = "failed to close USRP:";
goto bail;
}
}
goto unhandled;
default:
goto unhandled;
}
return;
// An error occured, print it, and shutdown all m-blocks
bail:
std::cerr << error_msg << data
<< "status = " << status << std::endl;
shutdown_all(PMT_F);
return;
// Received an unhandled message for a specific state
unhandled:
if(verbose && !pmt_eq(event, pmt_intern("%shutdown")))
std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
<< "in state "<< d_state << std::endl;
}
void
test_usrp_rx::open_usrp()
{
pmt_t which_usrp = pmt_from_long(0);
d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, which_usrp));
d_state = OPENING_USRP;
if(verbose)
std::cout << "[TEST_USRP_INBAND_RX] Opening the USRP\n";
}
void
test_usrp_rx::close_usrp()
{
d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
d_state = CLOSING_USRP;
if(verbose)
std::cout << "[TEST_USRP_INBAND_RX] Closing the USRP\n";
}
void
test_usrp_rx::allocate_channel()
{
long capacity = (long) 16e6;
d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
d_state = ALLOCATING_CHANNEL;
if(verbose)
std::cout << "[TEST_USRP_INBAND_RX] Requesting RX channel allocation\n";
}
void
test_usrp_rx::enter_receiving()
{
d_state = RECEIVING;
d_rx->send(s_cmd_start_recv_raw_samples,
pmt_list2(PMT_F,
d_rx_chan));
if(verbose)
std::cout << "[TEST_USRP_INBAND_RX] Receiving...\n";
}
void
test_usrp_rx::handle_response_recv_raw_samples(pmt_t data)
{
pmt_t invocation_handle = pmt_nth(0, data);
pmt_t status = pmt_nth(1, data);
pmt_t v_samples = pmt_nth(2, data);
pmt_t timestamp = pmt_nth(3, data);
pmt_t channel = pmt_nth(4, data);
pmt_t properties = pmt_nth(5, data);
d_samples_recvd += pmt_length(v_samples) / 4;
// Check for overrun
if(!pmt_is_dict(properties)) {
std::cout << "[TEST_USRP_INBAND_RX] Recv samples dictionary is improper\n";
return;
}
// Check if the number samples we have received meets the test
if(d_samples_recvd >= d_samples_to_recv) {
d_rx->send(s_cmd_stop_recv_raw_samples, pmt_list2(PMT_NIL, d_rx_chan));
enter_closing_channel();
return;
}
}
void
test_usrp_rx::enter_closing_channel()
{
d_state = CLOSING_CHANNEL;
d_rx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_rx_chan));
if(verbose)
std::cout << "[TEST_USRP_INBAND_RX] Deallocating RX channel\n";
}
REGISTER_MBLOCK_CLASS(test_usrp_rx);
// ----------------------------------------------------------------
int
main (int argc, char **argv)
{
mb_runtime_sptr rt = mb_make_runtime();
pmt_t result = PMT_NIL;
rt->run("top", "test_usrp_rx", PMT_F, &result);
}

View File

@ -1,506 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,2008 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <mblock/mblock.h>
#include <mblock/runtime.h>
#include <mblock/protocol_class.h>
#include <mblock/exception.h>
#include <mblock/msg_queue.h>
#include <mblock/message.h>
#include <mblock/msg_accepter.h>
#include <mblock/class_registry.h>
#include <pmt.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <iostream>
#include <ui_nco.h>
#include <symbols_usrp_server_cs.h>
#include <symbols_usrp_channel.h>
#include <symbols_usrp_low_level_cs.h>
#include <symbols_usrp_tx.h>
#include <symbols_usrp_rx.h>
#define NBPING 10
static bool verbose = true;
bool bskip = false;
long bstep = 10000;
long bcurr = 0;
long incr = 0x500;
long ptime = 0x000;
class test_usrp_inband_timestamps : public mb_mblock
{
mb_port_sptr d_tx;
mb_port_sptr d_rx;
mb_port_sptr d_cs;
pmt_t d_tx_chan; // returned tx channel handle
pmt_t d_rx_chan; // returned tx channel handle
struct timeval times[NBPING];
enum state_t {
INIT,
OPENING_USRP,
ALLOCATING_CHANNEL,
TRANSMITTING,
CLOSING_CHANNEL,
CLOSING_USRP,
};
state_t d_state;
long d_nsamples_to_send;
long d_nsamples_xmitted;
long d_nframes_xmitted;
long d_samples_per_frame;
bool d_done_sending;
// for generating sine wave output
ui_nco<float,float> d_nco;
double d_amplitude;
public:
test_usrp_inband_timestamps(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
~test_usrp_inband_timestamps();
void initial_transition();
void handle_message(mb_message_sptr msg);
protected:
void open_usrp();
void close_usrp();
void allocate_channel();
void send_packets();
void enter_receiving();
void enter_transmitting();
void build_and_send_ping();
void build_and_send_next_frame();
void handle_xmit_response(pmt_t invocation_handle);
void enter_closing_channel();
};
test_usrp_inband_timestamps::test_usrp_inband_timestamps(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
: mb_mblock(runtime, instance_name, user_arg),
d_tx_chan(PMT_NIL),
d_rx_chan(PMT_NIL),
d_state(INIT), d_nsamples_to_send((long) 40e6),
d_nsamples_xmitted(0),
d_nframes_xmitted(0),
//d_samples_per_frame((long)(126)),
d_samples_per_frame((long)(126 * 2)), // non-full packet
//d_samples_per_frame((long)(126 * 3.5)), // non-full packet
//d_samples_per_frame((long)(126 * 4)), // full packet
d_done_sending(false),
d_amplitude(16384)
{
if(verbose)
std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Initializing...\n";
d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
bool fake_usrp_p = false;
// Test the TX side
pmt_t usrp_dict = pmt_make_dict();
if(fake_usrp_p) {
pmt_dict_set(usrp_dict,
pmt_intern("fake-usrp"),
PMT_T);
}
// Set TX and RX interpolations
pmt_dict_set(usrp_dict,
pmt_intern("interp-tx"),
pmt_from_long(128));
pmt_dict_set(usrp_dict,
pmt_intern("decim-rx"),
pmt_from_long(16));
// Specify the RBF to use
pmt_dict_set(usrp_dict,
pmt_intern("rbf"),
pmt_intern("inband_1rxhb_1tx.rbf"));
define_component("server", "usrp_server", usrp_dict);
connect("self", "tx0", "server", "tx0");
connect("self", "rx0", "server", "rx0");
connect("self", "cs", "server", "cs");
// initialize NCO
double freq = 100e3;
int interp = 32; // 32 -> 4MS/s
double sample_rate = 128e6 / interp;
d_nco.set_freq(2*M_PI * freq/sample_rate);
}
test_usrp_inband_timestamps::~test_usrp_inband_timestamps()
{
}
void
test_usrp_inband_timestamps::initial_transition()
{
open_usrp();
}
void
test_usrp_inband_timestamps::handle_message(mb_message_sptr msg)
{
pmt_t event = msg->signal();
pmt_t data = msg->data();
pmt_t port_id = msg->port_id();
pmt_t handle = PMT_F;
pmt_t status = PMT_F;
std::string error_msg;
//std::cout << msg << std::endl;
switch(d_state){
case OPENING_USRP:
if (pmt_eq(event, s_response_open)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
allocate_channel();
return;
}
else {
error_msg = "failed to open usrp:";
goto bail;
}
}
goto unhandled;
case ALLOCATING_CHANNEL:
if (pmt_eq(event, s_response_allocate_channel)){
if(pmt_eq(d_tx->port_symbol(), port_id)) {
status = pmt_nth(1, data);
d_tx_chan = pmt_nth(2, data);
if (pmt_eq(status, PMT_T)){
if(verbose)
std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Received allocation for TX\n";
if(!pmt_eqv(d_rx_chan, PMT_NIL)) {
enter_receiving();
enter_transmitting();
}
return;
}
else {
error_msg = "failed to allocate channel:";
goto bail;
}
}
if(pmt_eq(d_rx->port_symbol(), port_id)) {
status = pmt_nth(1, data);
d_rx_chan = pmt_nth(2, data);
if (pmt_eq(status, PMT_T)){
if(verbose)
std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Received allocation for TX\n";
if(!pmt_eqv(d_tx_chan, PMT_NIL)) {
enter_receiving();
enter_transmitting();
}
return;
}
else {
error_msg = "failed to allocate channel:";
goto bail;
}
}
}
goto unhandled;
case TRANSMITTING:
if (pmt_eq(event, s_response_xmit_raw_frame)){
handle = pmt_nth(0, data);
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
handle_xmit_response(handle);
return;
}
else {
error_msg = "bad response-xmit-raw-frame:";
goto bail;
}
}
if (pmt_eq(event, s_response_from_control_channel)) {
std::cout << "ping response!\n";
}
goto unhandled;
case CLOSING_CHANNEL:
if (pmt_eq(event, s_response_deallocate_channel)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
close_usrp();
return;
}
else {
error_msg = "failed to deallocate channel:";
goto bail;
}
}
goto unhandled;
case CLOSING_USRP:
if (pmt_eq(event, s_response_close)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
shutdown_all(PMT_T);
return;
}
else {
error_msg = "failed to close USRP:";
goto bail;
}
}
goto unhandled;
default:
goto unhandled;
}
return;
bail:
std::cerr << error_msg << data
<< "status = " << status << std::endl;
shutdown_all(PMT_F);
return;
unhandled:
if(verbose && 0)
std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
<< "in state "<< d_state << std::endl;
}
void
test_usrp_inband_timestamps::open_usrp()
{
pmt_t which_usrp = pmt_from_long(0);
d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, which_usrp));
d_state = OPENING_USRP;
}
void
test_usrp_inband_timestamps::close_usrp()
{
d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
d_state = CLOSING_USRP;
if(verbose)
std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Closing USRP\n";
}
void
test_usrp_inband_timestamps::allocate_channel()
{
long capacity = (long) 16e6;
d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
d_state = ALLOCATING_CHANNEL;
}
void
test_usrp_inband_timestamps::enter_receiving()
{
d_rx->send(s_cmd_start_recv_raw_samples,
pmt_list2(PMT_F,
d_rx_chan));
}
void
test_usrp_inband_timestamps::enter_transmitting()
{
d_state = TRANSMITTING;
d_nsamples_xmitted = 0;
if(verbose)
std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Beginning transmission\n";
sleep(1);
build_and_send_next_frame();
build_and_send_next_frame();
build_and_send_next_frame();
build_and_send_next_frame();
}
void
test_usrp_inband_timestamps::build_and_send_ping()
{
d_tx->send(s_cmd_to_control_channel,
pmt_list2(PMT_NIL, pmt_list1(pmt_list2(s_op_ping_fixed,
pmt_list2(pmt_from_long(0),
pmt_from_long(0))))));
if(verbose && 0)
std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Ping sent" << std::endl;
}
void
test_usrp_inband_timestamps::build_and_send_next_frame()
{
// allocate the uniform vector for the samples
// FIXME perhaps hold on to this between calls
#if 0
long nsamples_this_frame =
std::min(d_nsamples_to_send - d_nsamples_xmitted,
d_samples_per_frame);
#else
long nsamples_this_frame = d_samples_per_frame;
#endif
if (nsamples_this_frame == 0){
d_done_sending = true;
return;
}
size_t nshorts = 2 * nsamples_this_frame; // 16-bit I & Q
pmt_t uvec = pmt_make_s16vector(nshorts, 0);
size_t ignore;
int16_t *samples = pmt_s16vector_writable_elements(uvec, ignore);
// fill in the complex sinusoid
for (int i = 0; i < nsamples_this_frame; i++){
if (1){
gr_complex s;
d_nco.sincos(&s, 1, d_amplitude);
// write 16-bit i & q
samples[2*i] = (int16_t) s.real();
samples[2*i+1] = (int16_t) s.imag();
}
else {
gr_complex s(d_amplitude, d_amplitude);
// write 16-bit i & q
samples[2*i] = (int16_t) s.real();
samples[2*i+1] = (int16_t) s.imag();
}
}
pmt_t timestamp;
if(bskip) {
timestamp = pmt_from_long(0x0); // throw away
bcurr++;
if(bcurr == bstep) {
bskip = false;
bcurr = 0;
}
} else {
timestamp = pmt_from_long(0xffffffff); // NOW
timestamp = pmt_from_long(ptime);
ptime += incr;
bcurr++;
if(bcurr == bstep) {
//bskip = true;
bcurr = 0;
}
}
std::cout << bskip << " -- " << bcurr << std::endl;
d_tx->send(s_cmd_xmit_raw_frame,
pmt_list4(pmt_from_long(d_nframes_xmitted), // invocation-handle
d_tx_chan, // channel
uvec, // the samples
timestamp));
d_nsamples_xmitted += nsamples_this_frame;
d_nframes_xmitted++;
if(verbose && 0)
std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Transmitted frame\n";
//build_and_send_next_frame();
}
void
test_usrp_inband_timestamps::handle_xmit_response(pmt_t handle)
{
if (d_done_sending &&
pmt_to_long(handle) == (d_nframes_xmitted - 1)){
// We're done sending and have received all responses
enter_closing_channel();
}
build_and_send_next_frame();
//build_and_send_ping();
}
void
test_usrp_inband_timestamps::enter_closing_channel()
{
d_state = CLOSING_CHANNEL;
d_tx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_tx_chan));
if(verbose)
std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Closing channel\n";
}
REGISTER_MBLOCK_CLASS(test_usrp_inband_timestamps);
// ----------------------------------------------------------------
int
main (int argc, char **argv)
{
// handle any command line args here
mb_runtime_sptr rt = mb_make_runtime();
pmt_t result = PMT_NIL;
rt->run("top", "test_usrp_inband_timestamps", PMT_F, &result);
}

View File

@ -1,411 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,2008 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <mblock/mblock.h>
#include <mblock/runtime.h>
#include <mblock/protocol_class.h>
#include <mblock/exception.h>
#include <mblock/msg_queue.h>
#include <mblock/message.h>
#include <mblock/msg_accepter.h>
#include <mblock/class_registry.h>
#include <pmt.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <ui_nco.h>
#include <symbols_usrp_server_cs.h>
#include <symbols_usrp_channel.h>
#include <symbols_usrp_low_level_cs.h>
#include <symbols_usrp_tx.h>
static bool verbose = true;
class test_usrp_tx : public mb_mblock
{
mb_port_sptr d_tx;
mb_port_sptr d_cs;
pmt_t d_tx_chan; // returned tx channel handle
enum state_t {
INIT,
OPENING_USRP,
ALLOCATING_CHANNEL,
TRANSMITTING,
CLOSING_CHANNEL,
CLOSING_USRP,
};
state_t d_state;
long d_nsamples_to_send;
long d_nsamples_xmitted;
long d_nframes_xmitted;
long d_samples_per_frame;
bool d_done_sending;
// for generating sine wave output
ui_nco<float,float> d_nco;
double d_amplitude;
public:
test_usrp_tx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
~test_usrp_tx();
void initial_transition();
void handle_message(mb_message_sptr msg);
protected:
void open_usrp();
void close_usrp();
void allocate_channel();
void send_packets();
void enter_transmitting();
void build_and_send_next_frame();
void handle_xmit_response(pmt_t invocation_handle);
void enter_closing_channel();
};
test_usrp_tx::test_usrp_tx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
: mb_mblock(runtime, instance_name, user_arg),
d_state(INIT), d_nsamples_to_send((long) 80e6),
d_nsamples_xmitted(0),
d_nframes_xmitted(0),
d_samples_per_frame((long)(126 * 4)), // full packet
d_done_sending(false),
d_amplitude(16384)
{
// std::cout << "[TEST_USRP_TX] Initializing...\n";
d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
//bool fake_usrp_p = true;
bool fake_usrp_p = false;
// Test the TX side
pmt_t usrp_dict = pmt_make_dict();
if(fake_usrp_p) {
pmt_dict_set(usrp_dict,
pmt_intern("fake-usrp"),
PMT_T);
}
// Specify the RBF to use
pmt_dict_set(usrp_dict,
pmt_intern("rbf"),
pmt_intern("inband_1rxhb_1tx.rbf"));
// Set TX and RX interpolations
pmt_dict_set(usrp_dict,
pmt_intern("interp-tx"),
pmt_from_long(64));
// If unspecified, chooses center frequency from range
// pmt_dict_set(usrp_dict,
// pmt_intern("rf-freq"),
// pmt_from_long(10e6));
define_component("server", "usrp_server", usrp_dict);
connect("self", "tx0", "server", "tx0");
connect("self", "cs", "server", "cs");
// initialize NCO
double freq = 100e3;
int interp = 32; // 32 -> 4MS/s
double sample_rate = 128e6 / interp;
d_nco.set_freq(2*M_PI * freq/sample_rate);
// FIXME need to somehow set the interp rate in the USRP.
// for now, we'll have the low-level code hardwire it.
}
test_usrp_tx::~test_usrp_tx()
{
}
void
test_usrp_tx::initial_transition()
{
open_usrp();
}
void
test_usrp_tx::handle_message(mb_message_sptr msg)
{
pmt_t event = msg->signal();
pmt_t data = msg->data();
pmt_t handle = PMT_F;
pmt_t status = PMT_F;
std::string error_msg;
//std::cout << msg << std::endl;
switch(d_state){
case OPENING_USRP:
if (pmt_eq(event, s_response_open)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
allocate_channel();
return;
}
else {
error_msg = "failed to open usrp:";
goto bail;
}
}
goto unhandled;
case ALLOCATING_CHANNEL:
if (pmt_eq(event, s_response_allocate_channel)){
status = pmt_nth(1, data);
d_tx_chan = pmt_nth(2, data);
if (pmt_eq(status, PMT_T)){
enter_transmitting();
return;
}
else {
error_msg = "failed to allocate channel:";
goto bail;
}
}
goto unhandled;
case TRANSMITTING:
if (pmt_eq(event, s_response_xmit_raw_frame)){
handle = pmt_nth(0, data);
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
handle_xmit_response(handle);
return;
}
else {
error_msg = "bad response-xmit-raw-frame:";
goto bail;
}
}
goto unhandled;
case CLOSING_CHANNEL:
if (pmt_eq(event, s_response_deallocate_channel)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
close_usrp();
return;
}
else {
error_msg = "failed to deallocate channel:";
goto bail;
}
}
goto unhandled;
case CLOSING_USRP:
if (pmt_eq(event, s_response_close)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
shutdown_all(PMT_T);
return;
}
else {
error_msg = "failed to close USRP:";
goto bail;
}
}
goto unhandled;
default:
goto unhandled;
}
return;
bail:
std::cerr << error_msg << data
<< "status = " << status << std::endl;
shutdown_all(PMT_F);
return;
unhandled:
std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
<< "in state "<< d_state << std::endl;
}
void
test_usrp_tx::open_usrp()
{
pmt_t which_usrp = pmt_from_long(0);
d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, which_usrp));
d_state = OPENING_USRP;
if(verbose)
std::cout << "[TEST_USRP_INBAND_TX] Opening the USRP\n";
}
void
test_usrp_tx::close_usrp()
{
d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
d_state = CLOSING_USRP;
if(verbose)
std::cout << "[TEST_USRP_INBAND_TX] Closing the USRP\n";
}
void
test_usrp_tx::allocate_channel()
{
long capacity = (long) 16e6;
d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
d_state = ALLOCATING_CHANNEL;
if(verbose)
std::cout << "[TEST_USRP_INBAND_TX] Requesting TX channel allocation\n";
}
void
test_usrp_tx::enter_transmitting()
{
d_state = TRANSMITTING;
d_nsamples_xmitted = 0;
if(verbose)
std::cout << "[TEST_USRP_INBAND_TX] Transmitting...\n";
build_and_send_next_frame(); // fire off 4 to start pipeline
build_and_send_next_frame();
build_and_send_next_frame();
build_and_send_next_frame();
}
void
test_usrp_tx::build_and_send_next_frame()
{
// allocate the uniform vector for the samples
// FIXME perhaps hold on to this between calls
#if 1
long nsamples_this_frame =
std::min(d_nsamples_to_send - d_nsamples_xmitted,
d_samples_per_frame);
#else
long nsamples_this_frame = d_samples_per_frame;
#endif
if (nsamples_this_frame == 0){
d_done_sending = true;
return;
}
size_t nshorts = 2 * nsamples_this_frame; // 16-bit I & Q
pmt_t uvec = pmt_make_s16vector(nshorts, 0);
size_t ignore;
int16_t *samples = pmt_s16vector_writable_elements(uvec, ignore);
// fill in the complex sinusoid
for (int i = 0; i < nsamples_this_frame; i++){
if (1){
gr_complex s;
d_nco.sincos(&s, 1, d_amplitude);
// write 16-bit i & q
samples[2*i] = (int16_t) s.real();
samples[2*i+1] = (int16_t) s.imag();
}
else {
gr_complex s(d_amplitude, d_amplitude);
// write 16-bit i & q
samples[2*i] = (int16_t) s.real();
samples[2*i+1] = (int16_t) s.imag();
}
}
pmt_t tx_properties = pmt_make_dict();
pmt_t timestamp = pmt_from_long(0xffffffff); // NOW
d_tx->send(s_cmd_xmit_raw_frame,
pmt_list5(pmt_from_long(d_nframes_xmitted), // invocation-handle
d_tx_chan, // channel
uvec, // the samples
timestamp,
tx_properties));
d_nsamples_xmitted += nsamples_this_frame;
d_nframes_xmitted++;
if(verbose && 0)
std::cout << "[TEST_USRP_INBAND_TX] Transmitted frame\n";
}
void
test_usrp_tx::handle_xmit_response(pmt_t handle)
{
if (d_done_sending &&
pmt_to_long(handle) == (d_nframes_xmitted - 1)){
// We're done sending and have received all responses
enter_closing_channel();
}
build_and_send_next_frame();
}
void
test_usrp_tx::enter_closing_channel()
{
d_state = CLOSING_CHANNEL;
d_tx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_tx_chan));
if(verbose)
std::cout << "[TEST_USRP_INBAND_tX] Deallocating TX channel\n";
}
REGISTER_MBLOCK_CLASS(test_usrp_tx);
// ----------------------------------------------------------------
int
main (int argc, char **argv)
{
// handle any command line args here
mb_runtime_sptr rt = mb_make_runtime();
pmt_t result = PMT_NIL;
rt->run("top", "test_usrp_tx", PMT_F, &result);
}

View File

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

View File

@ -1,202 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2002 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_UI_NCO_H
#define INCLUDED_UI_NCO_H
#include <vector>
#include <ui_sincos.h>
#include <cmath>
#include <complex>
typedef std::complex<float> gr_complex;
/*!
* \brief base class template for Numerically Controlled Oscillator (NCO)
*/
//FIXME Eventually generalize this to fixed point
template<class o_type, class i_type>
class ui_nco {
public:
ui_nco () : phase (0), phase_inc(0) {}
virtual ~ui_nco () {}
// radians
void set_phase (double angle) {
phase = angle;
}
void adjust_phase (double delta_phase) {
phase += delta_phase;
}
// angle_rate is in radians / step
void set_freq (double angle_rate){
phase_inc = angle_rate;
}
// angle_rate is a delta in radians / step
void adjust_freq (double delta_angle_rate)
{
phase_inc += delta_angle_rate;
}
// increment current phase angle
void step ()
{
phase += phase_inc;
if (fabs (phase) > M_PI){
while (phase > M_PI)
phase -= 2*M_PI;
while (phase < -M_PI)
phase += 2*M_PI;
}
}
void step (int n)
{
phase += phase_inc * n;
if (fabs (phase) > M_PI){
while (phase > M_PI)
phase -= 2*M_PI;
while (phase < -M_PI)
phase += 2*M_PI;
}
}
// units are radians / step
double get_phase () const { return phase; }
double get_freq () const { return phase_inc; }
// compute sin and cos for current phase angle
void sincos (float *sinx, float *cosx) const;
// compute cos or sin for current phase angle
float cos () const { return std::cos (phase); }
float sin () const { return std::sin (phase); }
// compute a block at a time
void sin (float *output, int noutput_items, double ampl = 1.0);
void cos (float *output, int noutput_items, double ampl = 1.0);
void sincos (gr_complex *output, int noutput_items, double ampl = 1.0);
void sin (short *output, int noutput_items, double ampl = 1.0);
void cos (short *output, int noutput_items, double ampl = 1.0);
void sin (int *output, int noutput_items, double ampl = 1.0);
void cos (int *output, int noutput_items, double ampl = 1.0);
protected:
double phase;
double phase_inc;
};
template<class o_type, class i_type>
void
ui_nco<o_type,i_type>::sincos (float *sinx, float *cosx) const
{
ui_sincosf (phase, sinx, cosx);
}
template<class o_type, class i_type>
void
ui_nco<o_type,i_type>::sin (float *output, int noutput_items, double ampl)
{
for (int i = 0; i < noutput_items; i++){
output[i] = (float)(sin () * ampl);
step ();
}
}
template<class o_type, class i_type>
void
ui_nco<o_type,i_type>::cos (float *output, int noutput_items, double ampl)
{
for (int i = 0; i < noutput_items; i++){
output[i] = (float)(cos () * ampl);
step ();
}
}
template<class o_type, class i_type>
void
ui_nco<o_type,i_type>::sin (short *output, int noutput_items, double ampl)
{
for (int i = 0; i < noutput_items; i++){
output[i] = (short)(sin() * ampl);
step ();
}
}
template<class o_type, class i_type>
void
ui_nco<o_type,i_type>::cos (short *output, int noutput_items, double ampl)
{
for (int i = 0; i < noutput_items; i++){
output[i] = (short)(cos () * ampl);
step ();
}
}
template<class o_type, class i_type>
void
ui_nco<o_type,i_type>::sin (int *output, int noutput_items, double ampl)
{
for (int i = 0; i < noutput_items; i++){
output[i] = (int)(sin () * ampl);
step ();
}
}
template<class o_type, class i_type>
void
ui_nco<o_type,i_type>::cos (int *output, int noutput_items, double ampl)
{
for (int i = 0; i < noutput_items; i++){
output[i] = (int)(cos () * ampl);
step ();
}
}
template<class o_type, class i_type>
void
ui_nco<o_type,i_type>::sincos (gr_complex *output, int noutput_items, double ampl)
{
for (int i = 0; i < noutput_items; i++){
float cosx, sinx;
sincos (&sinx, &cosx);
output[i] = gr_complex(cosx * ampl, sinx * ampl);
step ();
}
}
#endif /* INCLUDED_UI_NCO_H */

View File

@ -1,81 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2004 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#define _GNU_SOURCE // ask for GNU extensions if available
#include "ui_sincos.h"
#include <math.h>
// ----------------------------------------------------------------
#if defined (HAVE_SINCOS)
void
ui_sincos (double x, double *sinx, double *cosx)
{
sincos (x, sinx, cosx);
}
#else
void
ui_sincos (double x, double *sinx, double *cosx)
{
*sinx = sin (x);
*cosx = cos (x);
}
#endif
// ----------------------------------------------------------------
#if defined (HAVE_SINCOSF)
void
ui_sincosf (float x, float *sinx, float *cosx)
{
sincosf (x, sinx, cosx);
}
#elif defined (HAVE_SINF) && defined (HAVE_COSF)
void
ui_sincosf (float x, float *sinx, float *cosx)
{
*sinx = sinf (x);
*cosx = cosf (x);
}
#else
void
ui_sincosf (float x, float *sinx, float *cosx)
{
*sinx = sin (x);
*cosx = cos (x);
}
#endif

View File

@ -1,39 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2002,2004 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_UI_SINCOS_H
#define INCLUDED_UI_SINCOS_H
#ifdef __cplusplus
extern "C" {
#endif
// compute sine and cosine at the same time
void ui_sincos (double x, double *sin, double *cos);
void ui_sincosf (float x, float *sin, float *cos);
#ifdef __cplusplus
};
#endif
#endif /* INCLUDED_UI_SINCOS_H */

View File

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

View File

@ -1,114 +0,0 @@
#
# Copyright 2007,2008 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# GNU Radio is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
include $(top_srcdir)/Makefile.common
AM_CPPFLAGS = \
$(DEFINES) $(OMNITHREAD_INCLUDES) $(PMT_INCLUDES) $(MBLOCK_INCLUDES) \
$(USRP_INCLUDES) $(BOOST_CPPFLAGS) $(CPPUNIT_INCLUDES) \
-I$(srcdir)/../../apps-inband $(WITH_INCLUDES)
TESTS = test_inband
EXTRA_DIST = \
usrp_server.mbh \
usrp_interface.mbh
lib_LTLIBRARIES = \
libusrp-inband.la \
libusrp-inband-qa.la
# ------------------------------------------------------------------------
# Build the inband library
BUILT_SOURCES = \
usrp_server_mbh.cc \
usrp_interface_mbh.cc
usrp_server_mbh.cc : usrp_server.mbh
$(COMPILE_MBH) $(srcdir)/usrp_server.mbh usrp_server_mbh.cc
usrp_interface_mbh.cc : usrp_interface.mbh
$(COMPILE_MBH) $(srcdir)/usrp_interface.mbh usrp_interface_mbh.cc
libusrp_inband_la_SOURCES = \
$(BUILT_SOURCES) \
$(srcdir)/../../apps-inband/ui_sincos.c \
usrp_inband_usb_packet.cc \
usrp_rx.cc \
usrp_rx_stub.cc \
usrp_server.cc \
usrp_tx.cc \
usrp_tx_stub.cc \
usrp_usb_interface.cc
libusrp_inband_la_LDFLAGS = $(NO_UNDEFINED) -version-info 0:0:0
libusrp_inband_la_LIBADD = \
$(MBLOCK_LA) \
$(USRP_LA) \
-lstdc++
include_HEADERS = \
usrp_inband_usb_packet.h \
usrp_rx.h \
usrp_rx_stub.h \
usrp_server.h \
usrp_tx.h \
usrp_tx_stub.h \
usrp_usb_interface.h
noinst_HEADERS = \
qa_inband.h \
qa_inband_packet_prims.h \
qa_inband_usrp_server.h \
symbols_usrp_channel.h \
symbols_usrp_interface_cs.h \
symbols_usrp_low_level_cs.h \
symbols_usrp_rx.h \
symbols_usrp_rx_cs.h \
symbols_usrp_server_cs.h \
symbols_usrp_tx.h \
symbols_usrp_tx_cs.h
# ------------------------------------------------------------------------
# Build the qa code in its own library
libusrp_inband_qa_la_SOURCES = \
qa_inband.cc \
qa_inband_packet_prims.cc \
qa_inband_usrp_server.cc
# magic flags
libusrp_inband_qa_la_LDFLAGS = $(NO_UNDEFINED) -avoid-version
libusrp_inband_qa_la_LIBADD = \
libusrp-inband.la \
$(PMT_LA) \
$(CPPUNIT_LIBS) \
-lstdc++
# ------------------------------------------------------------------------
noinst_PROGRAMS = \
test_inband
test_inband_SOURCES = test_inband.cc
test_inband_LDADD = libusrp-inband-qa.la

View File

@ -1,65 +0,0 @@
#!/usr/bin/env python
#
# Copyright 2007 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# GNU Radio is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
import sys
import struct
from optparse import OptionParser
from usb_packet import *
def dump_packet(raw_pkt, outfile, dump_payload):
pkt = usb_packet(raw_pkt)
outfile.write(pkt.decoded_flags())
outfile.write(' chan= %2d len= %3d timestamp= 0x%08x rssi= % 2d tag= %2d\n' % (
pkt.chan(), pkt.payload_len(), pkt.timestamp(), pkt.rssi(), pkt.tag()))
if dump_payload:
assert pkt.payload_len() % 4 == 0
shorts = struct.unpack('<%dh' % (pkt.payload_len() // 2), pkt.payload())
for i in range(0, len(shorts), 2):
outfile.write(' %6d, %6d\n' % (shorts[i], shorts[i+1]))
def dump_packets(infile, outfile, dump_payload):
raw_pkt = infile.read(512)
while raw_pkt:
if len(raw_pkt) != 512:
sys.stderr.write("File length is not a multiple of 512 bytes")
raise SystemExit, 1
dump_packet(raw_pkt, outfile, dump_payload)
raw_pkt = infile.read(512)
def main():
parser = OptionParser()
parser.add_option('-p', '--dump-payload', action='store_true', default=False,
help='dump payload in decimal and hex')
(options, files) = parser.parse_args()
if len(files) == 0:
dump_packets(sys.stdin, sys.stdout, options.dump_payload)
else:
for f in files:
dump_packets(open(f, "r"), sys.stdout, options.dump_payload)
if __name__ == '__main__':
main()

View File

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

View File

@ -1,35 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <qa_inband.h>
#include <qa_inband_packet_prims.h>
#include <qa_inband_usrp_server.h>
CppUnit::TestSuite *
qa_inband::suite()
{
CppUnit::TestSuite *s = new CppUnit::TestSuite("inband");
s->addTest (qa_inband_packet_prims::suite());
s->addTest (qa_inband_usrp_server::suite());
return s;
}

View File

@ -1,35 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef INCLUDED_QA_INBAND_H
#define INCLUDED_QA_INBAND_H
#include <cppunit/TestSuite.h>
//! collect all the tests for the user server
class qa_inband {
public:
//! return suite of tests for all of usrp server
static CppUnit::TestSuite *suite();
};
#endif /* INCLUDED_QA_INBAND_H */

View File

@ -1,162 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <qa_inband_packet_prims.h>
#include <cppunit/TestAssert.h>
#include <stdio.h>
#include <string.h>
#include <usrp_inband_usb_packet.h> // will change on gigabit crossover
typedef usrp_inband_usb_packet transport_pkt;
void
qa_inband_packet_prims::test_flags()
{
transport_pkt pkt;
// Test each one of the flags while ensuring no other fields become set in the process
pkt.set_header(pkt.FL_START_OF_BURST,0,0,0);
CPPUNIT_ASSERT_EQUAL(1, pkt.start_of_burst());
CPPUNIT_ASSERT_EQUAL(0, pkt.end_of_burst());
CPPUNIT_ASSERT_EQUAL(0, pkt.overrun());
CPPUNIT_ASSERT_EQUAL(0, pkt.underrun());
CPPUNIT_ASSERT_EQUAL(0, pkt.dropped());
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
pkt.set_header(pkt.FL_END_OF_BURST,0,0,0);
CPPUNIT_ASSERT_EQUAL(0, pkt.start_of_burst());
CPPUNIT_ASSERT_EQUAL(1, pkt.end_of_burst());
CPPUNIT_ASSERT_EQUAL(0, pkt.overrun());
CPPUNIT_ASSERT_EQUAL(0, pkt.underrun());
CPPUNIT_ASSERT_EQUAL(0, pkt.dropped());
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
pkt.set_header(pkt.FL_OVERRUN,0,0,0);
CPPUNIT_ASSERT_EQUAL(0, pkt.start_of_burst());
CPPUNIT_ASSERT_EQUAL(0, pkt.end_of_burst());
CPPUNIT_ASSERT_EQUAL(1, pkt.overrun());
CPPUNIT_ASSERT_EQUAL(0, pkt.underrun());
CPPUNIT_ASSERT_EQUAL(0, pkt.dropped());
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
pkt.set_header(pkt.FL_UNDERRUN,0,0,0);
CPPUNIT_ASSERT_EQUAL(0, pkt.start_of_burst());
CPPUNIT_ASSERT_EQUAL(0, pkt.end_of_burst());
CPPUNIT_ASSERT_EQUAL(0, pkt.overrun());
CPPUNIT_ASSERT_EQUAL(1, pkt.underrun());
CPPUNIT_ASSERT_EQUAL(0, pkt.dropped());
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
pkt.set_header(pkt.FL_DROPPED,0,0,0);
CPPUNIT_ASSERT_EQUAL(0, pkt.start_of_burst());
CPPUNIT_ASSERT_EQUAL(0, pkt.end_of_burst());
CPPUNIT_ASSERT_EQUAL(0, pkt.overrun());
CPPUNIT_ASSERT_EQUAL(0, pkt.underrun());
CPPUNIT_ASSERT_EQUAL(1, pkt.dropped());
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
// test of all fields set
pkt.set_header(
pkt.FL_START_OF_BURST |
pkt.FL_END_OF_BURST |
pkt.FL_UNDERRUN |
pkt.FL_OVERRUN |
pkt.FL_DROPPED
,0,0,0);
CPPUNIT_ASSERT_EQUAL(1, pkt.start_of_burst());
CPPUNIT_ASSERT_EQUAL(1, pkt.end_of_burst());
CPPUNIT_ASSERT_EQUAL(1, pkt.overrun());
CPPUNIT_ASSERT_EQUAL(1, pkt.underrun());
CPPUNIT_ASSERT_EQUAL(1, pkt.dropped());
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
}
//////////////////////////////////////////////////////////////////////
void
qa_inband_packet_prims::test_fields()
{
transport_pkt pkt;
void * payload;
// test word0 field exclusiveness
//
// I want to test max values of each field to ensure field boundaries
// but these max values could change based on technology? The
// max payload is returned by a private method so the code is not
// technology dependent
pkt.set_header(0,16,0,0);
CPPUNIT_ASSERT_EQUAL(16, pkt.chan());
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
pkt.set_header(0,0,8,0);
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
CPPUNIT_ASSERT_EQUAL(8, pkt.tag());
CPPUNIT_ASSERT_EQUAL(0,pkt.payload_len());
pkt.set_header(0,0,0,pkt.max_payload());
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
CPPUNIT_ASSERT_EQUAL(pkt.max_payload(), pkt.payload_len());
// test timestamp, shouldn't have to test other fields since
// setting the timestamp only has the ability to affect one word
pkt.set_timestamp(54);
CPPUNIT_ASSERT_EQUAL(uint32_t(54), pkt.timestamp());
// test the payload, ensure no other fields overwritten
//
// is there a better test for this?
pkt.set_header(0,0,0,0);
payload = malloc(pkt.payload_len());
memset(payload, 'f', pkt.payload_len());
memcpy(pkt.payload(), payload, pkt.payload_len());
CPPUNIT_ASSERT_EQUAL(0, memcmp(pkt.payload(), payload, pkt.payload_len()));
CPPUNIT_ASSERT_EQUAL(0, pkt.start_of_burst());
CPPUNIT_ASSERT_EQUAL(0, pkt.end_of_burst());
CPPUNIT_ASSERT_EQUAL(0, pkt.overrun());
CPPUNIT_ASSERT_EQUAL(0, pkt.underrun());
CPPUNIT_ASSERT_EQUAL(0, pkt.dropped());
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
free(payload);
}
//////////////////////////////////////////////////////////////////////

View File

@ -1,41 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef QA_INBAND_PACKET_PRIMS_H
#define QA_INBAND_PACKET_PRIMS_H
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestCase.h>
class qa_inband_packet_prims : public CppUnit::TestCase {
CPPUNIT_TEST_SUITE(qa_inband_packet_prims);
CPPUNIT_TEST(test_flags);
CPPUNIT_TEST(test_fields);
CPPUNIT_TEST_SUITE_END();
private:
void test_flags();
void test_fields();
};
#endif /* INCLUDED_QA_INBAND_PACKET_PRIMS_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,50 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef QA_INBAND_USRP_SERVER_H
#define QA_INBAND_USRP_SERVER_H
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestCase.h>
class qa_inband_usrp_server : public CppUnit::TestCase {
CPPUNIT_TEST_SUITE(qa_inband_usrp_server);
CPPUNIT_TEST(test_open_close);
CPPUNIT_TEST(test_chan_allocation);
CPPUNIT_TEST(test_chan_deallocation);
CPPUNIT_TEST(test_tx);
CPPUNIT_TEST(test_rx);
CPPUNIT_TEST(test_cs);
CPPUNIT_TEST(test_rid);
CPPUNIT_TEST_SUITE_END();
private:
void test_chan_allocation();
void test_chan_deallocation();
void test_open_close();
void test_tx();
void test_rx();
void test_cs();
void test_rid();
};
#endif /* INCLUDED_QA_INBAND_USRP_SERVER_H */

View File

@ -1,40 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef INCLUDED_SYMBOLS_USRP_CHANNEL_H
#define INCLUDED_SYMBOLS_USRP_CHANNEL_H
#include <pmt.h>
// Outgoing
static pmt_t s_cmd_allocate_channel = pmt_intern("cmd-allocate-channel");
static pmt_t s_cmd_deallocate_channel = pmt_intern("cmd-deallocate-channel");
// Incoming
static pmt_t s_response_allocate_channel = pmt_intern("response-allocate-channel");
static pmt_t s_response_deallocate_channel = pmt_intern("response-deallocate-channel");
// Errors
static pmt_t s_err_requested_capacity_unavailable = pmt_intern("err-requested-capacity-unavailable");
static pmt_t s_err_channel_unavailable = pmt_intern("err-channel-unavailable");
static pmt_t s_err_channel_invalid = pmt_intern("err-channel-invalid");
static pmt_t s_err_channel_permission_denied = pmt_intern("err-channel-permission-denied");
#endif /* INCLUDED_SYMBOLS_USRP_CHANNEL_H */

View File

@ -1,43 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef INCLUDED_SYMBOLS_USRP_INTERFACE_CS_H
#define INCLUDED_SYMBOLS_USRP_INTERFACE_CS_H
#include <pmt.h>
// Outgoing
static pmt_t s_cmd_usrp_open = pmt_intern("cmd-usrp-open");
static pmt_t s_cmd_usrp_close = pmt_intern("cmd-usrp-close");
static pmt_t s_cmd_usrp_ntx_chan = pmt_intern("cmd-usrp-ntx-chan");
static pmt_t s_cmd_usrp_nrx_chan = pmt_intern("cmd-usrp-nrx-chan");
static pmt_t s_cmd_usrp_write = pmt_intern("cmd-usrp-write");
static pmt_t s_cmd_usrp_start_reading = pmt_intern("cmd-usrp-start-reading");
static pmt_t s_cmd_usrp_stop_reading = pmt_intern("cmd-usrp-stop-reading");
// Incoming
static pmt_t s_response_usrp_open = pmt_intern("response-usrp-open");
static pmt_t s_response_usrp_close = pmt_intern("response-usrp-close");
static pmt_t s_response_usrp_ntx_chan = pmt_intern("response-usrp-ntx-chan");
static pmt_t s_response_usrp_nrx_chan = pmt_intern("response-usrp-nrx-chan");
static pmt_t s_response_usrp_write = pmt_intern("response-usrp-write");
static pmt_t s_response_usrp_read = pmt_intern("response-usrp-read");
#endif /* INCLUDED_SYMBOLS_USRP_INTERFACE_CS_H */

View File

@ -1,47 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef INCLUDED_SYMBOLS_USRP_LOW_LEVEL_CS_H
#define INCLUDED_SYMBOLS_USRP_LOW_LEVEL_CS_H
#include <pmt.h>
// Outgoing
static pmt_t s_cmd_to_control_channel = pmt_intern("cmd-to-control-channel");
// Incoming
static pmt_t s_response_from_control_channel = pmt_intern("response-from-control-channel");
// Subpackets
static pmt_t s_op_ping_fixed = pmt_intern("op-ping-fixed");
static pmt_t s_op_ping_fixed_reply = pmt_intern("op-ping-fixed-reply");
static pmt_t s_op_write_reg = pmt_intern("op-write-reg");
static pmt_t s_op_write_reg_masked = pmt_intern("op-write-reg-masked");
static pmt_t s_op_read_reg = pmt_intern("op-read-reg");
static pmt_t s_op_read_reg_reply = pmt_intern("op-read-reg-reply");
static pmt_t s_op_i2c_write = pmt_intern("op-i2c-write");
static pmt_t s_op_i2c_read = pmt_intern("op-i2c-read");
static pmt_t s_op_i2c_read_reply = pmt_intern("op-i2c-read-reply");
static pmt_t s_op_spi_write = pmt_intern("op-spi-write");
static pmt_t s_op_spi_read = pmt_intern("op-spi-read");
static pmt_t s_op_spi_read_reply = pmt_intern("op-spi-read-reply");
static pmt_t s_op_delay = pmt_intern("op-delay");
#endif /* INCLUDED_SYMBOLS_USRP_LOW_LEVEL_CS_H */

View File

@ -1,36 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef INCLUDED_SYMBOLS_USRP_RX_H
#define INCLUDED_SYMBOLS_USRP_RX_H
#include <pmt.h>
// Outgoing
static pmt_t s_cmd_start_recv_raw_samples = pmt_intern("cmd-start-recv-raw-samples");
static pmt_t s_cmd_stop_recv_raw_samples = pmt_intern("cmd-stop-recv-raw-samples");
// Incoming
static pmt_t s_response_recv_raw_samples = pmt_intern("response-recv-raw-samples");
// Errors
static pmt_t s_err_already_receiving = pmt_intern("err-already-receiving");
#endif /* INCLUDED_SYMBOLS_USRP_RX_H */

View File

@ -1,32 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef INCLUDED_SYMBOLS_USRP_RX_CS_H
#define INCLUDED_SYMBOLS_USRP_RX_CS_H
#include <pmt.h>
// Outgoing
static pmt_t s_cmd_usrp_rx_start_reading = pmt_intern("cmd-usrp-rx-start-reading");
// Incoming
static pmt_t s_response_usrp_rx_read = pmt_intern("response-usrp-rx-read");
#endif /* INCLUDED_SYMBOLS_USRP_RX_CS_H */

View File

@ -1,47 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef INCLUDED_SYMBOLS_USRP_SERVER_CS_H
#define INCLUDED_SYMBOLS_USRP_SERVER_CS_H
#include <pmt.h>
// Outgoing
static pmt_t s_cmd_open = pmt_intern("cmd-open");
static pmt_t s_cmd_close = pmt_intern("cmd-close");
static pmt_t s_cmd_max_capacity = pmt_intern("cmd-max-capacity");
static pmt_t s_cmd_ntx_chan = pmt_intern("cmd-ntx-chan");
static pmt_t s_cmd_nrx_chan = pmt_intern("cmd-nrx-chan");
static pmt_t s_cmd_current_capacity_allocation = pmt_intern("cmd-current-capacity-allocation");
// Incoming
static pmt_t s_response_open = pmt_intern("response-open");
static pmt_t s_response_close = pmt_intern("response-close");
static pmt_t s_response_max_capacity = pmt_intern("response-max-capacity");
static pmt_t s_response_ntx_chan = pmt_intern("response-ntx-chan");
static pmt_t s_response_nrx_chan = pmt_intern("response-nrx-chan");
static pmt_t s_response_current_capacity_allocation = pmt_intern("response-current-capacity-allocation");
// Errors
static pmt_t s_err_usrp_not_opened = pmt_intern("err-usrp-not-opened");
static pmt_t s_err_usrp_already_opened = pmt_intern("err-usrp-already-opened");
static pmt_t s_err_usrp_already_closed = pmt_intern("err-usrp-already-closed");
#endif /* INCLUDED_SYMBOLS_USRP_SERVER_CS_H */

View File

@ -1,32 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef INCLUDED_SYMBOLS_USRP_TX_H
#define INCLUDED_SYMBOLS_USRP_TX_H
#include <pmt.h>
// Outgoing
static pmt_t s_cmd_xmit_raw_frame = pmt_intern("cmd-xmit-raw-frame");
// Incoming
static pmt_t s_response_xmit_raw_frame = pmt_intern("response-xmit-raw-frame");
#endif /* INCLUDED_SYMBOLS_USRP_TX_H */

View File

@ -1,32 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef INCLUDED_SYMBOLS_USRP_TX_CS_H
#define INCLUDED_SYMBOLS_USRP_TX_CS_H
#include <pmt.h>
// Outgoing
static pmt_t s_cmd_usrp_tx_write = pmt_intern("cmd-usrp-tx-write");
// Incoming
static pmt_t s_response_usrp_tx_write = pmt_intern("response-usrp-tx-write");
#endif /* INCLUDED_SYMBOLS_USRP_TX_CS_H */

View File

@ -1,36 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <cppunit/TextTestRunner.h>
#include <qa_inband.h>
int
main(int argc, char **argv)
{
CppUnit::TextTestRunner runner;
runner.addTest(qa_inband::suite ());
bool was_successful = runner.run("", false);
return was_successful ? 0 : 1;
}

View File

@ -1,115 +0,0 @@
#
# Copyright 2007 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# GNU Radio is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
import struct
FL_OVERRUN = 0x80000000
FL_UNDERRUN = 0x40000000
FL_DROPPED = 0x20000000
FL_END_OF_BURST = 0x10000000
FL_START_OF_BURST = 0x08000000
FL_ALL_FLAGS = 0xf8000000
FL_OVERRUN_SHIFT = 31
FL_UNDERRUN_SHIFT = 30
FL_DROPPED_SHIFT = 29
FL_END_OF_BURST_SHIFT = 28
FL_START_OF_BURST_SHIFT = 27
RSSI_MASK = 0x3f
RSSI_SHIFT = 21
CHAN_MASK = 0x1f
CHAN_SHIFT = 16
TAG_MASK = 0xf
TAG_SHIFT = 9
PAYLOAD_LEN_MASK = 0x1ff
PAYLOAD_LEN_SHIFT = 0
def make_header(flags, chan, payload_len, timestamp, rssi=0, tag=0):
word0 = ((flags & FL_ALL_FLAGS)
| ((rssi & RSSI_MASK) << RSSI_SHIFT)
| ((chan & CHAN_MASK) << CHAN_SHIFT)
| ((tag & TAG_MASK) << TAG_SHIFT)
| ((payload_len & PAYLOAD_LEN_MASK) << PAYLOAD_LEN_SHIFT))
word1 = timestamp
return struct.pack('<2I', word0, word1)
def _decode(pred, indicator):
if pred:
return indicator
else:
return '-'
class usb_packet(object):
def __init__(self, raw_pkt):
assert isinstance(raw_pkt, str) and len(raw_pkt) == 512
self._raw_pkt = raw_pkt;
(self._word0, self._word1) = struct.unpack('<2I', self._raw_pkt[0:8])
def timestamp(self):
return self._word1
def rssi(self):
return (self._word0 >> RSSI_SHIFT) & RSSI_MASK
def chan(self):
return (self._word0 >> CHAN_SHIFT) & CHAN_MASK
def tag(self):
return (self._word0 >> TAG_SHIFT) & TAG_MASK
def payload_len(self):
return (self._word0 >> PAYLOAD_LEN_SHIFT) & PAYLOAD_LEN_MASK
def flags(self):
return self._word0 & FL_ALL_FLAGS
def overrun(self):
return (self._word0 >> FL_OVERRUN_SHIFT) & 0x1
def underrun(self):
return (self._word0 >> FL_UNDERRUN_SHIFT) & 0x1
def start_of_burst(self):
return (self._word0 >> FL_START_OF_BURST_SHIFT) & 0x1
def end_of_burst(self):
return (self._word0 >> FL_END_OF_BURST_SHIFT) & 0x1
def dropped(self):
return (self._word0 >> FL_DROPPED_SHIFT) & 0x1
def payload(self):
return self._raw_pkt[8:8+self.payload_len()]
def decoded_flags(self):
s = (_decode(self.overrun(), 'O')
+ _decode(self.underrun(), 'U')
+ _decode(self.dropped(), 'D')
+ _decode(self.end_of_burst(), 'E')
+ _decode(self.start_of_burst(), 'S'))
return s

View File

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

View File

@ -1,240 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,2008 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef INCLUDED_USRP_INBAND_USB_PACKET_H_
#define INCLUDED_USRP_INBAND_USB_PACKET_H_
#include <usrp_bytesex.h>
#include <mblock/mblock.h>
#include <pmt.h>
#include <iostream>
#include <symbols_usrp_low_level_cs.h>
static const int USB_PKT_SIZE = 512; // bytes
static const int MAX_PAYLOAD = USB_PKT_SIZE-2*sizeof(uint32_t);
static const int CONTROL_CHAN = 0x1f;
class usrp_inband_usb_packet {
//
// keep raw packet in USRP-endian order
//
uint32_t d_word0;
uint32_t d_timestamp;
unsigned char d_payload[MAX_PAYLOAD];
public:
enum opcodes {
OP_PING_FIXED = 0x00,
OP_PING_FIXED_REPLY = 0x01,
OP_WRITE_REG = 0x02,
OP_WRITE_REG_MASKED = 0x03,
OP_READ_REG = 0x04,
OP_READ_REG_REPLY = 0x05,
OP_I2C_WRITE = 0x06,
OP_I2C_READ = 0x07,
OP_I2C_READ_REPLY = 0x08,
OP_SPI_WRITE = 0x09,
OP_SPI_READ = 0x0a,
OP_SPI_READ_REPLY = 0x0b,
OP_DELAY = 0x0c
};
enum flags {
FL_OVERRUN = 0x80000000,
FL_UNDERRUN = 0x40000000,
FL_DROPPED = 0x20000000,
FL_START_OF_BURST = 0x10000000,
FL_END_OF_BURST = 0x08000000,
FL_CARRIER_SENSE = 0x04000000,
FL_ALL_FLAGS = 0xfc000000
};
static const int FL_OVERRUN_SHIFT = 31;
static const int FL_UNDERRUN_SHIFT = 30;
static const int FL_DROPPED_SHIFT = 29;
static const int FL_END_OF_BURST_SHIFT = 27;
static const int FL_START_OF_BURST_SHIFT = 28;
static const int RSSI_MASK = 0x3f;
static const int RSSI_SHIFT = 21;
static const int CHAN_MASK = 0x1f;
static const int CHAN_SHIFT = 16;
static const int TAG_MASK = 0xf;
static const int TAG_SHIFT = 9;
static const int PAYLOAD_LEN_MASK = 0x1ff;
static const int PAYLOAD_LEN_SHIFT = 0;
// Fixed size for opcode and length fields
static const int CS_FIXED_LEN = 2;
static const int CS_OPCODE_MASK = 0xff;
static const int CS_OPCODE_SHIFT = 24;
static const int CS_LEN_MASK = 0xff;
static const int CS_LEN_SHIFT = 16;
static const int CS_RID_MASK = 0x3f;
static const int CS_RID_SHIFT = 10;
static const int CS_PING_LEN = 2;
static const int CS_PINGVAL_MASK = 0x3ff;
static const int CS_PINGVAL_SHIFT = 0;
static const int CS_WRITEREG_LEN = 6;
static const int CS_WRITEREGMASKED_LEN = 10;
static const int CS_READREG_LEN = 2;
static const int CS_READREGREPLY_LEN = 6;
static const int CS_REGNUM_MASK = 0x3ff;
static const int CS_REGNUM_SHIFT = 0;
static const int CS_DELAY_LEN = 2;
static const int CS_DELAY_MASK = 0xffff;
static const int CS_DELAY_SHIFT = 0;
static const int CS_I2CADDR_MASK = 0x7f;
static const int CS_I2CADDR_SHIFT = 0;
static const int CS_I2CREAD_LEN = 3;
static const int CS_I2CREADBYTES_MASK = 0x7f;
static const int CS_I2CREADBYTES_SHIFT = 24;
static const int CS_SPIOPT_MASK = 0xffff;
static const int CS_SPIOPT_SHIFT = 0;
static const int CS_SPIFORMAT_MASK = 0xff;
static const int CS_SPIFORMAT_SHIFT = 16;
static const int CS_SPIENABLES_MASK = 0xff;
static const int CS_SPIENABLES_SHIFT = 24;
static const int CS_SPIREAD_LEN = 7;
static const int CS_SPINBYTES_MASK = 0xff;
static const int CS_SPINBYTES_SHIFT = 24;
public:
void set_timestamp(uint32_t timestamp){
d_timestamp = host_to_usrp_u32(timestamp);
}
void set_end_of_burst() {
uint32_t word0 = usrp_to_host_u32(d_word0);
word0 |= 1<<FL_END_OF_BURST_SHIFT;
d_word0 = host_to_usrp_u32(word0);
}
void set_header(int flags, int chan, int tag, int payload_len){
uint32_t word0 = ((flags & FL_ALL_FLAGS)
| ((chan & CHAN_MASK) << CHAN_SHIFT)
| ((tag & TAG_MASK) << TAG_SHIFT)
| ((payload_len & PAYLOAD_LEN_MASK) << PAYLOAD_LEN_SHIFT));
d_word0 = host_to_usrp_u32(word0);
}
void incr_header_len(int val) {
set_header(flags(), chan(), tag(), payload_len() + val);
}
uint32_t timestamp() const {
return usrp_to_host_u32(d_timestamp);
}
int rssi() const {
uint32_t word0 = usrp_to_host_u32(d_word0);
return (word0 >> RSSI_SHIFT) & RSSI_MASK;
}
int chan() const {
uint32_t word0 = usrp_to_host_u32(d_word0);
return (word0 >> CHAN_SHIFT) & CHAN_MASK;
}
int tag() const {
uint32_t word0 = usrp_to_host_u32(d_word0);
return (word0 >> TAG_SHIFT) & TAG_MASK;
}
int payload_len() const {
uint32_t word0 = usrp_to_host_u32(d_word0);
return (word0 >> PAYLOAD_LEN_SHIFT) & PAYLOAD_LEN_MASK;
}
int flags() const {
return usrp_to_host_u32(d_word0) & FL_ALL_FLAGS;
}
int overrun() const {
return (usrp_to_host_u32(d_word0) & FL_OVERRUN) >> FL_OVERRUN_SHIFT;
}
int underrun() const {
return (usrp_to_host_u32(d_word0) & FL_UNDERRUN) >> FL_UNDERRUN_SHIFT;
}
int start_of_burst() const {
return (usrp_to_host_u32(d_word0) & FL_START_OF_BURST) >> FL_START_OF_BURST_SHIFT;
}
int end_of_burst() const {
return (usrp_to_host_u32(d_word0) & FL_END_OF_BURST) >> FL_END_OF_BURST_SHIFT;
}
int dropped() const {
return (usrp_to_host_u32(d_word0) & FL_DROPPED) >> FL_DROPPED_SHIFT;
}
unsigned char *payload() {
return d_payload;
}
static int max_payload() {
return MAX_PAYLOAD;
}
static int max_pkt_size() {
return USB_PKT_SIZE;
}
// C/S methods
bool align32();
bool cs_ping(long rid, long ping_val);
bool cs_ping_reply(long rid, long ping_val);
bool cs_write_reg(long reg_num, long val);
bool cs_write_reg_masked(long reg_num, long val, long mask);
bool cs_read_reg(long rid, long reg_num);
bool cs_read_reg_reply(long rid, long reg_num, long reg_val);
bool cs_delay(long ticks);
bool cs_i2c_write(long i2c_addr, uint8_t *i2c_data, size_t data_len);
bool cs_i2c_read(long rid, long i2c_addr, long n_bytes);
bool cs_i2c_read_reply(long rid, long i2c_addr, uint8_t *i2c_data, long i2c_data_len);
bool cs_spi_write(long enables, long format, long opt_header_bytes, uint8_t *spi_data, long spi_data_len);
bool cs_spi_read(long rid, long enables, long format, long opt_header_bytes, long n_bytes);
bool cs_spi_read_reply(long rid, uint8_t *spi_data, long spi_data_len);
int cs_len(int payload_offset);
pmt_t read_subpacket(int payload_offset);
};
#endif

View File

@ -1,88 +0,0 @@
;; -*- scheme -*- ; not really, but tells emacs how to format this
;;
;; Copyright 2007 Free Software Foundation, Inc.
;;
;; This file is part of GNU Radio
;;
;; GNU Radio is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
;;
;; GNU Radio is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License along
;; with this program; if not, write to the Free Software Foundation, Inc.,
;; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
;;
;; ----------------------------------------------------------------
;; This is an mblock header file
;;
;; The format is very much a work-in-progress.
;; It'll be compiled to C++.
;; ----------------------------------------------------------------
;; ----------------------------------------------------------------
;; usrp-interface-cs
;;
;; Handles interaction between the usrp_sever and the USB interface
(define-protocol-class usrp-interface-cs
(:outgoing
(cmd-usrp-open invocation-handle which-usrp)
(cmd-usrp-close invocation-handle)
(cmd-usrp-ntx-chan invocation-handle)
(cmd-usrp-nrx-chan invocation-handle)
(cmd-usrp-write invocation-handle channel data)
(cmd-usrp-start-reading invocation-handle channel)
)
(:incoming
(response-usrp-open invocation-handle status)
(response-usrp-close invocation-handle status)
(response-usrp-ntx-chan invocation-handle ntx-chan)
(response-usrp-nrx-chan invocation-handle nrx-chan)
(response-usrp-write invocation-handle status channel)
(response-usrp-read invocation-handle status data)
)
)
;; ----------------------------------------------------------------
;; usrp-tx-cs
;;
;; Handles interaction between the USB interface and TX interface
(define-protocol-class usrp-tx-cs
(:outgoing
(cmd-usrp-tx-write invocation-handle channel data tx-handle)
)
(:incoming
(response-usrp-tx-write invocation-handle status channel)
)
)
;; ----------------------------------------------------------------
;; usrp-rx-cs
;;
;; Handles interaction between the USB interface and RX interface
(define-protocol-class usrp-rx-cs
(:outgoing
(cmd-usrp-rx-start-reading invocation-handle rx-handle)
(cmd-usrp-rx-stop-reading invocation-handle)
)
(:incoming
(response-usrp-rx-read invocation-handle status data)
;; There is currently no response to a stop reading
)
)

View File

@ -1,184 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <usrp_rx.h>
#include <usrp_standard.h>
#include <iostream>
#include <vector>
#include <usb.h>
#include <mblock/class_registry.h>
#include <usrp_inband_usb_packet.h>
#include <fpga_regs_common.h>
#include <stdio.h>
#include <symbols_usrp_rx_cs.h>
typedef usrp_inband_usb_packet transport_pkt;
static const bool verbose = false;
bool usrp_rx_stop;
usrp_rx::usrp_rx(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg)
: mb_mblock(rt, instance_name, user_arg),
d_disk_write(false),
d_disk_write_pkt(false) // if true, writes full packet, else just the payload
{
d_cs = define_port("cs", "usrp-rx-cs", true, mb_port::EXTERNAL);
if(d_disk_write) {
d_ofile0.open("rx_data_chan0.dat",std::ios::binary|std::ios::out);
d_ofile1.open("rx_data_chan1.dat",std::ios::binary|std::ios::out);
d_cs_ofile.open("rx_cs.dat",std::ios::binary|std::ios::out);
}
usrp_rx_stop = false;
}
usrp_rx::~usrp_rx()
{
if(d_disk_write) {
d_ofile0.close();
d_ofile1.close();
d_cs_ofile.close();
}
}
void
usrp_rx::initial_transition()
{
}
/*!
* \brief Handles incoming signals to to the m-block, wihch should only ever be
* a single message: cmd-usrrp-rx-start-reading. There is no signal to stop
* reading as the m-block goes in to a forever loop to read inband packets from
* the bus.
*/
void
usrp_rx::handle_message(mb_message_sptr msg)
{
pmt_t event = msg->signal();
pmt_t port_id = msg->port_id();
pmt_t data = msg->data();
// Theoretically only have 1 message to ever expect, but
// want to make sure its at least what we want
if(pmt_eq(port_id, d_cs->port_symbol())) {
if(pmt_eqv(event, s_cmd_usrp_rx_start_reading))
read_and_respond(data);
}
}
/*!
* \brief Performs the actual reading of data from the USB bus, called by
* handle_message() when a cmd-usrp-rx-start-reading signal is received.
*
* The method enters a forever loop where it continues to read data from the bus
* and generate read responses to the higher layer. Currently, shared memory is
* used to exit this loop.
*
* The \p data parameter is a PMT list which contains only a single element, an
* invocation handle which will be returned with all read respones.
*/
void
usrp_rx::read_and_respond(pmt_t data)
{
size_t ignore;
bool underrun;
unsigned int n_read;
unsigned int pkt_size = sizeof(transport_pkt);
pmt_t invocation_handle = pmt_nth(0, data);
// Need the handle to the RX port to send responses, this is passed
// by the USRP interface m-block
pmt_t handle = pmt_nth(1, data);
d_urx =
boost::any_cast<usrp_standard_rx_sptr>(pmt_any_ref(handle));
if(verbose)
std::cout << "[usrp_rx] Waiting for packets..\n";
// Read by 512 which is packet size and send them back up
while(!usrp_rx_stop) {
pmt_t v_pkt = pmt_make_u8vector(pkt_size, 0);
transport_pkt *pkt =
(transport_pkt *) pmt_u8vector_writable_elements(v_pkt, ignore);
n_read = d_urx->read(pkt, pkt_size, &underrun);
if(n_read != pkt_size) {
std::cerr << "[usrp_rx] Error reading packet, shutting down\n";
d_cs->send(s_response_usrp_rx_read,
pmt_list3(PMT_NIL, PMT_F, PMT_NIL));
return;
}
if(underrun && verbose && 0)
std::cout << "[usrp_rx] Underrun\n";
d_cs->send(s_response_usrp_rx_read,
pmt_list3(PMT_NIL, PMT_T, v_pkt));
if(verbose && 0)
std::cout << "[usrp_rx] Read 1 packet\n";
if(d_disk_write) {
if(pkt->chan() == CONTROL_CHAN)
d_cs_ofile.write((const char *)pkt, transport_pkt::max_pkt_size());
else {
if(d_disk_write_pkt) {
if(pkt->chan() == 0)
d_ofile0.write((const char *)pkt, transport_pkt::max_pkt_size());
else if(pkt->chan() == 1)
d_ofile1.write((const char *)pkt, transport_pkt::max_pkt_size());
} else {
if(pkt->chan() == 0)
d_ofile0.write((const char *)pkt->payload(), transport_pkt::max_payload());
else if(pkt->chan() == 1)
d_ofile1.write((const char *)pkt->payload(), transport_pkt::max_payload());
}
}
d_cs_ofile.flush();
d_ofile0.flush();
d_ofile1.flush();
}
}
usrp_rx_stop = false;
if(verbose) {
std::cout << "[USRP_RX] Stopping...\n";
fflush(stdout);
}
}
REGISTER_MBLOCK_CLASS(usrp_rx);

View File

@ -1,58 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,2008 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef INCLUDED_USRP_RX_H
#define INCLUDED_USRP_RX_H
#include <mblock/mblock.h>
#include <fstream>
#include "usrp_standard.h"
extern bool usrp_rx_stop; // used to communicate a 'stop' to the RX stub
/*!
* \brief Implements the low level usb interface to the USRP
*/
class usrp_rx : public mb_mblock
{
mb_port_sptr d_cs;
usrp_standard_rx_sptr d_urx;
bool d_disk_write;
bool d_disk_write_pkt;
std::ofstream d_ofile0;
std::ofstream d_ofile1;
std::ofstream d_cs_ofile;
public:
usrp_rx(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
~usrp_rx();
void initial_transition();
void handle_message(mb_message_sptr msg);
private:
void read_and_respond(pmt_t data);
void read_data();
};
#endif /* INCLUDED_USRP_RX_H */

View File

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

View File

@ -1,79 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,2008 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef INCLUDED_USRP_RX_STUB_H
#define INCLUDED_USRP_RX_STUB_H
#include <mblock/mblock.h>
#include <vector>
#include "usrp_standard.h"
#include <ui_nco.h>
#include <fstream>
#include <queue>
#include <usrp_inband_usb_packet.h>
typedef usrp_inband_usb_packet transport_pkt;
extern bool usrp_rx_stop_stub; // used to communicate a 'stop' to the RX stub
extern std::queue<pmt_t> d_cs_queue;
static pmt_t s_timeout = pmt_intern("%timeout");
static pmt_t s_done = pmt_intern("done");
/*!
* \brief Implements the low level usb interface to the USRP
*/
class usrp_rx_stub : public mb_mblock
{
public:
mb_port_sptr d_cs;
usrp_standard_rx* d_urx;
long d_samples_per_frame;
long d_decim_rx;
mb_time d_t0;
double d_delta_t;
// for generating sine wave output
ui_nco<float,float> d_nco;
double d_amplitude;
bool d_disk_write;
std::ofstream d_ofile;
public:
usrp_rx_stub(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
~usrp_rx_stub();
void initial_transition();
void handle_message(mb_message_sptr msg);
private:
void read_and_respond();
void read_data();
void start_packet_timer();
};
#endif /* INCLUDED_USRP_RX_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,131 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,2008 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef INCLUDED_USRP_SERVER_H
#define INCLUDED_USRP_SERVER_H
#include <mblock/mblock.h>
#include <vector>
#include <queue>
#include <fstream>
#include <usrp_inband_usb_packet.h>
typedef usrp_inband_usb_packet transport_pkt; // makes conversion to gigabit easy
/*!
* \brief Implements the lowest-level mblock usb_interface to the USRP
*/
class usrp_server : public mb_mblock
{
public:
// our ports
enum port_types {
RX_PORT = 0,
TX_PORT = 1
};
static const int N_PORTS = 4;
std::vector<mb_port_sptr> d_tx, d_rx;
mb_port_sptr d_cs;
mb_port_sptr d_cs_usrp;
static const int D_USB_CAPACITY = 32 * 1024 * 1024;
static const int D_MAX_CHANNELS = 16;
long d_ntx_chan;
long d_nrx_chan;
pmt_t d_usrp_dict;
bool d_fpga_debug;
long d_interp_tx;
long d_decim_rx;
// Keep track of the request IDs
struct rid_info {
pmt_t owner;
long user_rid;
rid_info() {
owner = PMT_NIL;
user_rid = 0;
}
};
static const long D_MAX_RID = 64;
std::vector<rid_info> d_rids;
struct channel_info {
long assigned_capacity; // the capacity currently assignedby the channel
pmt_t owner; // port ID of the owner of the channel
channel_info() {
assigned_capacity = 0;
owner = PMT_NIL;
}
};
long d_rx_chan_mask; // A bitmask representing the channels in the
// receiving state
std::vector<struct channel_info> d_chaninfo_tx;
std::vector<struct channel_info> d_chaninfo_rx;
std::queue<mb_message_sptr> d_defer_queue;
bool d_defer;
bool d_opened;
bool d_fake_rx;
public:
usrp_server(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
~usrp_server();
void initial_transition();
void handle_message(mb_message_sptr msg);
protected:
static int max_capacity() { return D_USB_CAPACITY; }
private:
void handle_cmd_allocate_channel(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data);
void handle_cmd_deallocate_channel(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data);
void handle_cmd_xmit_raw_frame(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data);
void handle_cmd_to_control_channel(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data);
void handle_cmd_start_recv_raw_samples(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data);
void handle_cmd_stop_recv_raw_samples(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data);
int rx_port_index(pmt_t port_id);
int tx_port_index(pmt_t port_id);
long current_capacity_allocation();
void recall_defer_queue();
void reset_channels();
void handle_response_usrp_read(pmt_t data);
bool check_valid(mb_port_sptr port, long channel, std::vector<struct channel_info> &chan_info, pmt_t signal_info);
void parse_control_pkt(pmt_t invocation_handle, transport_pkt *pkt);
long next_rid();
void initialize_registers();
void set_register(long reg, long val);
void read_register(long reg);
void check_register_initialization();
void reset_all_registers();
};
#endif /* INCLUDED_USRP_SERVER_H */

View File

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

View File

@ -1,150 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,2008 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <usrp_tx.h>
#include <iostream>
#include <usb.h>
#include <mblock/class_registry.h>
#include <usrp_inband_usb_packet.h>
#include <fpga_regs_common.h>
#include <usrp_standard.h>
#include <stdio.h>
#include <symbols_usrp_tx_cs.h>
typedef usrp_inband_usb_packet transport_pkt;
static const bool verbose = false;
usrp_tx::usrp_tx(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg)
: mb_mblock(rt, instance_name, user_arg),
d_disk_write(false)
{
d_cs = define_port("cs", "usrp-tx-cs", true, mb_port::EXTERNAL);
//d_disk_write=true;
if(d_disk_write) {
d_ofile.open("tx_data.dat",std::ios::binary|std::ios::out);
d_cs_ofile.open("tx_cs.dat",std::ios::binary|std::ios::out);
}
}
usrp_tx::~usrp_tx()
{
if(d_disk_write) {
d_ofile.close();
d_cs_ofile.close();
}
}
void
usrp_tx::initial_transition()
{
}
/*!
* \brief Handles incoming signals to to the m-block, wihch should only ever be
* a single message: cmd-usrp-tx-write.
*/
void
usrp_tx::handle_message(mb_message_sptr msg)
{
pmt_t event = msg->signal();
pmt_t port_id = msg->port_id();
pmt_t data = msg->data();
// Theoretically only have 1 message to ever expect, but
// want to make sure its at least what we want
if(pmt_eq(port_id, d_cs->port_symbol())) {
if(pmt_eqv(event, s_cmd_usrp_tx_write))
write(data);
}
}
/*!
* \brief Performs the actual writing of data to the USB bus, called by
* handle_message() when a cmd-usrp-tx-write signal is received.
*
* The \p data parameter is a PMT list which contains three mandatory elements,
* in the following order: an invocation handle, a channel, and a uniform vector
* of memory which contains the packets to be written to the bus.
*/
void
usrp_tx::write(pmt_t data)
{
pmt_t invocation_handle = pmt_nth(0, data);
pmt_t channel = pmt_nth(1, data);
pmt_t v_packets = pmt_nth(2, data);
d_utx = boost::any_cast<usrp_standard_tx_sptr>(pmt_any_ref(pmt_nth(3, data)));
size_t n_bytes;
bool underrun; // this will need to go, as it is taken care of in the packet headers
transport_pkt *pkts = (transport_pkt *) pmt_u8vector_writable_elements(v_packets, n_bytes);
int ret = d_utx->write (pkts, n_bytes, &underrun);
if (0 && underrun)
fprintf(stderr, "uU");
if (ret == (int) n_bytes) {
if (verbose)
std::cout << "[usrp_server] Write of " << n_bytes << " successful\n";
// need to respond with the channel so the USRP server knows who to forward the result of
// the write to by looking up the owner of the channel
d_cs->send(s_response_usrp_tx_write,
pmt_list3(invocation_handle, PMT_T, channel));
}
else {
if (verbose)
std::cout << "[usrp_server] Error writing " << n_bytes << " bytes to USB bus\n";
d_cs->send(s_response_usrp_tx_write,
pmt_list3(invocation_handle, PMT_F, channel));
}
long n_packets =
static_cast<long>(std::ceil(n_bytes / (double)transport_pkt::max_pkt_size()));
for(int i=0; i < n_packets; i++) {
if(d_disk_write) {
if(pkts[i].chan() == CONTROL_CHAN)
d_cs_ofile.write((const char *)&pkts[i], transport_pkt::max_pkt_size());
else
d_ofile.write((const char *)&pkts[i], transport_pkt::max_pkt_size());
d_cs_ofile.flush();
d_ofile.flush();
}
}
return;
}
REGISTER_MBLOCK_CLASS(usrp_tx);

View File

@ -1,52 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,2008 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef INCLUDED_USRP_TX_H
#define INCLUDED_USRP_TX_H
#include <mblock/mblock.h>
#include <fstream>
#include "usrp_standard.h"
/*!
* \brief Implements the low level usb interface to the USRP
*/
class usrp_tx : public mb_mblock
{
mb_port_sptr d_cs;
usrp_standard_tx_sptr d_utx;
bool d_disk_write;
std::ofstream d_ofile;
std::ofstream d_cs_ofile;
public:
usrp_tx(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
~usrp_tx();
void initial_transition();
void handle_message(mb_message_sptr msg);
private:
void write(pmt_t data);
};
#endif /* INCLUDED_USRP_TX_H */

View File

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

View File

@ -1,61 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,2008 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef INCLUDED_USRP_TX_STUB_H
#define INCLUDED_USRP_TX_STUB_H
#include <mblock/mblock.h>
#include <vector>
#include "usrp_standard.h"
#include <fstream>
#include <usrp_inband_usb_packet.h>
typedef usrp_inband_usb_packet transport_pkt;
/*!
* \brief Implements the low level usb interface to the USRP
*/
class usrp_tx_stub : public mb_mblock
{
public:
mb_port_sptr d_cs;
usrp_standard_tx* d_utx;
std::ofstream d_ofile;
std::ofstream d_cs_ofile;
bool d_disk_write;
public:
usrp_tx_stub(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
~usrp_tx_stub();
void initial_transition();
void handle_message(mb_message_sptr msg);
private:
void write(pmt_t data);
void parse_cs(pmt_t invocation_handle, transport_pkt pkt);
};
#endif /* INCLUDED_USRP_TX_STUB_H */

View File

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

View File

@ -1,78 +0,0 @@
/* -*- c++ -*- */
/*
* Copyright 2007,2008 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef INCLUDED_USRP_USB_INTERFACE_H
#define INCLUDED_USRP_USB_INTERFACE_H
#include <mblock/mblock.h>
#include <vector>
#include "usrp_standard.h"
/*!
* \brief Implements the low level usb interface to the USRP
*/
class usrp_usb_interface : public mb_mblock
{
public:
usrp_standard_tx_sptr d_utx;
usrp_standard_rx_sptr d_urx;
boost::shared_ptr<usrp_basic> d_ub_tx;
boost::shared_ptr<usrp_basic> d_ub_rx;
mb_port_sptr d_cs;
mb_port_sptr d_rx_cs;
mb_port_sptr d_tx_cs;
long d_ntx_chan;
long d_nrx_chan;
bool d_fake_usrp;
bool d_rx_reading;
long d_interp_tx;
long d_decim_rx;
double d_rf_freq;
std::string d_rbf;
public:
usrp_usb_interface(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
~usrp_usb_interface();
void initial_transition();
void handle_message(mb_message_sptr msg);
usrp_subdev_spec pick_rx_subdevice();
usrp_subdev_spec pick_tx_subdevice();
usrp_subdev_spec pick_subdev(boost::shared_ptr<usrp_basic> d_usrp_basic, std::vector<int> candidates);
private:
void handle_cmd_open(pmt_t data);
void handle_cmd_close(pmt_t data);
void handle_cmd_write(pmt_t data);
void handle_cmd_start_reading(pmt_t data);
void handle_cmd_stop_reading(pmt_t data);
};
#endif /* INCLUDED_USRP_USB_INTERFACE_H */