mirror of https://gerrit.osmocom.org/libusrp
Remove mblock library. We hardly knew 'ye.
This commit is contained in:
parent
6ef29ec6b2
commit
1815e30065
|
@ -1,35 +0,0 @@
|
|||
/Makefile
|
||||
/Makefile.in
|
||||
/.la
|
||||
/.lo
|
||||
/.deps
|
||||
/.libs
|
||||
/*.la
|
||||
/*.lo
|
||||
/*.dat
|
||||
/.*.swp
|
||||
/usrper
|
||||
/usrper2
|
||||
/test_input
|
||||
/test_fusb
|
||||
/test_usrp
|
||||
/test_usrp0
|
||||
/test_usrp_standard_rx
|
||||
/test_usrp_standard_tx
|
||||
/test_usrp_standard_2tx
|
||||
/test_usrp_inband_timestamps
|
||||
/test_usrp_inband_registers
|
||||
/test_usrp_inband_rx
|
||||
/test_usrp_inband_2rx
|
||||
/test_usrp_inband_tx
|
||||
/test_usrp_inband_2tx
|
||||
/test_usrp_basic_rx
|
||||
/check_order_quickly
|
||||
/usrp_cal_dc_offset
|
||||
/test_usrp_inband_cs
|
||||
/read_packets
|
||||
/test_usrp_inband_ping
|
||||
/test_usrp_inband_underrun
|
||||
/test_usrp_inband_overrun
|
||||
/gmac_mbh.cc
|
||||
/test_gmac_tx
|
|
@ -1,77 +0,0 @@
|
|||
#
|
||||
# Copyright 2003,2006,2008 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of GNU Radio
|
||||
#
|
||||
# GNU Radio is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# GNU Radio is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with GNU Radio; see the file COPYING. If not, write to
|
||||
# the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
include $(top_srcdir)/Makefile.common
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
$(DEFINES) $(OMNITHREAD_INCLUDES) $(PMT_INCLUDES) $(MBLOCK_INCLUDES) \
|
||||
$(USRP_INCLUDES) $(USRP_INBAND_INCLUDES) $(BOOST_CPPFLAGS) \
|
||||
$(CPPUNIT_INCLUDES) $(WITH_INCLUDES) -I$(top_srcdir)/mblock/src/lib
|
||||
|
||||
|
||||
bin_PROGRAMS =
|
||||
|
||||
noinst_PROGRAMS = \
|
||||
test_usrp_inband_ping \
|
||||
test_usrp_inband_registers \
|
||||
test_usrp_inband_rx \
|
||||
test_usrp_inband_2rx \
|
||||
test_usrp_inband_tx \
|
||||
test_usrp_inband_2tx \
|
||||
test_usrp_inband_timestamps \
|
||||
test_usrp_inband_overrun \
|
||||
test_usrp_inband_underrun \
|
||||
read_packets
|
||||
|
||||
noinst_HEADERS = \
|
||||
ui_nco.h \
|
||||
ui_sincos.h
|
||||
|
||||
|
||||
test_usrp_inband_ping_SOURCES = test_usrp_inband_ping.cc
|
||||
test_usrp_inband_ping_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
|
||||
|
||||
test_usrp_inband_tx_SOURCES = test_usrp_inband_tx.cc ui_sincos.c
|
||||
test_usrp_inband_tx_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
|
||||
|
||||
test_usrp_inband_2tx_SOURCES = test_usrp_inband_2tx.cc ui_sincos.c
|
||||
test_usrp_inband_2tx_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
|
||||
|
||||
test_usrp_inband_timestamps_SOURCES = test_usrp_inband_timestamps.cc ui_sincos.c
|
||||
test_usrp_inband_timestamps_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
|
||||
|
||||
test_usrp_inband_registers_SOURCES = test_usrp_inband_registers.cc ui_sincos.c
|
||||
test_usrp_inband_registers_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
|
||||
|
||||
test_usrp_inband_overrun_SOURCES = test_usrp_inband_overrun.cc
|
||||
test_usrp_inband_overrun_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
|
||||
|
||||
test_usrp_inband_underrun_SOURCES = test_usrp_inband_underrun.cc
|
||||
test_usrp_inband_underrun_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
|
||||
|
||||
test_usrp_inband_rx_SOURCES = test_usrp_inband_rx.cc ui_sincos.c
|
||||
test_usrp_inband_rx_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
|
||||
|
||||
test_usrp_inband_2rx_SOURCES = test_usrp_inband_2rx.cc ui_sincos.c
|
||||
test_usrp_inband_2rx_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
|
||||
|
||||
read_packets_SOURCES = read_packets.cc
|
||||
read_packets_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
|
|
@ -1,109 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007,2008 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
#include <usrp_inband_usb_packet.h>
|
||||
#include <mblock/class_registry.h>
|
||||
#include <vector>
|
||||
#include <usrp_usb_interface.h>
|
||||
#include <fstream>
|
||||
|
||||
typedef usrp_inband_usb_packet transport_pkt; // makes conversion to gigabit easy
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
if(argc !=2) {
|
||||
std::cout << "Usage: ./read_packets <data_file>\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::ifstream infile;
|
||||
std::ofstream outfile;
|
||||
|
||||
unsigned int pkt_size = transport_pkt::max_pkt_size();
|
||||
unsigned int pkt_num=0;
|
||||
|
||||
transport_pkt *pkt;
|
||||
char pkt_data[pkt_size]; // allocate the number of bytes for a single packet
|
||||
|
||||
pkt = (transport_pkt *)pkt_data; // makes operations cleaner to read
|
||||
|
||||
// Open the file and read the packets, dumping information
|
||||
infile.open(argv[1], std::ios::binary|std::ios::in);
|
||||
if(!infile.is_open())
|
||||
exit(-1);
|
||||
|
||||
//outfile.open("dump.dat",std::ios::out|std::ios::binary);
|
||||
|
||||
// read 1 packet in to the memory
|
||||
infile.read(pkt_data, pkt_size);
|
||||
|
||||
while(!infile.eof()) {
|
||||
|
||||
printf("Packet %u\n", pkt_num);
|
||||
|
||||
if(pkt->start_of_burst())
|
||||
printf("\tstart of burst\n");
|
||||
|
||||
if(pkt->end_of_burst())
|
||||
printf("\tend of burst\n");
|
||||
|
||||
// if(pkt->carrier_sense())
|
||||
// printf("\tcarrier sense\n");
|
||||
|
||||
if(pkt->underrun())
|
||||
printf("\tunderrun\n");
|
||||
|
||||
if(pkt->overrun())
|
||||
printf("\toverrun\n");
|
||||
|
||||
printf("\tchannel: \t0x%x\n", pkt->chan());
|
||||
printf("\ttimestamp: \t0x%x\n", pkt->timestamp());
|
||||
//printf("\ttimestamp: \t%u\n", pkt->timestamp());
|
||||
printf("\tlength: \t%u\n", pkt->payload_len());
|
||||
printf("\trssi: \t%u\n", pkt->rssi());
|
||||
|
||||
printf("\tpayload: \n");
|
||||
for(int i=0; i < pkt->payload_len(); i++)
|
||||
//for(int i=0; i < pkt->max_payload(); i++)
|
||||
{
|
||||
printf("\t%d\t0x%x\n", i, *(pkt->payload()+i));
|
||||
//outfile.write((const char*)(pkt->payload()+i),1);
|
||||
//printf("\t\t0x%x\n", pkt->payload()+i);
|
||||
|
||||
}
|
||||
printf("\n\n");
|
||||
|
||||
pkt_num++;
|
||||
|
||||
// read 1 packet in to the memory
|
||||
infile.read(pkt_data, pkt_size);
|
||||
|
||||
}
|
||||
|
||||
infile.close();
|
||||
//outfile.close();
|
||||
|
||||
}
|
|
@ -1,371 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007,2008 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <mblock/mblock.h>
|
||||
#include <mblock/runtime.h>
|
||||
#include <mb_runtime_nop.h> // QA only
|
||||
#include <mblock/protocol_class.h>
|
||||
#include <mblock/exception.h>
|
||||
#include <mblock/msg_queue.h>
|
||||
#include <mblock/message.h>
|
||||
#include <mb_mblock_impl.h>
|
||||
#include <mblock/msg_accepter.h>
|
||||
#include <mblock/class_registry.h>
|
||||
#include <pmt.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
// Include the symbols needed for communication with USRP server
|
||||
#include <symbols_usrp_server_cs.h>
|
||||
#include <symbols_usrp_channel.h>
|
||||
#include <symbols_usrp_low_level_cs.h>
|
||||
#include <symbols_usrp_rx.h>
|
||||
|
||||
static bool verbose = true;
|
||||
|
||||
class test_usrp_rx : public mb_mblock
|
||||
{
|
||||
mb_port_sptr d_rx;
|
||||
mb_port_sptr d_cs;
|
||||
pmt_t d_rx_chan0, d_rx_chan1;
|
||||
|
||||
enum state_t {
|
||||
INIT,
|
||||
OPENING_USRP,
|
||||
ALLOCATING_CHANNEL,
|
||||
RECEIVING,
|
||||
CLOSING_CHANNEL,
|
||||
CLOSING_USRP,
|
||||
};
|
||||
|
||||
state_t d_state;
|
||||
|
||||
std::ofstream d_ofile;
|
||||
|
||||
long d_samples_recvd;
|
||||
long d_samples_to_recv;
|
||||
|
||||
public:
|
||||
test_usrp_rx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
|
||||
~test_usrp_rx();
|
||||
void initial_transition();
|
||||
void handle_message(mb_message_sptr msg);
|
||||
|
||||
protected:
|
||||
void open_usrp();
|
||||
void close_usrp();
|
||||
void allocate_channel();
|
||||
void send_packets();
|
||||
void enter_receiving();
|
||||
void build_and_send_next_frame();
|
||||
void handle_response_recv_raw_samples(pmt_t invocation_handle);
|
||||
void enter_closing_channel();
|
||||
};
|
||||
|
||||
test_usrp_rx::test_usrp_rx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
|
||||
: mb_mblock(runtime, instance_name, user_arg),
|
||||
d_rx_chan0(PMT_NIL), d_rx_chan1(PMT_NIL),
|
||||
d_samples_recvd(0),
|
||||
d_samples_to_recv(20e6)
|
||||
{
|
||||
d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
|
||||
d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
|
||||
|
||||
// Pass a dictionary to usrp_server which specifies which interface to use, the stub or USRP
|
||||
pmt_t usrp_dict = pmt_make_dict();
|
||||
|
||||
// To test the application without a USRP
|
||||
bool fake_usrp_p = false;
|
||||
if(fake_usrp_p) {
|
||||
pmt_dict_set(usrp_dict,
|
||||
pmt_intern("fake-usrp"),
|
||||
PMT_T);
|
||||
}
|
||||
|
||||
// Specify the RBF to use
|
||||
pmt_dict_set(usrp_dict,
|
||||
pmt_intern("rbf"),
|
||||
pmt_intern("inband_2rxhb_2tx.rbf"));
|
||||
|
||||
pmt_dict_set(usrp_dict,
|
||||
pmt_intern("decim-rx"),
|
||||
pmt_from_long(64));
|
||||
|
||||
define_component("server", "usrp_server", usrp_dict);
|
||||
|
||||
connect("self", "rx0", "server", "rx0");
|
||||
connect("self", "cs", "server", "cs");
|
||||
|
||||
}
|
||||
|
||||
test_usrp_rx::~test_usrp_rx()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_rx::initial_transition()
|
||||
{
|
||||
open_usrp();
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_rx::handle_message(mb_message_sptr msg)
|
||||
{
|
||||
pmt_t event = msg->signal();
|
||||
pmt_t data = msg->data();
|
||||
|
||||
pmt_t handle = PMT_F;
|
||||
pmt_t status = PMT_F;
|
||||
std::string error_msg;
|
||||
|
||||
switch(d_state){
|
||||
|
||||
//----------------------------- OPENING_USRP ----------------------------//
|
||||
// We only expect a response from opening the USRP which should be succesful
|
||||
// or failed.
|
||||
case OPENING_USRP:
|
||||
if (pmt_eq(event, s_response_open)){
|
||||
status = pmt_nth(1, data);
|
||||
if (pmt_eq(status, PMT_T)){
|
||||
allocate_channel();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "failed to open usrp:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
goto unhandled;
|
||||
|
||||
//----------------------- ALLOCATING CHANNELS --------------------//
|
||||
// Allocate an RX channel to perform the overrun test.
|
||||
case ALLOCATING_CHANNEL:
|
||||
if (pmt_eq(event, s_response_allocate_channel)){
|
||||
status = pmt_nth(1, data);
|
||||
if(pmt_eqv(d_rx_chan0, PMT_NIL))
|
||||
d_rx_chan0 = pmt_nth(2, data);
|
||||
else
|
||||
d_rx_chan1 = pmt_nth(2, data);
|
||||
|
||||
if (pmt_eq(status, PMT_T) && !pmt_eqv(d_rx_chan1, PMT_NIL)){
|
||||
enter_receiving();
|
||||
return;
|
||||
}
|
||||
else if(pmt_eq(status, PMT_F)){
|
||||
error_msg = "failed to allocate channel:";
|
||||
goto bail;
|
||||
}
|
||||
return;
|
||||
}
|
||||
goto unhandled;
|
||||
|
||||
//--------------------------- RECEIVING ------------------------------//
|
||||
// In the receiving state, we receive samples until the specified amount
|
||||
// while counting the number of overruns.
|
||||
case RECEIVING:
|
||||
if (pmt_eq(event, s_response_recv_raw_samples)){
|
||||
status = pmt_nth(1, data);
|
||||
|
||||
if (pmt_eq(status, PMT_T)){
|
||||
handle_response_recv_raw_samples(data);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "bad response-xmit-raw-frame:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
goto unhandled;
|
||||
|
||||
//------------------------- CLOSING CHANNEL ----------------------------//
|
||||
// Check deallocation response for the RX channel
|
||||
case CLOSING_CHANNEL:
|
||||
if (pmt_eq(event, s_response_deallocate_channel)){
|
||||
status = pmt_nth(1, data);
|
||||
|
||||
if (pmt_eq(status, PMT_T)){
|
||||
close_usrp();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "failed to deallocate channel:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
// Alternately, we ignore all response recv samples while waiting for the
|
||||
// channel to actually close
|
||||
if (pmt_eq(event, s_response_recv_raw_samples))
|
||||
return;
|
||||
|
||||
goto unhandled;
|
||||
|
||||
//--------------------------- CLOSING USRP ------------------------------//
|
||||
// Once we have received a successful USRP close response, we shutdown all
|
||||
// mblocks and exit.
|
||||
case CLOSING_USRP:
|
||||
if (pmt_eq(event, s_response_close)){
|
||||
status = pmt_nth(1, data);
|
||||
|
||||
if (pmt_eq(status, PMT_T)){
|
||||
fflush(stdout);
|
||||
shutdown_all(PMT_T);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "failed to close USRP:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
goto unhandled;
|
||||
|
||||
default:
|
||||
goto unhandled;
|
||||
}
|
||||
return;
|
||||
|
||||
// An error occured, print it, and shutdown all m-blocks
|
||||
bail:
|
||||
std::cerr << error_msg << data
|
||||
<< "status = " << status << std::endl;
|
||||
shutdown_all(PMT_F);
|
||||
return;
|
||||
|
||||
// Received an unhandled message for a specific state
|
||||
unhandled:
|
||||
if(verbose && !pmt_eq(event, pmt_intern("%shutdown")))
|
||||
std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
|
||||
<< "in state "<< d_state << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
test_usrp_rx::open_usrp()
|
||||
{
|
||||
pmt_t which_usrp = pmt_from_long(0);
|
||||
|
||||
d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, which_usrp));
|
||||
d_state = OPENING_USRP;
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_RX] Opening the USRP\n";
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_rx::close_usrp()
|
||||
{
|
||||
|
||||
d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
|
||||
d_state = CLOSING_USRP;
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_RX] Closing the USRP\n";
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_rx::allocate_channel()
|
||||
{
|
||||
long capacity = (long) 16e6;
|
||||
d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
|
||||
d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
|
||||
d_state = ALLOCATING_CHANNEL;
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_RX] Requesting RX channel allocation\n";
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_rx::enter_receiving()
|
||||
{
|
||||
d_state = RECEIVING;
|
||||
|
||||
d_rx->send(s_cmd_start_recv_raw_samples,
|
||||
pmt_list2(PMT_F,
|
||||
d_rx_chan0));
|
||||
|
||||
d_rx->send(s_cmd_start_recv_raw_samples,
|
||||
pmt_list2(PMT_F,
|
||||
d_rx_chan1));
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_RX] Receiving...\n";
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_rx::handle_response_recv_raw_samples(pmt_t data)
|
||||
{
|
||||
pmt_t invocation_handle = pmt_nth(0, data);
|
||||
pmt_t status = pmt_nth(1, data);
|
||||
pmt_t v_samples = pmt_nth(2, data);
|
||||
pmt_t timestamp = pmt_nth(3, data);
|
||||
pmt_t channel = pmt_nth(4, data);
|
||||
pmt_t properties = pmt_nth(5, data);
|
||||
|
||||
d_samples_recvd += pmt_length(v_samples) / 4;
|
||||
|
||||
// Check for overrun
|
||||
if(!pmt_is_dict(properties)) {
|
||||
std::cout << "[TEST_USRP_INBAND_RX] Recv samples dictionary is improper\n";
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the number samples we have received meets the test
|
||||
if(d_samples_recvd >= d_samples_to_recv) {
|
||||
d_rx->send(s_cmd_stop_recv_raw_samples, pmt_list2(PMT_NIL, d_rx_chan0));
|
||||
d_rx->send(s_cmd_stop_recv_raw_samples, pmt_list2(PMT_NIL, d_rx_chan1));
|
||||
enter_closing_channel();
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_rx::enter_closing_channel()
|
||||
{
|
||||
d_state = CLOSING_CHANNEL;
|
||||
|
||||
d_rx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_rx_chan0));
|
||||
d_rx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_rx_chan1));
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_RX] Deallocating RX channel\n";
|
||||
}
|
||||
|
||||
REGISTER_MBLOCK_CLASS(test_usrp_rx);
|
||||
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
mb_runtime_sptr rt = mb_make_runtime();
|
||||
pmt_t result = PMT_NIL;
|
||||
|
||||
rt->run("top", "test_usrp_rx", PMT_F, &result);
|
||||
|
||||
}
|
|
@ -1,430 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007,2008 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <mblock/mblock.h>
|
||||
#include <mblock/runtime.h>
|
||||
#include <mb_runtime_nop.h> // QA only
|
||||
#include <mblock/protocol_class.h>
|
||||
#include <mblock/exception.h>
|
||||
#include <mblock/msg_queue.h>
|
||||
#include <mblock/message.h>
|
||||
#include <mb_mblock_impl.h>
|
||||
#include <mblock/msg_accepter.h>
|
||||
#include <mblock/class_registry.h>
|
||||
#include <pmt.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <ui_nco.h>
|
||||
#include <symbols_usrp_server_cs.h>
|
||||
#include <symbols_usrp_channel.h>
|
||||
#include <symbols_usrp_low_level_cs.h>
|
||||
#include <symbols_usrp_tx.h>
|
||||
|
||||
static bool verbose = true;
|
||||
|
||||
class test_usrp_tx : public mb_mblock
|
||||
{
|
||||
mb_port_sptr d_tx;
|
||||
mb_port_sptr d_cs;
|
||||
pmt_t d_tx_chan0, d_tx_chan1;
|
||||
|
||||
enum state_t {
|
||||
INIT,
|
||||
OPENING_USRP,
|
||||
ALLOCATING_CHANNEL,
|
||||
TRANSMITTING,
|
||||
CLOSING_CHANNEL,
|
||||
CLOSING_USRP,
|
||||
};
|
||||
|
||||
state_t d_state;
|
||||
long d_nsamples_to_send;
|
||||
long d_nsamples_xmitted;
|
||||
long d_nframes_xmitted;
|
||||
long d_samples_per_frame;
|
||||
bool d_done_sending;
|
||||
|
||||
// for generating sine wave output
|
||||
ui_nco<float,float> d_nco;
|
||||
double d_amplitude;
|
||||
|
||||
public:
|
||||
test_usrp_tx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
|
||||
~test_usrp_tx();
|
||||
void initial_transition();
|
||||
void handle_message(mb_message_sptr msg);
|
||||
|
||||
protected:
|
||||
void open_usrp();
|
||||
void close_usrp();
|
||||
void allocate_channel();
|
||||
void send_packets();
|
||||
void enter_transmitting();
|
||||
void build_and_send_next_frame();
|
||||
void handle_xmit_response(pmt_t invocation_handle);
|
||||
void enter_closing_channel();
|
||||
};
|
||||
|
||||
test_usrp_tx::test_usrp_tx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
|
||||
: mb_mblock(runtime, instance_name, user_arg),
|
||||
d_tx_chan0(PMT_NIL), d_tx_chan1(PMT_NIL),
|
||||
d_state(INIT), d_nsamples_to_send((long) 80e6),
|
||||
d_nsamples_xmitted(0),
|
||||
d_nframes_xmitted(0),
|
||||
d_samples_per_frame((long)(126 * 4)), // full packet
|
||||
d_done_sending(false),
|
||||
d_amplitude(16384)
|
||||
{
|
||||
// std::cout << "[TEST_USRP_TX] Initializing...\n";
|
||||
|
||||
d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
|
||||
d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
|
||||
|
||||
//bool fake_usrp_p = true;
|
||||
bool fake_usrp_p = false;
|
||||
|
||||
// Test the TX side
|
||||
|
||||
pmt_t usrp_dict = pmt_make_dict();
|
||||
|
||||
if(fake_usrp_p) {
|
||||
pmt_dict_set(usrp_dict,
|
||||
pmt_intern("fake-usrp"),
|
||||
PMT_T);
|
||||
}
|
||||
|
||||
// Specify the RBF to use
|
||||
pmt_dict_set(usrp_dict,
|
||||
pmt_intern("rbf"),
|
||||
pmt_intern("inband_2rxhb_2tx.rbf"));
|
||||
|
||||
// Set TX and RX interpolations
|
||||
pmt_dict_set(usrp_dict,
|
||||
pmt_intern("interp-tx"),
|
||||
pmt_from_long(128));
|
||||
|
||||
// pmt_dict_set(usrp_dict,
|
||||
// pmt_intern("rf-freq"),
|
||||
// pmt_from_long(10e6));
|
||||
|
||||
define_component("server", "usrp_server", usrp_dict);
|
||||
|
||||
connect("self", "tx0", "server", "tx0");
|
||||
connect("self", "cs", "server", "cs");
|
||||
|
||||
// initialize NCO
|
||||
double freq = 100e3;
|
||||
int interp = 32; // 32 -> 4MS/s
|
||||
double sample_rate = 128e6 / interp;
|
||||
d_nco.set_freq(2*M_PI * freq/sample_rate);
|
||||
|
||||
// FIXME need to somehow set the interp rate in the USRP.
|
||||
// for now, we'll have the low-level code hardwire it.
|
||||
}
|
||||
|
||||
test_usrp_tx::~test_usrp_tx()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_tx::initial_transition()
|
||||
{
|
||||
open_usrp();
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_tx::handle_message(mb_message_sptr msg)
|
||||
{
|
||||
pmt_t event = msg->signal();
|
||||
pmt_t data = msg->data();
|
||||
|
||||
pmt_t handle = PMT_F;
|
||||
pmt_t status = PMT_F;
|
||||
std::string error_msg;
|
||||
|
||||
//std::cout << msg << std::endl;
|
||||
|
||||
switch(d_state){
|
||||
case OPENING_USRP:
|
||||
if (pmt_eq(event, s_response_open)){
|
||||
status = pmt_nth(1, data);
|
||||
if (pmt_eq(status, PMT_T)){
|
||||
allocate_channel();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "failed to open usrp:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
goto unhandled;
|
||||
|
||||
case ALLOCATING_CHANNEL:
|
||||
if (pmt_eq(event, s_response_allocate_channel)){
|
||||
status = pmt_nth(1, data);
|
||||
if(pmt_eqv(d_tx_chan0, PMT_NIL))
|
||||
d_tx_chan0 = pmt_nth(2, data);
|
||||
else
|
||||
d_tx_chan1 = pmt_nth(2, data);
|
||||
|
||||
if (pmt_eq(status, PMT_T) && !pmt_eqv(d_tx_chan1, PMT_NIL)){
|
||||
enter_transmitting();
|
||||
return;
|
||||
}
|
||||
else if(pmt_eq(status, PMT_F)){
|
||||
error_msg = "failed to allocate channel:";
|
||||
goto bail;
|
||||
}
|
||||
return;
|
||||
}
|
||||
goto unhandled;
|
||||
|
||||
case TRANSMITTING:
|
||||
if (pmt_eq(event, s_response_xmit_raw_frame)){
|
||||
handle = pmt_nth(0, data);
|
||||
status = pmt_nth(1, data);
|
||||
|
||||
if (pmt_eq(status, PMT_T)){
|
||||
handle_xmit_response(handle);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "bad response-xmit-raw-frame:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
goto unhandled;
|
||||
|
||||
case CLOSING_CHANNEL:
|
||||
if (pmt_eq(event, s_response_deallocate_channel)){
|
||||
status = pmt_nth(1, data);
|
||||
|
||||
if (pmt_eq(status, PMT_T)){
|
||||
close_usrp();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "failed to deallocate channel:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
goto unhandled;
|
||||
|
||||
case CLOSING_USRP:
|
||||
if (pmt_eq(event, s_response_close)){
|
||||
status = pmt_nth(1, data);
|
||||
|
||||
if (pmt_eq(status, PMT_T)){
|
||||
shutdown_all(PMT_T);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "failed to close USRP:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
goto unhandled;
|
||||
|
||||
default:
|
||||
goto unhandled;
|
||||
}
|
||||
return;
|
||||
|
||||
bail:
|
||||
std::cerr << error_msg << data
|
||||
<< "status = " << status << std::endl;
|
||||
shutdown_all(PMT_F);
|
||||
return;
|
||||
|
||||
unhandled:
|
||||
std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
|
||||
<< "in state "<< d_state << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
test_usrp_tx::open_usrp()
|
||||
{
|
||||
pmt_t which_usrp = pmt_from_long(0);
|
||||
|
||||
d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, which_usrp));
|
||||
d_state = OPENING_USRP;
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_TX] Opening the USRP\n";
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_tx::close_usrp()
|
||||
{
|
||||
d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
|
||||
d_state = CLOSING_USRP;
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_TX] Closing the USRP\n";
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_tx::allocate_channel()
|
||||
{
|
||||
long capacity = (long) 16e6;
|
||||
|
||||
// Send two capacity requests, which will allocate us two channels
|
||||
d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
|
||||
d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
|
||||
d_state = ALLOCATING_CHANNEL;
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_TX] Requesting TX channel allocation\n";
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_tx::enter_transmitting()
|
||||
{
|
||||
d_state = TRANSMITTING;
|
||||
d_nsamples_xmitted = 0;
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_TX] Transmitting...\n";
|
||||
|
||||
build_and_send_next_frame(); // fire off 4 to start pipeline
|
||||
build_and_send_next_frame();
|
||||
build_and_send_next_frame();
|
||||
build_and_send_next_frame();
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_tx::build_and_send_next_frame()
|
||||
{
|
||||
// allocate the uniform vector for the samples
|
||||
// FIXME perhaps hold on to this between calls
|
||||
|
||||
#if 1
|
||||
long nsamples_this_frame =
|
||||
std::min(d_nsamples_to_send - d_nsamples_xmitted,
|
||||
d_samples_per_frame);
|
||||
#else
|
||||
long nsamples_this_frame = d_samples_per_frame;
|
||||
#endif
|
||||
|
||||
if (nsamples_this_frame == 0){
|
||||
d_done_sending = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
size_t nshorts = 2 * nsamples_this_frame; // 16-bit I & Q
|
||||
pmt_t uvec = pmt_make_s16vector(nshorts, 0);
|
||||
size_t ignore;
|
||||
int16_t *samples = pmt_s16vector_writable_elements(uvec, ignore);
|
||||
|
||||
// fill in the complex sinusoid
|
||||
|
||||
for (int i = 0; i < nsamples_this_frame; i++){
|
||||
|
||||
if (1){
|
||||
gr_complex s;
|
||||
d_nco.sincos(&s, 1, d_amplitude);
|
||||
// write 16-bit i & q
|
||||
samples[2*i] = (int16_t) s.real();
|
||||
samples[2*i+1] = (int16_t) s.imag();
|
||||
}
|
||||
else {
|
||||
gr_complex s(d_amplitude, d_amplitude);
|
||||
|
||||
// write 16-bit i & q
|
||||
samples[2*i] = (int16_t) s.real();
|
||||
samples[2*i+1] = (int16_t) s.imag();
|
||||
}
|
||||
}
|
||||
|
||||
pmt_t tx_properties = pmt_make_dict();
|
||||
|
||||
pmt_t timestamp = pmt_from_long(0xffffffff); // NOW
|
||||
d_tx->send(s_cmd_xmit_raw_frame,
|
||||
pmt_list5(pmt_from_long(d_nframes_xmitted), // invocation-handle
|
||||
d_tx_chan0, // channel
|
||||
uvec, // the samples
|
||||
timestamp,
|
||||
tx_properties));
|
||||
|
||||
// Resend on channel 1
|
||||
d_tx->send(s_cmd_xmit_raw_frame,
|
||||
pmt_list5(pmt_from_long(d_nframes_xmitted), // invocation-handle
|
||||
d_tx_chan1, // channel
|
||||
uvec, // the samples
|
||||
timestamp,
|
||||
tx_properties));
|
||||
|
||||
d_nsamples_xmitted += nsamples_this_frame;
|
||||
d_nframes_xmitted++;
|
||||
|
||||
if(verbose && 0)
|
||||
std::cout << "[TEST_USRP_INBAND_TX] Transmitted frame\n";
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
test_usrp_tx::handle_xmit_response(pmt_t handle)
|
||||
{
|
||||
if (d_done_sending &&
|
||||
pmt_to_long(handle) == (d_nframes_xmitted - 1)){
|
||||
// We're done sending and have received all responses
|
||||
enter_closing_channel();
|
||||
}
|
||||
|
||||
build_and_send_next_frame();
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_tx::enter_closing_channel()
|
||||
{
|
||||
d_state = CLOSING_CHANNEL;
|
||||
|
||||
// Deallocate both channels
|
||||
d_tx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_tx_chan0));
|
||||
d_tx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_tx_chan1));
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_tX] Deallocating TX channel\n";
|
||||
}
|
||||
|
||||
REGISTER_MBLOCK_CLASS(test_usrp_tx);
|
||||
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
// handle any command line args here
|
||||
|
||||
mb_runtime_sptr rt = mb_make_runtime();
|
||||
pmt_t result = PMT_NIL;
|
||||
|
||||
rt->run("top", "test_usrp_tx", PMT_F, &result);
|
||||
}
|
|
@ -1,375 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007,2008 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <mblock/mblock.h>
|
||||
#include <mblock/runtime.h>
|
||||
#include <mblock/protocol_class.h>
|
||||
#include <mblock/exception.h>
|
||||
#include <mblock/msg_queue.h>
|
||||
#include <mblock/message.h>
|
||||
#include <mblock/msg_accepter.h>
|
||||
#include <mblock/class_registry.h>
|
||||
#include <pmt.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
// Include the symbols needed for communication with USRP server
|
||||
#include <symbols_usrp_server_cs.h>
|
||||
#include <symbols_usrp_channel.h>
|
||||
#include <symbols_usrp_low_level_cs.h>
|
||||
#include <symbols_usrp_rx.h>
|
||||
|
||||
static bool verbose = true;
|
||||
|
||||
class test_usrp_rx : public mb_mblock
|
||||
{
|
||||
mb_port_sptr d_rx;
|
||||
mb_port_sptr d_cs;
|
||||
pmt_t d_rx_chan; // returned tx channel handle
|
||||
|
||||
enum state_t {
|
||||
INIT,
|
||||
OPENING_USRP,
|
||||
ALLOCATING_CHANNEL,
|
||||
RECEIVING,
|
||||
CLOSING_CHANNEL,
|
||||
CLOSING_USRP,
|
||||
};
|
||||
|
||||
state_t d_state;
|
||||
|
||||
std::ofstream d_ofile;
|
||||
|
||||
long d_n_overruns;
|
||||
|
||||
long d_samples_recvd;
|
||||
long d_samples_to_recv;
|
||||
|
||||
public:
|
||||
test_usrp_rx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
|
||||
~test_usrp_rx();
|
||||
void initial_transition();
|
||||
void handle_message(mb_message_sptr msg);
|
||||
|
||||
protected:
|
||||
void open_usrp();
|
||||
void close_usrp();
|
||||
void allocate_channel();
|
||||
void send_packets();
|
||||
void enter_receiving();
|
||||
void build_and_send_next_frame();
|
||||
void handle_response_recv_raw_samples(pmt_t invocation_handle);
|
||||
void enter_closing_channel();
|
||||
};
|
||||
|
||||
test_usrp_rx::test_usrp_rx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
|
||||
: mb_mblock(runtime, instance_name, user_arg),
|
||||
d_n_overruns(0),
|
||||
d_samples_recvd(0),
|
||||
d_samples_to_recv(10e6)
|
||||
{
|
||||
|
||||
d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
|
||||
d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
|
||||
|
||||
// Pass a dictionary to usrp_server which specifies which interface to use, the stub or USRP
|
||||
pmt_t usrp_dict = pmt_make_dict();
|
||||
|
||||
// Specify the RBF to use
|
||||
pmt_dict_set(usrp_dict,
|
||||
pmt_intern("rbf"),
|
||||
pmt_intern("inband_1rxhb_1tx.rbf"));
|
||||
|
||||
pmt_dict_set(usrp_dict,
|
||||
pmt_intern("decim-rx"),
|
||||
pmt_from_long(128));
|
||||
|
||||
define_component("server", "usrp_server", usrp_dict);
|
||||
|
||||
connect("self", "rx0", "server", "rx0");
|
||||
connect("self", "cs", "server", "cs");
|
||||
|
||||
}
|
||||
|
||||
test_usrp_rx::~test_usrp_rx()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_rx::initial_transition()
|
||||
{
|
||||
open_usrp();
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_rx::handle_message(mb_message_sptr msg)
|
||||
{
|
||||
pmt_t event = msg->signal();
|
||||
pmt_t data = msg->data();
|
||||
|
||||
pmt_t handle = PMT_F;
|
||||
pmt_t status = PMT_F;
|
||||
std::string error_msg;
|
||||
|
||||
switch(d_state){
|
||||
|
||||
//----------------------------- OPENING_USRP ----------------------------//
|
||||
// We only expect a response from opening the USRP which should be succesful
|
||||
// or failed.
|
||||
case OPENING_USRP:
|
||||
if (pmt_eq(event, s_response_open)){
|
||||
status = pmt_nth(1, data);
|
||||
if (pmt_eq(status, PMT_T)){
|
||||
allocate_channel();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "failed to open usrp:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
goto unhandled;
|
||||
|
||||
//----------------------- ALLOCATING CHANNELS --------------------//
|
||||
// Allocate an RX channel to perform the overrun test.
|
||||
case ALLOCATING_CHANNEL:
|
||||
if (pmt_eq(event, s_response_allocate_channel)){
|
||||
status = pmt_nth(1, data);
|
||||
d_rx_chan = pmt_nth(2, data);
|
||||
|
||||
if (pmt_eq(status, PMT_T)){
|
||||
enter_receiving();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "failed to allocate channel:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
goto unhandled;
|
||||
|
||||
//--------------------------- RECEIVING ------------------------------//
|
||||
// In the receiving state, we receive samples until the specified amount
|
||||
// while counting the number of overruns.
|
||||
case RECEIVING:
|
||||
if (pmt_eq(event, s_response_recv_raw_samples)){
|
||||
status = pmt_nth(1, data);
|
||||
|
||||
if (pmt_eq(status, PMT_T)){
|
||||
handle_response_recv_raw_samples(data);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "bad response-xmit-raw-frame:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
goto unhandled;
|
||||
|
||||
//------------------------- CLOSING CHANNEL ----------------------------//
|
||||
// Check deallocation response for the RX channel
|
||||
case CLOSING_CHANNEL:
|
||||
if (pmt_eq(event, s_response_deallocate_channel)){
|
||||
status = pmt_nth(1, data);
|
||||
|
||||
if (pmt_eq(status, PMT_T)){
|
||||
close_usrp();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "failed to deallocate channel:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
// Alternately, we ignore all response recv samples while waiting for the
|
||||
// channel to actually close
|
||||
if (pmt_eq(event, s_response_recv_raw_samples))
|
||||
return;
|
||||
|
||||
goto unhandled;
|
||||
|
||||
//--------------------------- CLOSING USRP ------------------------------//
|
||||
// Once we have received a successful USRP close response, we shutdown all
|
||||
// mblocks and exit.
|
||||
case CLOSING_USRP:
|
||||
if (pmt_eq(event, s_response_close)){
|
||||
status = pmt_nth(1, data);
|
||||
|
||||
if (pmt_eq(status, PMT_T)){
|
||||
std::cout << "\nOverruns: " << d_n_overruns << std::endl;
|
||||
fflush(stdout);
|
||||
shutdown_all(PMT_T);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "failed to close USRP:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
goto unhandled;
|
||||
|
||||
default:
|
||||
goto unhandled;
|
||||
}
|
||||
return;
|
||||
|
||||
// An error occured, print it, and shutdown all m-blocks
|
||||
bail:
|
||||
std::cerr << error_msg << data
|
||||
<< "status = " << status << std::endl;
|
||||
shutdown_all(PMT_F);
|
||||
return;
|
||||
|
||||
// Received an unhandled message for a specific state
|
||||
unhandled:
|
||||
if(verbose && !pmt_eq(event, pmt_intern("%shutdown")))
|
||||
std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
|
||||
<< "in state "<< d_state << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
test_usrp_rx::open_usrp()
|
||||
{
|
||||
pmt_t which_usrp = pmt_from_long(0);
|
||||
|
||||
d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, which_usrp));
|
||||
d_state = OPENING_USRP;
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_OVERRUN] Opening the USRP\n";
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_rx::close_usrp()
|
||||
{
|
||||
d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
|
||||
d_state = CLOSING_USRP;
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_OVERRUN] Closing the USRP\n";
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_rx::allocate_channel()
|
||||
{
|
||||
long capacity = (long) 16e6;
|
||||
d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
|
||||
d_state = ALLOCATING_CHANNEL;
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_OVERRUN] Requesting RX channel allocation\n";
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_rx::enter_receiving()
|
||||
{
|
||||
d_state = RECEIVING;
|
||||
|
||||
d_rx->send(s_cmd_start_recv_raw_samples,
|
||||
pmt_list2(PMT_F,
|
||||
d_rx_chan));
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_OVERRUN] Receiving...\n";
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_rx::handle_response_recv_raw_samples(pmt_t data)
|
||||
{
|
||||
pmt_t invocation_handle = pmt_nth(0, data);
|
||||
pmt_t status = pmt_nth(1, data);
|
||||
pmt_t v_samples = pmt_nth(2, data);
|
||||
pmt_t timestamp = pmt_nth(3, data);
|
||||
pmt_t channel = pmt_nth(4, data);
|
||||
pmt_t properties = pmt_nth(5, data);
|
||||
|
||||
d_samples_recvd += pmt_length(v_samples) / 4;
|
||||
|
||||
// Check for overrun
|
||||
if(!pmt_is_dict(properties)) {
|
||||
std::cout << "[TEST_USRP_INBAND_OVERRUN] Recv samples dictionary is improper\n";
|
||||
return;
|
||||
}
|
||||
|
||||
if(pmt_t overrun = pmt_dict_ref(properties,
|
||||
pmt_intern("overrun"),
|
||||
PMT_NIL)) {
|
||||
if(pmt_eqv(overrun, PMT_T)) {
|
||||
d_n_overruns++;
|
||||
|
||||
if(verbose && 0)
|
||||
std::cout << "[TEST_USRP_INBAND_OVERRUN] Underrun\n";
|
||||
}
|
||||
else {
|
||||
if(verbose && 0)
|
||||
std::cout << "[TEST_USRP_INBAND_OVERRUN] No overrun\n" << overrun <<std::endl;
|
||||
}
|
||||
} else {
|
||||
|
||||
if(verbose && 0)
|
||||
std::cout << "[TEST_USRP_INBAND_OVERRUN] No overrun\n";
|
||||
}
|
||||
|
||||
// Check if the number samples we have received meets the test
|
||||
if(d_samples_recvd >= d_samples_to_recv) {
|
||||
d_rx->send(s_cmd_stop_recv_raw_samples, pmt_list2(PMT_NIL, d_rx_chan));
|
||||
enter_closing_channel();
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_rx::enter_closing_channel()
|
||||
{
|
||||
d_state = CLOSING_CHANNEL;
|
||||
|
||||
sleep(2);
|
||||
|
||||
d_rx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_rx_chan));
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_OVERRUN] Deallocating RX channel\n";
|
||||
}
|
||||
|
||||
REGISTER_MBLOCK_CLASS(test_usrp_rx);
|
||||
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
// handle any command line args here
|
||||
|
||||
mb_runtime_sptr rt = mb_make_runtime();
|
||||
pmt_t result = PMT_NIL;
|
||||
|
||||
rt->run("top", "test_usrp_rx", PMT_F, &result);
|
||||
}
|
|
@ -1,374 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007,2008 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <mblock/mblock.h>
|
||||
#include <mblock/runtime.h>
|
||||
#include <mblock/protocol_class.h>
|
||||
#include <mblock/exception.h>
|
||||
#include <mblock/msg_queue.h>
|
||||
#include <mblock/message.h>
|
||||
#include <mblock/msg_accepter.h>
|
||||
#include <mblock/class_registry.h>
|
||||
#include <pmt.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <iostream>
|
||||
|
||||
// Include the symbols needed for communication with USRP server
|
||||
#include <symbols_usrp_server_cs.h>
|
||||
#include <symbols_usrp_channel.h>
|
||||
#include <symbols_usrp_low_level_cs.h>
|
||||
#include <symbols_usrp_tx.h>
|
||||
#include <symbols_usrp_rx.h>
|
||||
|
||||
static bool verbose = false;
|
||||
|
||||
class test_usrp_inband_ping : public mb_mblock
|
||||
{
|
||||
|
||||
mb_port_sptr d_tx; // Ports connected to the USRP server
|
||||
mb_port_sptr d_rx;
|
||||
mb_port_sptr d_cs;
|
||||
|
||||
pmt_t d_tx_chan; // Returned channel from TX allocation
|
||||
pmt_t d_rx_chan; // Returned channel from RX allocation
|
||||
|
||||
pmt_t d_which_usrp; // The USRP to use for the test
|
||||
|
||||
long d_warm_msgs; // The number of messages to 'warm' the USRP
|
||||
long d_warm_recvd; // The number of msgs received in the 'warm' state
|
||||
|
||||
// Keep track of current state
|
||||
enum state_t {
|
||||
INIT,
|
||||
OPENING_USRP,
|
||||
ALLOCATING_CHANNELS,
|
||||
WARMING_USRP,
|
||||
PINGING,
|
||||
CLOSING_CHANNELS,
|
||||
CLOSING_USRP,
|
||||
};
|
||||
state_t d_state;
|
||||
|
||||
public:
|
||||
test_usrp_inband_ping(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
|
||||
~test_usrp_inband_ping();
|
||||
void initial_transition();
|
||||
void handle_message(mb_message_sptr msg);
|
||||
|
||||
protected:
|
||||
void opening_usrp();
|
||||
void allocating_channels();
|
||||
void enter_warming_usrp();
|
||||
void enter_pinging();
|
||||
void build_and_send_ping();
|
||||
void closing_channels();
|
||||
void closing_usrp();
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
// handle any command line args here
|
||||
|
||||
mb_runtime_sptr rt = mb_make_runtime();
|
||||
pmt_t result = PMT_NIL;
|
||||
|
||||
rt->run("top", "test_usrp_inband_ping", PMT_F, &result);
|
||||
}
|
||||
|
||||
|
||||
test_usrp_inband_ping::test_usrp_inband_ping(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
|
||||
: mb_mblock(runtime, instance_name, user_arg),
|
||||
d_tx_chan(PMT_NIL),
|
||||
d_rx_chan(PMT_NIL),
|
||||
d_which_usrp(pmt_from_long(0)),
|
||||
d_state(INIT)
|
||||
{
|
||||
|
||||
// A dictionary is used to pass parameters to the USRP
|
||||
pmt_t usrp_dict = pmt_make_dict();
|
||||
|
||||
// Specify the RBF to use
|
||||
pmt_dict_set(usrp_dict,
|
||||
pmt_intern("rbf"),
|
||||
pmt_intern("fixed1.rbf"));
|
||||
|
||||
// Set TX and RX interpolations
|
||||
pmt_dict_set(usrp_dict,
|
||||
pmt_intern("interp-tx"),
|
||||
pmt_from_long(128));
|
||||
|
||||
pmt_dict_set(usrp_dict,
|
||||
pmt_intern("decim-rx"),
|
||||
pmt_from_long(16));
|
||||
|
||||
d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
|
||||
d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
|
||||
d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
|
||||
|
||||
// Create an instance of USRP server and connect ports
|
||||
define_component("server", "usrp_server", usrp_dict);
|
||||
connect("self", "tx0", "server", "tx0");
|
||||
connect("self", "rx0", "server", "rx0");
|
||||
connect("self", "cs", "server", "cs");
|
||||
|
||||
}
|
||||
|
||||
test_usrp_inband_ping::~test_usrp_inband_ping()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_inband_ping::initial_transition()
|
||||
{
|
||||
opening_usrp();
|
||||
}
|
||||
|
||||
// Handle message reads all incoming messages from USRP server which will be
|
||||
// initialization and ping responses. We perform actions based on the current
|
||||
// state and the event (ie, ping response)
|
||||
void
|
||||
test_usrp_inband_ping::handle_message(mb_message_sptr msg)
|
||||
{
|
||||
pmt_t event = msg->signal();
|
||||
pmt_t data = msg->data();
|
||||
pmt_t port_id = msg->port_id();
|
||||
|
||||
pmt_t handle = PMT_F;
|
||||
pmt_t status = PMT_F;
|
||||
std::string error_msg;
|
||||
|
||||
// Dispatch based on state
|
||||
switch(d_state) {
|
||||
|
||||
//----------------------------- OPENING_USRP ----------------------------//
|
||||
// We only expect a response from opening the USRP which should be succesful
|
||||
// or failed.
|
||||
case OPENING_USRP:
|
||||
|
||||
if(pmt_eq(event, s_response_open)) {
|
||||
|
||||
status = pmt_nth(1, data); // failed/succes
|
||||
|
||||
if(pmt_eq(status, PMT_T)) {
|
||||
allocating_channels();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "failed to open usrp:";
|
||||
goto bail;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
goto unhandled; // all other messages not handled in this state
|
||||
|
||||
|
||||
//----------------------- ALLOCATING CHANNELS --------------------//
|
||||
// When allocating channels, we need to wait for 2 responses from
|
||||
// USRP server: one for TX and one for RX. Both are initialized to
|
||||
// NIL so we know to continue to the next state once both are set.
|
||||
case ALLOCATING_CHANNELS:
|
||||
|
||||
// A TX allocation response
|
||||
if(pmt_eq(event, s_response_allocate_channel)
|
||||
&& pmt_eq(d_tx->port_symbol(), port_id))
|
||||
{
|
||||
status = pmt_nth(1, data);
|
||||
|
||||
// If successful response, extract the channel
|
||||
if(pmt_eq(status, PMT_T)) {
|
||||
|
||||
d_tx_chan = pmt_nth(2, data);
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_PING] Received TX allocation"
|
||||
<< " on channel " << d_tx_chan << std::endl;
|
||||
|
||||
// If the RX has also been allocated already, we can continue
|
||||
if(!pmt_eqv(d_rx_chan, PMT_NIL))
|
||||
enter_warming_usrp();
|
||||
|
||||
return;
|
||||
}
|
||||
else { // TX allocation failed
|
||||
error_msg = "failed to allocate TX channel:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
// A RX allocation response
|
||||
if(pmt_eq(event, s_response_allocate_channel)
|
||||
&& pmt_eq(d_rx->port_symbol(), port_id))
|
||||
{
|
||||
status = pmt_nth(1, data);
|
||||
|
||||
// If successful response, extract the channel
|
||||
if(pmt_eq(status, PMT_T)) {
|
||||
|
||||
d_rx_chan = pmt_nth(2, data);
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_PING] Received RX allocation"
|
||||
<< " on channel " << d_rx_chan << std::endl;
|
||||
|
||||
// If the TX has also been allocated already, we can continue
|
||||
if(!pmt_eqv(d_tx_chan, PMT_NIL))
|
||||
enter_warming_usrp();
|
||||
|
||||
return;
|
||||
}
|
||||
else { // RX allocation failed
|
||||
error_msg = "failed to allocate RX channel:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
goto unhandled;
|
||||
|
||||
//----------------------- WARMING USRP --------------------//
|
||||
// The FX2 seems to need some amount of data to be buffered
|
||||
// before it begins reading. We use this state to simply
|
||||
// warm up the USRP before benchmarking pings.
|
||||
case WARMING_USRP:
|
||||
|
||||
// We really don't care about the responses from the
|
||||
// control channel in the warming stage, but once we receive
|
||||
// the proper number of responses we switch states.
|
||||
if(pmt_eq(event, s_response_from_control_channel)
|
||||
&& pmt_eq(d_rx->port_symbol(), port_id))
|
||||
{
|
||||
d_warm_recvd++;
|
||||
|
||||
if(d_warm_recvd > d_warm_msgs)
|
||||
enter_pinging();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
goto unhandled;
|
||||
|
||||
case PINGING:
|
||||
goto unhandled;
|
||||
|
||||
case CLOSING_CHANNELS:
|
||||
goto unhandled;
|
||||
|
||||
case CLOSING_USRP:
|
||||
goto unhandled;
|
||||
|
||||
case INIT:
|
||||
goto unhandled;
|
||||
|
||||
}
|
||||
|
||||
// An error occured, print it, and shutdown all m-blocks
|
||||
bail:
|
||||
std::cerr << error_msg << data
|
||||
<< "status = " << status << std::endl;
|
||||
shutdown_all(PMT_F);
|
||||
return;
|
||||
|
||||
// Received an unhandled message for a specific state
|
||||
unhandled:
|
||||
if(verbose)
|
||||
std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
|
||||
<< "in state "<< d_state << std::endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Sends a command to USRP server to open up a connection to the
|
||||
// specified USRP, which is defaulted to USRP 0 on the system
|
||||
void
|
||||
test_usrp_inband_ping::opening_usrp()
|
||||
{
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_PING] Opening USRP "
|
||||
<< d_which_usrp << std::endl;
|
||||
|
||||
d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, d_which_usrp));
|
||||
d_state = OPENING_USRP;
|
||||
}
|
||||
|
||||
// RX and TX channels must be allocated so that the USRP server can
|
||||
// properly share bandwidth across multiple USRPs. No commands will be
|
||||
// successful to the USRP through the USRP server on the TX or RX channels until
|
||||
// a bandwidth allocation has been received.
|
||||
void
|
||||
test_usrp_inband_ping::allocating_channels()
|
||||
{
|
||||
d_state = ALLOCATING_CHANNELS;
|
||||
|
||||
long capacity = (long) 16e6;
|
||||
d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
|
||||
d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
|
||||
}
|
||||
|
||||
// The USRP needs some amount of initial data to pass a buffering point such
|
||||
// that it begins to pull and read data from the FX2. We send an arbitrary
|
||||
// amount of data to start the pipeline, which are just pings.
|
||||
void
|
||||
test_usrp_inband_ping::enter_warming_usrp()
|
||||
{
|
||||
d_state = WARMING_USRP;
|
||||
|
||||
for(int i=0; i < d_warm_msgs; i++)
|
||||
build_and_send_ping();
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_inband_ping::enter_pinging()
|
||||
{
|
||||
d_state = PINGING;
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_PING] Running ping tests\n";
|
||||
|
||||
}
|
||||
|
||||
// Pings are sent over the TX channel using the signal 'cmd-to-control-channel'
|
||||
// to the USRP server. Within this message there can be infinite subpackets
|
||||
// stored as a list (the second parameter) and sent. The only subpacket we send
|
||||
// is a ping, interpreted by the 'op-ping-fixed' signal.
|
||||
void
|
||||
test_usrp_inband_ping::build_and_send_ping()
|
||||
{
|
||||
|
||||
d_tx->send(s_cmd_to_control_channel, // USRP server signal
|
||||
pmt_list2(PMT_NIL, // invocation handle
|
||||
pmt_list1(pmt_list3(s_op_ping_fixed,
|
||||
pmt_from_long(0),
|
||||
pmt_from_long(0)))));
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_PING] Ping!!" << std::endl;
|
||||
}
|
||||
|
||||
REGISTER_MBLOCK_CLASS(test_usrp_inband_ping);
|
|
@ -1,435 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <mblock/mblock.h>
|
||||
#include <mblock/runtime.h>
|
||||
#include <mblock/protocol_class.h>
|
||||
#include <mblock/exception.h>
|
||||
#include <mblock/msg_queue.h>
|
||||
#include <mblock/message.h>
|
||||
//#include <mb_mblock_impl.h>
|
||||
#include <mblock/msg_accepter.h>
|
||||
#include <mblock/class_registry.h>
|
||||
#include <pmt.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <iostream>
|
||||
|
||||
// Include the symbols needed for communication with USRP server
|
||||
#include <symbols_usrp_server_cs.h>
|
||||
#include <symbols_usrp_channel.h>
|
||||
#include <symbols_usrp_low_level_cs.h>
|
||||
#include <symbols_usrp_tx.h>
|
||||
#include <symbols_usrp_rx.h>
|
||||
|
||||
static bool verbose = true;
|
||||
|
||||
class test_usrp_inband_registers : public mb_mblock
|
||||
{
|
||||
|
||||
mb_port_sptr d_tx; // Ports connected to the USRP server
|
||||
mb_port_sptr d_rx;
|
||||
mb_port_sptr d_cs;
|
||||
|
||||
pmt_t d_tx_chan; // Returned channel from TX allocation
|
||||
pmt_t d_rx_chan; // Returned channel from RX allocation
|
||||
|
||||
pmt_t d_which_usrp; // The USRP to use for the test
|
||||
|
||||
long d_warm_msgs; // The number of messages to 'warm' the USRP
|
||||
long d_warm_recvd; // The number of msgs received in the 'warm' state
|
||||
|
||||
// Keep track of current state
|
||||
enum state_t {
|
||||
INIT,
|
||||
OPENING_USRP,
|
||||
ALLOCATING_CHANNELS,
|
||||
WRITE_REGISTER,
|
||||
READ_REGISTER,
|
||||
CLOSING_CHANNELS,
|
||||
CLOSING_USRP,
|
||||
};
|
||||
state_t d_state;
|
||||
|
||||
public:
|
||||
test_usrp_inband_registers(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
|
||||
~test_usrp_inband_registers();
|
||||
void initial_transition();
|
||||
void handle_message(mb_message_sptr msg);
|
||||
|
||||
protected:
|
||||
void opening_usrp();
|
||||
void allocating_channels();
|
||||
void write_register();
|
||||
void read_register();
|
||||
void closing_channels();
|
||||
void closing_usrp();
|
||||
void enter_receiving();
|
||||
void build_and_send_ping();
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
// handle any command line args here
|
||||
|
||||
mb_runtime_sptr rt = mb_make_runtime();
|
||||
pmt_t result = PMT_NIL;
|
||||
|
||||
rt->run("top", "test_usrp_inband_registers", PMT_F, &result);
|
||||
}
|
||||
|
||||
|
||||
test_usrp_inband_registers::test_usrp_inband_registers(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
|
||||
: mb_mblock(runtime, instance_name, user_arg),
|
||||
d_tx_chan(PMT_NIL),
|
||||
d_rx_chan(PMT_NIL),
|
||||
d_which_usrp(pmt_from_long(0)),
|
||||
d_state(INIT)
|
||||
{
|
||||
|
||||
// A dictionary is used to pass parameters to the USRP
|
||||
pmt_t usrp_dict = pmt_make_dict();
|
||||
|
||||
// Specify the RBF to use
|
||||
pmt_dict_set(usrp_dict,
|
||||
pmt_intern("rbf"),
|
||||
pmt_intern("inband_1rxhb_1tx.rbf"));
|
||||
|
||||
// Set TX and RX interpolations
|
||||
pmt_dict_set(usrp_dict,
|
||||
pmt_intern("interp-tx"),
|
||||
pmt_from_long(128));
|
||||
|
||||
pmt_dict_set(usrp_dict,
|
||||
pmt_intern("decim-rx"),
|
||||
pmt_from_long(16));
|
||||
|
||||
d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
|
||||
d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
|
||||
d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
|
||||
|
||||
// Create an instance of USRP server and connect ports
|
||||
define_component("server", "usrp_server", usrp_dict);
|
||||
connect("self", "tx0", "server", "tx0");
|
||||
connect("self", "rx0", "server", "rx0");
|
||||
connect("self", "cs", "server", "cs");
|
||||
|
||||
}
|
||||
|
||||
test_usrp_inband_registers::~test_usrp_inband_registers()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_inband_registers::initial_transition()
|
||||
{
|
||||
opening_usrp();
|
||||
}
|
||||
|
||||
// Handle message reads all incoming messages from USRP server which will be
|
||||
// initialization and ping responses. We perform actions based on the current
|
||||
// state and the event (ie, ping response)
|
||||
void
|
||||
test_usrp_inband_registers::handle_message(mb_message_sptr msg)
|
||||
{
|
||||
pmt_t event = msg->signal();
|
||||
pmt_t data = msg->data();
|
||||
pmt_t port_id = msg->port_id();
|
||||
|
||||
pmt_t handle = PMT_F;
|
||||
pmt_t status = PMT_F;
|
||||
std::string error_msg;
|
||||
|
||||
// Dispatch based on state
|
||||
switch(d_state) {
|
||||
|
||||
//----------------------------- OPENING_USRP ----------------------------//
|
||||
// We only expect a response from opening the USRP which should be succesful
|
||||
// or failed.
|
||||
case OPENING_USRP:
|
||||
|
||||
if(pmt_eq(event, s_response_open)) {
|
||||
|
||||
status = pmt_nth(1, data); // failed/succes
|
||||
|
||||
if(pmt_eq(status, PMT_T)) {
|
||||
allocating_channels();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "failed to open usrp:";
|
||||
goto bail;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
goto unhandled; // all other messages not handled in this state
|
||||
|
||||
|
||||
//----------------------- ALLOCATING CHANNELS --------------------//
|
||||
// When allocating channels, we need to wait for 2 responses from
|
||||
// USRP server: one for TX and one for RX. Both are initialized to
|
||||
// NIL so we know to continue to the next state once both are set.
|
||||
case ALLOCATING_CHANNELS:
|
||||
|
||||
// A TX allocation response
|
||||
if(pmt_eq(event, s_response_allocate_channel)
|
||||
&& pmt_eq(d_tx->port_symbol(), port_id))
|
||||
{
|
||||
status = pmt_nth(1, data);
|
||||
|
||||
// If successful response, extract the channel
|
||||
if(pmt_eq(status, PMT_T)) {
|
||||
|
||||
d_tx_chan = pmt_nth(2, data);
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_PING] Received TX allocation"
|
||||
<< " on channel " << d_tx_chan << std::endl;
|
||||
|
||||
// If the RX has also been allocated already, we can continue
|
||||
if(!pmt_eqv(d_rx_chan, PMT_NIL)) {
|
||||
enter_receiving();
|
||||
write_register();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else { // TX allocation failed
|
||||
error_msg = "failed to allocate TX channel:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
// A RX allocation response
|
||||
if(pmt_eq(event, s_response_allocate_channel)
|
||||
&& pmt_eq(d_rx->port_symbol(), port_id))
|
||||
{
|
||||
status = pmt_nth(1, data);
|
||||
|
||||
// If successful response, extract the channel
|
||||
if(pmt_eq(status, PMT_T)) {
|
||||
|
||||
d_rx_chan = pmt_nth(2, data);
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_PING] Received RX allocation"
|
||||
<< " on channel " << d_rx_chan << std::endl;
|
||||
|
||||
// If the TX has also been allocated already, we can continue
|
||||
if(!pmt_eqv(d_tx_chan, PMT_NIL)) {
|
||||
enter_receiving();
|
||||
write_register();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else { // RX allocation failed
|
||||
error_msg = "failed to allocate RX channel:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
goto unhandled;
|
||||
|
||||
//-------------------------- WRITE REGISTER ----------------------------//
|
||||
// In the write register state, we do not expect to receive any messages
|
||||
// since the write does not directly generate a response until the USRP
|
||||
// responds.
|
||||
case WRITE_REGISTER:
|
||||
goto unhandled;
|
||||
|
||||
//-------------------------- READ REGISTER ----------------------------//
|
||||
// In the read register state, we only expect a read register response back
|
||||
// that has the value we expect to have in it. We read the response, ensure
|
||||
// that the read was successful and display the register value.
|
||||
case READ_REGISTER:
|
||||
|
||||
if(pmt_eq(event, s_response_from_control_channel)
|
||||
&& pmt_eq(d_tx->port_symbol(), port_id))
|
||||
{
|
||||
status = pmt_nth(1, data);
|
||||
|
||||
// If the read was successful, we extract the subpacket information
|
||||
if(pmt_eq(status, PMT_T)) {
|
||||
|
||||
pmt_t subp = pmt_nth(2, data); // subpacket should be the read reg reply
|
||||
|
||||
pmt_t subp_sig = pmt_nth(0, subp);
|
||||
pmt_t subp_data = pmt_nth(1, subp);
|
||||
|
||||
if(!pmt_eqv(subp_sig, s_op_read_reg_reply)) {
|
||||
error_msg = "received improper subpacket when expecting reg reply.";
|
||||
goto bail;
|
||||
}
|
||||
|
||||
pmt_t rid = pmt_nth(0, subp_data);
|
||||
pmt_t reg_num = pmt_nth(1, subp_data);
|
||||
pmt_t reg_val = pmt_nth(2, subp_data);
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_REGISTERS] Received read reg reply "
|
||||
<< "("
|
||||
<< "RID: " << rid << ", "
|
||||
<< "Reg: " << reg_num << ", "
|
||||
<< "Val: " << reg_val
|
||||
<< ")\n";
|
||||
|
||||
// read_register(); FIX ME STATE TRANSITION
|
||||
return;
|
||||
|
||||
} else { // bail on unsuccessful write
|
||||
error_msg = "failed to write to register.";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
goto unhandled;
|
||||
|
||||
case CLOSING_CHANNELS:
|
||||
goto unhandled;
|
||||
|
||||
case CLOSING_USRP:
|
||||
goto unhandled;
|
||||
|
||||
case INIT:
|
||||
goto unhandled;
|
||||
|
||||
}
|
||||
|
||||
// An error occured, print it, and shutdown all m-blocks
|
||||
bail:
|
||||
std::cerr << error_msg << data
|
||||
<< "status = " << status << std::endl;
|
||||
shutdown_all(PMT_F);
|
||||
return;
|
||||
|
||||
// Received an unhandled message for a specific state
|
||||
unhandled:
|
||||
if(verbose && !pmt_eq(event, s_response_recv_raw_samples))
|
||||
std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
|
||||
<< "in state "<< d_state << std::endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Sends a command to USRP server to open up a connection to the
|
||||
// specified USRP, which is defaulted to USRP 0 on the system
|
||||
void
|
||||
test_usrp_inband_registers::opening_usrp()
|
||||
{
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_PING] Opening USRP "
|
||||
<< d_which_usrp << std::endl;
|
||||
|
||||
d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, d_which_usrp));
|
||||
d_state = OPENING_USRP;
|
||||
}
|
||||
|
||||
// RX and TX channels must be allocated so that the USRP server can
|
||||
// properly share bandwidth across multiple USRPs. No commands will be
|
||||
// successful to the USRP through the USRP server on the TX or RX channels until
|
||||
// a bandwidth allocation has been received.
|
||||
void
|
||||
test_usrp_inband_registers::allocating_channels()
|
||||
{
|
||||
d_state = ALLOCATING_CHANNELS;
|
||||
|
||||
long capacity = (long) 16e6;
|
||||
d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
|
||||
d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
|
||||
}
|
||||
|
||||
// After allocating the channels, a write register command will be sent to the
|
||||
// USRP.
|
||||
void
|
||||
test_usrp_inband_registers::write_register()
|
||||
{
|
||||
d_state = WRITE_REGISTER;
|
||||
|
||||
long reg = 0;
|
||||
|
||||
d_tx->send(s_cmd_to_control_channel, // C/S packet
|
||||
pmt_list2(PMT_NIL, // invoc handle
|
||||
pmt_list1(
|
||||
pmt_list2(s_op_write_reg,
|
||||
pmt_list2(
|
||||
pmt_from_long(reg),
|
||||
pmt_from_long(0xbeef))))));
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_REGISTERS] Writing 0xbeef to "
|
||||
<< reg << std::endl;
|
||||
|
||||
read_register(); // immediately transition to read the register
|
||||
}
|
||||
|
||||
// Temporary: for testing pings
|
||||
void
|
||||
test_usrp_inband_registers::build_and_send_ping()
|
||||
{
|
||||
|
||||
d_tx->send(s_cmd_to_control_channel,
|
||||
pmt_list2(PMT_NIL, pmt_list1(pmt_list2(s_op_ping_fixed,
|
||||
pmt_list2(pmt_from_long(0),
|
||||
pmt_from_long(0))))));
|
||||
|
||||
std::cout << "[TEST_USRP_INBAND_CS] Ping sent" << std::endl;
|
||||
}
|
||||
|
||||
// After writing to the register, we want to read the value back and ensure that
|
||||
// it is the same value that we wrote.
|
||||
void
|
||||
test_usrp_inband_registers::read_register()
|
||||
{
|
||||
d_state = READ_REGISTER;
|
||||
|
||||
long reg = 9;
|
||||
|
||||
d_tx->send(s_cmd_to_control_channel, // C/S packet
|
||||
pmt_list2(PMT_NIL, // invoc handle
|
||||
pmt_list1(
|
||||
pmt_list2(s_op_read_reg,
|
||||
pmt_list2(
|
||||
pmt_from_long(0), // rid
|
||||
pmt_from_long(reg))))));
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_REGISTERS] Reading from register "
|
||||
<< reg << std::endl;
|
||||
}
|
||||
|
||||
// Used to enter the receiving state
|
||||
void
|
||||
test_usrp_inband_registers::enter_receiving()
|
||||
{
|
||||
d_rx->send(s_cmd_start_recv_raw_samples,
|
||||
pmt_list2(PMT_F,
|
||||
d_rx_chan));
|
||||
}
|
||||
|
||||
REGISTER_MBLOCK_CLASS(test_usrp_inband_registers);
|
|
@ -1,362 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <mblock/mblock.h>
|
||||
#include <mblock/runtime.h>
|
||||
#include <mblock/protocol_class.h>
|
||||
#include <mblock/exception.h>
|
||||
#include <mblock/msg_queue.h>
|
||||
#include <mblock/message.h>
|
||||
#include <mblock/msg_accepter.h>
|
||||
#include <mblock/class_registry.h>
|
||||
#include <pmt.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
// Include the symbols needed for communication with USRP server
|
||||
#include <symbols_usrp_server_cs.h>
|
||||
#include <symbols_usrp_channel.h>
|
||||
#include <symbols_usrp_low_level_cs.h>
|
||||
#include <symbols_usrp_rx.h>
|
||||
|
||||
static bool verbose = true;
|
||||
|
||||
class test_usrp_rx : public mb_mblock
|
||||
{
|
||||
mb_port_sptr d_rx;
|
||||
mb_port_sptr d_cs;
|
||||
pmt_t d_rx_chan; // returned tx channel handle
|
||||
|
||||
enum state_t {
|
||||
INIT,
|
||||
OPENING_USRP,
|
||||
ALLOCATING_CHANNEL,
|
||||
RECEIVING,
|
||||
CLOSING_CHANNEL,
|
||||
CLOSING_USRP,
|
||||
};
|
||||
|
||||
state_t d_state;
|
||||
|
||||
std::ofstream d_ofile;
|
||||
|
||||
long d_samples_recvd;
|
||||
long d_samples_to_recv;
|
||||
|
||||
public:
|
||||
test_usrp_rx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
|
||||
~test_usrp_rx();
|
||||
void initial_transition();
|
||||
void handle_message(mb_message_sptr msg);
|
||||
|
||||
protected:
|
||||
void open_usrp();
|
||||
void close_usrp();
|
||||
void allocate_channel();
|
||||
void send_packets();
|
||||
void enter_receiving();
|
||||
void build_and_send_next_frame();
|
||||
void handle_response_recv_raw_samples(pmt_t invocation_handle);
|
||||
void enter_closing_channel();
|
||||
};
|
||||
|
||||
test_usrp_rx::test_usrp_rx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
|
||||
: mb_mblock(runtime, instance_name, user_arg),
|
||||
d_samples_recvd(0),
|
||||
d_samples_to_recv(20e6)
|
||||
{
|
||||
d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
|
||||
d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
|
||||
|
||||
// Pass a dictionary to usrp_server which specifies which interface to use, the stub or USRP
|
||||
pmt_t usrp_dict = pmt_make_dict();
|
||||
|
||||
// To test the application without a USRP
|
||||
bool fake_usrp_p = false;
|
||||
if(fake_usrp_p) {
|
||||
pmt_dict_set(usrp_dict,
|
||||
pmt_intern("fake-usrp"),
|
||||
PMT_T);
|
||||
}
|
||||
|
||||
// Specify the RBF to use
|
||||
pmt_dict_set(usrp_dict,
|
||||
pmt_intern("rbf"),
|
||||
pmt_intern("inband_1rxhb_1tx.rbf"));
|
||||
|
||||
pmt_dict_set(usrp_dict,
|
||||
pmt_intern("decim-rx"),
|
||||
pmt_from_long(64));
|
||||
|
||||
// If unspecified, chooses center frequency from range
|
||||
// pmt_dict_set(usrp_dict,
|
||||
// pmt_intern("rf-freq"),
|
||||
// pmt_from_long(10e6));
|
||||
|
||||
define_component("server", "usrp_server", usrp_dict);
|
||||
|
||||
connect("self", "rx0", "server", "rx0");
|
||||
connect("self", "cs", "server", "cs");
|
||||
|
||||
}
|
||||
|
||||
test_usrp_rx::~test_usrp_rx()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_rx::initial_transition()
|
||||
{
|
||||
open_usrp();
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_rx::handle_message(mb_message_sptr msg)
|
||||
{
|
||||
pmt_t event = msg->signal();
|
||||
pmt_t data = msg->data();
|
||||
|
||||
pmt_t handle = PMT_F;
|
||||
pmt_t status = PMT_F;
|
||||
std::string error_msg;
|
||||
|
||||
switch(d_state){
|
||||
|
||||
//----------------------------- OPENING_USRP ----------------------------//
|
||||
// We only expect a response from opening the USRP which should be succesful
|
||||
// or failed.
|
||||
case OPENING_USRP:
|
||||
if (pmt_eq(event, s_response_open)){
|
||||
status = pmt_nth(1, data);
|
||||
if (pmt_eq(status, PMT_T)){
|
||||
allocate_channel();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "failed to open usrp:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
goto unhandled;
|
||||
|
||||
//----------------------- ALLOCATING CHANNELS --------------------//
|
||||
// Allocate an RX channel to perform the overrun test.
|
||||
case ALLOCATING_CHANNEL:
|
||||
if (pmt_eq(event, s_response_allocate_channel)){
|
||||
status = pmt_nth(1, data);
|
||||
d_rx_chan = pmt_nth(2, data);
|
||||
|
||||
if (pmt_eq(status, PMT_T)){
|
||||
enter_receiving();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "failed to allocate channel:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
goto unhandled;
|
||||
|
||||
//--------------------------- RECEIVING ------------------------------//
|
||||
// In the receiving state, we receive samples until the specified amount
|
||||
// while counting the number of overruns.
|
||||
case RECEIVING:
|
||||
if (pmt_eq(event, s_response_recv_raw_samples)){
|
||||
status = pmt_nth(1, data);
|
||||
|
||||
if (pmt_eq(status, PMT_T)){
|
||||
handle_response_recv_raw_samples(data);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "bad response-xmit-raw-frame:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
goto unhandled;
|
||||
|
||||
//------------------------- CLOSING CHANNEL ----------------------------//
|
||||
// Check deallocation response for the RX channel
|
||||
case CLOSING_CHANNEL:
|
||||
if (pmt_eq(event, s_response_deallocate_channel)){
|
||||
status = pmt_nth(1, data);
|
||||
|
||||
if (pmt_eq(status, PMT_T)){
|
||||
close_usrp();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "failed to deallocate channel:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
// Alternately, we ignore all response recv samples while waiting for the
|
||||
// channel to actually close
|
||||
if (pmt_eq(event, s_response_recv_raw_samples))
|
||||
return;
|
||||
|
||||
goto unhandled;
|
||||
|
||||
//--------------------------- CLOSING USRP ------------------------------//
|
||||
// Once we have received a successful USRP close response, we shutdown all
|
||||
// mblocks and exit.
|
||||
case CLOSING_USRP:
|
||||
if (pmt_eq(event, s_response_close)){
|
||||
status = pmt_nth(1, data);
|
||||
|
||||
if (pmt_eq(status, PMT_T)){
|
||||
fflush(stdout);
|
||||
shutdown_all(PMT_T);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "failed to close USRP:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
goto unhandled;
|
||||
|
||||
default:
|
||||
goto unhandled;
|
||||
}
|
||||
return;
|
||||
|
||||
// An error occured, print it, and shutdown all m-blocks
|
||||
bail:
|
||||
std::cerr << error_msg << data
|
||||
<< "status = " << status << std::endl;
|
||||
shutdown_all(PMT_F);
|
||||
return;
|
||||
|
||||
// Received an unhandled message for a specific state
|
||||
unhandled:
|
||||
if(verbose && !pmt_eq(event, pmt_intern("%shutdown")))
|
||||
std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
|
||||
<< "in state "<< d_state << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
test_usrp_rx::open_usrp()
|
||||
{
|
||||
pmt_t which_usrp = pmt_from_long(0);
|
||||
|
||||
d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, which_usrp));
|
||||
d_state = OPENING_USRP;
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_RX] Opening the USRP\n";
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_rx::close_usrp()
|
||||
{
|
||||
|
||||
d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
|
||||
d_state = CLOSING_USRP;
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_RX] Closing the USRP\n";
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_rx::allocate_channel()
|
||||
{
|
||||
long capacity = (long) 16e6;
|
||||
d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
|
||||
d_state = ALLOCATING_CHANNEL;
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_RX] Requesting RX channel allocation\n";
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_rx::enter_receiving()
|
||||
{
|
||||
d_state = RECEIVING;
|
||||
|
||||
d_rx->send(s_cmd_start_recv_raw_samples,
|
||||
pmt_list2(PMT_F,
|
||||
d_rx_chan));
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_RX] Receiving...\n";
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_rx::handle_response_recv_raw_samples(pmt_t data)
|
||||
{
|
||||
pmt_t invocation_handle = pmt_nth(0, data);
|
||||
pmt_t status = pmt_nth(1, data);
|
||||
pmt_t v_samples = pmt_nth(2, data);
|
||||
pmt_t timestamp = pmt_nth(3, data);
|
||||
pmt_t channel = pmt_nth(4, data);
|
||||
pmt_t properties = pmt_nth(5, data);
|
||||
|
||||
d_samples_recvd += pmt_length(v_samples) / 4;
|
||||
|
||||
// Check for overrun
|
||||
if(!pmt_is_dict(properties)) {
|
||||
std::cout << "[TEST_USRP_INBAND_RX] Recv samples dictionary is improper\n";
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the number samples we have received meets the test
|
||||
if(d_samples_recvd >= d_samples_to_recv) {
|
||||
d_rx->send(s_cmd_stop_recv_raw_samples, pmt_list2(PMT_NIL, d_rx_chan));
|
||||
enter_closing_channel();
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_rx::enter_closing_channel()
|
||||
{
|
||||
d_state = CLOSING_CHANNEL;
|
||||
|
||||
d_rx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_rx_chan));
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_RX] Deallocating RX channel\n";
|
||||
}
|
||||
|
||||
REGISTER_MBLOCK_CLASS(test_usrp_rx);
|
||||
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
mb_runtime_sptr rt = mb_make_runtime();
|
||||
pmt_t result = PMT_NIL;
|
||||
|
||||
rt->run("top", "test_usrp_rx", PMT_F, &result);
|
||||
|
||||
}
|
|
@ -1,506 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007,2008 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <mblock/mblock.h>
|
||||
#include <mblock/runtime.h>
|
||||
#include <mblock/protocol_class.h>
|
||||
#include <mblock/exception.h>
|
||||
#include <mblock/msg_queue.h>
|
||||
#include <mblock/message.h>
|
||||
#include <mblock/msg_accepter.h>
|
||||
#include <mblock/class_registry.h>
|
||||
#include <pmt.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <ui_nco.h>
|
||||
#include <symbols_usrp_server_cs.h>
|
||||
#include <symbols_usrp_channel.h>
|
||||
#include <symbols_usrp_low_level_cs.h>
|
||||
#include <symbols_usrp_tx.h>
|
||||
#include <symbols_usrp_rx.h>
|
||||
|
||||
#define NBPING 10
|
||||
|
||||
static bool verbose = true;
|
||||
bool bskip = false;
|
||||
long bstep = 10000;
|
||||
long bcurr = 0;
|
||||
long incr = 0x500;
|
||||
long ptime = 0x000;
|
||||
|
||||
class test_usrp_inband_timestamps : public mb_mblock
|
||||
{
|
||||
mb_port_sptr d_tx;
|
||||
mb_port_sptr d_rx;
|
||||
mb_port_sptr d_cs;
|
||||
pmt_t d_tx_chan; // returned tx channel handle
|
||||
pmt_t d_rx_chan; // returned tx channel handle
|
||||
|
||||
struct timeval times[NBPING];
|
||||
|
||||
enum state_t {
|
||||
INIT,
|
||||
OPENING_USRP,
|
||||
ALLOCATING_CHANNEL,
|
||||
TRANSMITTING,
|
||||
CLOSING_CHANNEL,
|
||||
CLOSING_USRP,
|
||||
};
|
||||
|
||||
state_t d_state;
|
||||
long d_nsamples_to_send;
|
||||
long d_nsamples_xmitted;
|
||||
long d_nframes_xmitted;
|
||||
long d_samples_per_frame;
|
||||
bool d_done_sending;
|
||||
|
||||
// for generating sine wave output
|
||||
ui_nco<float,float> d_nco;
|
||||
double d_amplitude;
|
||||
|
||||
public:
|
||||
test_usrp_inband_timestamps(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
|
||||
~test_usrp_inband_timestamps();
|
||||
void initial_transition();
|
||||
void handle_message(mb_message_sptr msg);
|
||||
|
||||
protected:
|
||||
void open_usrp();
|
||||
void close_usrp();
|
||||
void allocate_channel();
|
||||
void send_packets();
|
||||
void enter_receiving();
|
||||
void enter_transmitting();
|
||||
void build_and_send_ping();
|
||||
void build_and_send_next_frame();
|
||||
void handle_xmit_response(pmt_t invocation_handle);
|
||||
void enter_closing_channel();
|
||||
};
|
||||
|
||||
test_usrp_inband_timestamps::test_usrp_inband_timestamps(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
|
||||
: mb_mblock(runtime, instance_name, user_arg),
|
||||
d_tx_chan(PMT_NIL),
|
||||
d_rx_chan(PMT_NIL),
|
||||
d_state(INIT), d_nsamples_to_send((long) 40e6),
|
||||
d_nsamples_xmitted(0),
|
||||
d_nframes_xmitted(0),
|
||||
//d_samples_per_frame((long)(126)),
|
||||
d_samples_per_frame((long)(126 * 2)), // non-full packet
|
||||
//d_samples_per_frame((long)(126 * 3.5)), // non-full packet
|
||||
//d_samples_per_frame((long)(126 * 4)), // full packet
|
||||
d_done_sending(false),
|
||||
d_amplitude(16384)
|
||||
{
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Initializing...\n";
|
||||
|
||||
d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
|
||||
d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
|
||||
d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
|
||||
|
||||
bool fake_usrp_p = false;
|
||||
|
||||
// Test the TX side
|
||||
|
||||
pmt_t usrp_dict = pmt_make_dict();
|
||||
|
||||
if(fake_usrp_p) {
|
||||
pmt_dict_set(usrp_dict,
|
||||
pmt_intern("fake-usrp"),
|
||||
PMT_T);
|
||||
}
|
||||
|
||||
// Set TX and RX interpolations
|
||||
pmt_dict_set(usrp_dict,
|
||||
pmt_intern("interp-tx"),
|
||||
pmt_from_long(128));
|
||||
|
||||
pmt_dict_set(usrp_dict,
|
||||
pmt_intern("decim-rx"),
|
||||
pmt_from_long(16));
|
||||
|
||||
// Specify the RBF to use
|
||||
pmt_dict_set(usrp_dict,
|
||||
pmt_intern("rbf"),
|
||||
pmt_intern("inband_1rxhb_1tx.rbf"));
|
||||
|
||||
define_component("server", "usrp_server", usrp_dict);
|
||||
|
||||
connect("self", "tx0", "server", "tx0");
|
||||
connect("self", "rx0", "server", "rx0");
|
||||
connect("self", "cs", "server", "cs");
|
||||
|
||||
// initialize NCO
|
||||
double freq = 100e3;
|
||||
int interp = 32; // 32 -> 4MS/s
|
||||
double sample_rate = 128e6 / interp;
|
||||
d_nco.set_freq(2*M_PI * freq/sample_rate);
|
||||
|
||||
}
|
||||
|
||||
test_usrp_inband_timestamps::~test_usrp_inband_timestamps()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_inband_timestamps::initial_transition()
|
||||
{
|
||||
open_usrp();
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_inband_timestamps::handle_message(mb_message_sptr msg)
|
||||
{
|
||||
pmt_t event = msg->signal();
|
||||
pmt_t data = msg->data();
|
||||
pmt_t port_id = msg->port_id();
|
||||
|
||||
pmt_t handle = PMT_F;
|
||||
pmt_t status = PMT_F;
|
||||
std::string error_msg;
|
||||
|
||||
//std::cout << msg << std::endl;
|
||||
|
||||
switch(d_state){
|
||||
case OPENING_USRP:
|
||||
if (pmt_eq(event, s_response_open)){
|
||||
status = pmt_nth(1, data);
|
||||
if (pmt_eq(status, PMT_T)){
|
||||
allocate_channel();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "failed to open usrp:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
goto unhandled;
|
||||
|
||||
case ALLOCATING_CHANNEL:
|
||||
if (pmt_eq(event, s_response_allocate_channel)){
|
||||
|
||||
if(pmt_eq(d_tx->port_symbol(), port_id)) {
|
||||
status = pmt_nth(1, data);
|
||||
d_tx_chan = pmt_nth(2, data);
|
||||
|
||||
if (pmt_eq(status, PMT_T)){
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Received allocation for TX\n";
|
||||
|
||||
if(!pmt_eqv(d_rx_chan, PMT_NIL)) {
|
||||
enter_receiving();
|
||||
enter_transmitting();
|
||||
}
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "failed to allocate channel:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
if(pmt_eq(d_rx->port_symbol(), port_id)) {
|
||||
status = pmt_nth(1, data);
|
||||
d_rx_chan = pmt_nth(2, data);
|
||||
|
||||
if (pmt_eq(status, PMT_T)){
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Received allocation for TX\n";
|
||||
|
||||
if(!pmt_eqv(d_tx_chan, PMT_NIL)) {
|
||||
enter_receiving();
|
||||
enter_transmitting();
|
||||
}
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "failed to allocate channel:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
}
|
||||
goto unhandled;
|
||||
|
||||
case TRANSMITTING:
|
||||
if (pmt_eq(event, s_response_xmit_raw_frame)){
|
||||
handle = pmt_nth(0, data);
|
||||
status = pmt_nth(1, data);
|
||||
|
||||
if (pmt_eq(status, PMT_T)){
|
||||
handle_xmit_response(handle);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "bad response-xmit-raw-frame:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
if (pmt_eq(event, s_response_from_control_channel)) {
|
||||
std::cout << "ping response!\n";
|
||||
}
|
||||
goto unhandled;
|
||||
|
||||
case CLOSING_CHANNEL:
|
||||
if (pmt_eq(event, s_response_deallocate_channel)){
|
||||
status = pmt_nth(1, data);
|
||||
|
||||
if (pmt_eq(status, PMT_T)){
|
||||
close_usrp();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "failed to deallocate channel:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
goto unhandled;
|
||||
|
||||
case CLOSING_USRP:
|
||||
if (pmt_eq(event, s_response_close)){
|
||||
status = pmt_nth(1, data);
|
||||
|
||||
if (pmt_eq(status, PMT_T)){
|
||||
shutdown_all(PMT_T);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "failed to close USRP:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
goto unhandled;
|
||||
|
||||
default:
|
||||
goto unhandled;
|
||||
}
|
||||
return;
|
||||
|
||||
bail:
|
||||
std::cerr << error_msg << data
|
||||
<< "status = " << status << std::endl;
|
||||
shutdown_all(PMT_F);
|
||||
return;
|
||||
|
||||
unhandled:
|
||||
if(verbose && 0)
|
||||
std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
|
||||
<< "in state "<< d_state << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
test_usrp_inband_timestamps::open_usrp()
|
||||
{
|
||||
pmt_t which_usrp = pmt_from_long(0);
|
||||
|
||||
d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, which_usrp));
|
||||
d_state = OPENING_USRP;
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_inband_timestamps::close_usrp()
|
||||
{
|
||||
d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
|
||||
d_state = CLOSING_USRP;
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Closing USRP\n";
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_inband_timestamps::allocate_channel()
|
||||
{
|
||||
long capacity = (long) 16e6;
|
||||
d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
|
||||
d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
|
||||
d_state = ALLOCATING_CHANNEL;
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_inband_timestamps::enter_receiving()
|
||||
{
|
||||
d_rx->send(s_cmd_start_recv_raw_samples,
|
||||
pmt_list2(PMT_F,
|
||||
d_rx_chan));
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_inband_timestamps::enter_transmitting()
|
||||
{
|
||||
d_state = TRANSMITTING;
|
||||
d_nsamples_xmitted = 0;
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Beginning transmission\n";
|
||||
|
||||
sleep(1);
|
||||
|
||||
build_and_send_next_frame();
|
||||
build_and_send_next_frame();
|
||||
build_and_send_next_frame();
|
||||
build_and_send_next_frame();
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_inband_timestamps::build_and_send_ping()
|
||||
{
|
||||
|
||||
d_tx->send(s_cmd_to_control_channel,
|
||||
pmt_list2(PMT_NIL, pmt_list1(pmt_list2(s_op_ping_fixed,
|
||||
pmt_list2(pmt_from_long(0),
|
||||
pmt_from_long(0))))));
|
||||
if(verbose && 0)
|
||||
std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Ping sent" << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_inband_timestamps::build_and_send_next_frame()
|
||||
{
|
||||
// allocate the uniform vector for the samples
|
||||
// FIXME perhaps hold on to this between calls
|
||||
|
||||
#if 0
|
||||
long nsamples_this_frame =
|
||||
std::min(d_nsamples_to_send - d_nsamples_xmitted,
|
||||
d_samples_per_frame);
|
||||
#else
|
||||
long nsamples_this_frame = d_samples_per_frame;
|
||||
#endif
|
||||
|
||||
if (nsamples_this_frame == 0){
|
||||
d_done_sending = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
size_t nshorts = 2 * nsamples_this_frame; // 16-bit I & Q
|
||||
pmt_t uvec = pmt_make_s16vector(nshorts, 0);
|
||||
size_t ignore;
|
||||
int16_t *samples = pmt_s16vector_writable_elements(uvec, ignore);
|
||||
|
||||
// fill in the complex sinusoid
|
||||
|
||||
for (int i = 0; i < nsamples_this_frame; i++){
|
||||
|
||||
if (1){
|
||||
gr_complex s;
|
||||
d_nco.sincos(&s, 1, d_amplitude);
|
||||
// write 16-bit i & q
|
||||
samples[2*i] = (int16_t) s.real();
|
||||
samples[2*i+1] = (int16_t) s.imag();
|
||||
}
|
||||
else {
|
||||
gr_complex s(d_amplitude, d_amplitude);
|
||||
|
||||
// write 16-bit i & q
|
||||
samples[2*i] = (int16_t) s.real();
|
||||
samples[2*i+1] = (int16_t) s.imag();
|
||||
}
|
||||
}
|
||||
|
||||
pmt_t timestamp;
|
||||
|
||||
if(bskip) {
|
||||
timestamp = pmt_from_long(0x0); // throw away
|
||||
bcurr++;
|
||||
if(bcurr == bstep) {
|
||||
bskip = false;
|
||||
bcurr = 0;
|
||||
}
|
||||
} else {
|
||||
timestamp = pmt_from_long(0xffffffff); // NOW
|
||||
timestamp = pmt_from_long(ptime);
|
||||
ptime += incr;
|
||||
bcurr++;
|
||||
if(bcurr == bstep) {
|
||||
//bskip = true;
|
||||
bcurr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << bskip << " -- " << bcurr << std::endl;
|
||||
|
||||
d_tx->send(s_cmd_xmit_raw_frame,
|
||||
pmt_list4(pmt_from_long(d_nframes_xmitted), // invocation-handle
|
||||
d_tx_chan, // channel
|
||||
uvec, // the samples
|
||||
timestamp));
|
||||
|
||||
d_nsamples_xmitted += nsamples_this_frame;
|
||||
d_nframes_xmitted++;
|
||||
|
||||
if(verbose && 0)
|
||||
std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Transmitted frame\n";
|
||||
|
||||
//build_and_send_next_frame();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
test_usrp_inband_timestamps::handle_xmit_response(pmt_t handle)
|
||||
{
|
||||
if (d_done_sending &&
|
||||
pmt_to_long(handle) == (d_nframes_xmitted - 1)){
|
||||
// We're done sending and have received all responses
|
||||
enter_closing_channel();
|
||||
}
|
||||
|
||||
build_and_send_next_frame();
|
||||
//build_and_send_ping();
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_inband_timestamps::enter_closing_channel()
|
||||
{
|
||||
d_state = CLOSING_CHANNEL;
|
||||
|
||||
d_tx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_tx_chan));
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Closing channel\n";
|
||||
}
|
||||
|
||||
REGISTER_MBLOCK_CLASS(test_usrp_inband_timestamps);
|
||||
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
// handle any command line args here
|
||||
|
||||
mb_runtime_sptr rt = mb_make_runtime();
|
||||
pmt_t result = PMT_NIL;
|
||||
|
||||
rt->run("top", "test_usrp_inband_timestamps", PMT_F, &result);
|
||||
}
|
|
@ -1,411 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007,2008 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <mblock/mblock.h>
|
||||
#include <mblock/runtime.h>
|
||||
#include <mblock/protocol_class.h>
|
||||
#include <mblock/exception.h>
|
||||
#include <mblock/msg_queue.h>
|
||||
#include <mblock/message.h>
|
||||
#include <mblock/msg_accepter.h>
|
||||
#include <mblock/class_registry.h>
|
||||
#include <pmt.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <ui_nco.h>
|
||||
#include <symbols_usrp_server_cs.h>
|
||||
#include <symbols_usrp_channel.h>
|
||||
#include <symbols_usrp_low_level_cs.h>
|
||||
#include <symbols_usrp_tx.h>
|
||||
|
||||
static bool verbose = true;
|
||||
|
||||
class test_usrp_tx : public mb_mblock
|
||||
{
|
||||
mb_port_sptr d_tx;
|
||||
mb_port_sptr d_cs;
|
||||
pmt_t d_tx_chan; // returned tx channel handle
|
||||
|
||||
enum state_t {
|
||||
INIT,
|
||||
OPENING_USRP,
|
||||
ALLOCATING_CHANNEL,
|
||||
TRANSMITTING,
|
||||
CLOSING_CHANNEL,
|
||||
CLOSING_USRP,
|
||||
};
|
||||
|
||||
state_t d_state;
|
||||
long d_nsamples_to_send;
|
||||
long d_nsamples_xmitted;
|
||||
long d_nframes_xmitted;
|
||||
long d_samples_per_frame;
|
||||
bool d_done_sending;
|
||||
|
||||
// for generating sine wave output
|
||||
ui_nco<float,float> d_nco;
|
||||
double d_amplitude;
|
||||
|
||||
public:
|
||||
test_usrp_tx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
|
||||
~test_usrp_tx();
|
||||
void initial_transition();
|
||||
void handle_message(mb_message_sptr msg);
|
||||
|
||||
protected:
|
||||
void open_usrp();
|
||||
void close_usrp();
|
||||
void allocate_channel();
|
||||
void send_packets();
|
||||
void enter_transmitting();
|
||||
void build_and_send_next_frame();
|
||||
void handle_xmit_response(pmt_t invocation_handle);
|
||||
void enter_closing_channel();
|
||||
};
|
||||
|
||||
test_usrp_tx::test_usrp_tx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
|
||||
: mb_mblock(runtime, instance_name, user_arg),
|
||||
d_state(INIT), d_nsamples_to_send((long) 80e6),
|
||||
d_nsamples_xmitted(0),
|
||||
d_nframes_xmitted(0),
|
||||
d_samples_per_frame((long)(126 * 4)), // full packet
|
||||
d_done_sending(false),
|
||||
d_amplitude(16384)
|
||||
{
|
||||
// std::cout << "[TEST_USRP_TX] Initializing...\n";
|
||||
|
||||
d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
|
||||
d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
|
||||
|
||||
//bool fake_usrp_p = true;
|
||||
bool fake_usrp_p = false;
|
||||
|
||||
// Test the TX side
|
||||
|
||||
pmt_t usrp_dict = pmt_make_dict();
|
||||
|
||||
if(fake_usrp_p) {
|
||||
pmt_dict_set(usrp_dict,
|
||||
pmt_intern("fake-usrp"),
|
||||
PMT_T);
|
||||
}
|
||||
|
||||
// Specify the RBF to use
|
||||
pmt_dict_set(usrp_dict,
|
||||
pmt_intern("rbf"),
|
||||
pmt_intern("inband_1rxhb_1tx.rbf"));
|
||||
|
||||
// Set TX and RX interpolations
|
||||
pmt_dict_set(usrp_dict,
|
||||
pmt_intern("interp-tx"),
|
||||
pmt_from_long(64));
|
||||
|
||||
// If unspecified, chooses center frequency from range
|
||||
// pmt_dict_set(usrp_dict,
|
||||
// pmt_intern("rf-freq"),
|
||||
// pmt_from_long(10e6));
|
||||
|
||||
define_component("server", "usrp_server", usrp_dict);
|
||||
|
||||
connect("self", "tx0", "server", "tx0");
|
||||
connect("self", "cs", "server", "cs");
|
||||
|
||||
// initialize NCO
|
||||
double freq = 100e3;
|
||||
int interp = 32; // 32 -> 4MS/s
|
||||
double sample_rate = 128e6 / interp;
|
||||
d_nco.set_freq(2*M_PI * freq/sample_rate);
|
||||
|
||||
// FIXME need to somehow set the interp rate in the USRP.
|
||||
// for now, we'll have the low-level code hardwire it.
|
||||
}
|
||||
|
||||
test_usrp_tx::~test_usrp_tx()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_tx::initial_transition()
|
||||
{
|
||||
open_usrp();
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_tx::handle_message(mb_message_sptr msg)
|
||||
{
|
||||
pmt_t event = msg->signal();
|
||||
pmt_t data = msg->data();
|
||||
|
||||
pmt_t handle = PMT_F;
|
||||
pmt_t status = PMT_F;
|
||||
std::string error_msg;
|
||||
|
||||
//std::cout << msg << std::endl;
|
||||
|
||||
switch(d_state){
|
||||
case OPENING_USRP:
|
||||
if (pmt_eq(event, s_response_open)){
|
||||
status = pmt_nth(1, data);
|
||||
if (pmt_eq(status, PMT_T)){
|
||||
allocate_channel();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "failed to open usrp:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
goto unhandled;
|
||||
|
||||
case ALLOCATING_CHANNEL:
|
||||
if (pmt_eq(event, s_response_allocate_channel)){
|
||||
status = pmt_nth(1, data);
|
||||
d_tx_chan = pmt_nth(2, data);
|
||||
|
||||
if (pmt_eq(status, PMT_T)){
|
||||
enter_transmitting();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "failed to allocate channel:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
goto unhandled;
|
||||
|
||||
case TRANSMITTING:
|
||||
if (pmt_eq(event, s_response_xmit_raw_frame)){
|
||||
handle = pmt_nth(0, data);
|
||||
status = pmt_nth(1, data);
|
||||
|
||||
if (pmt_eq(status, PMT_T)){
|
||||
handle_xmit_response(handle);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "bad response-xmit-raw-frame:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
goto unhandled;
|
||||
|
||||
case CLOSING_CHANNEL:
|
||||
if (pmt_eq(event, s_response_deallocate_channel)){
|
||||
status = pmt_nth(1, data);
|
||||
|
||||
if (pmt_eq(status, PMT_T)){
|
||||
close_usrp();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "failed to deallocate channel:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
goto unhandled;
|
||||
|
||||
case CLOSING_USRP:
|
||||
if (pmt_eq(event, s_response_close)){
|
||||
status = pmt_nth(1, data);
|
||||
|
||||
if (pmt_eq(status, PMT_T)){
|
||||
shutdown_all(PMT_T);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "failed to close USRP:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
goto unhandled;
|
||||
|
||||
default:
|
||||
goto unhandled;
|
||||
}
|
||||
return;
|
||||
|
||||
bail:
|
||||
std::cerr << error_msg << data
|
||||
<< "status = " << status << std::endl;
|
||||
shutdown_all(PMT_F);
|
||||
return;
|
||||
|
||||
unhandled:
|
||||
std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
|
||||
<< "in state "<< d_state << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
test_usrp_tx::open_usrp()
|
||||
{
|
||||
pmt_t which_usrp = pmt_from_long(0);
|
||||
|
||||
d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, which_usrp));
|
||||
d_state = OPENING_USRP;
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_TX] Opening the USRP\n";
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_tx::close_usrp()
|
||||
{
|
||||
d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
|
||||
d_state = CLOSING_USRP;
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_TX] Closing the USRP\n";
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_tx::allocate_channel()
|
||||
{
|
||||
long capacity = (long) 16e6;
|
||||
d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
|
||||
d_state = ALLOCATING_CHANNEL;
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_TX] Requesting TX channel allocation\n";
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_tx::enter_transmitting()
|
||||
{
|
||||
d_state = TRANSMITTING;
|
||||
d_nsamples_xmitted = 0;
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_TX] Transmitting...\n";
|
||||
|
||||
build_and_send_next_frame(); // fire off 4 to start pipeline
|
||||
build_and_send_next_frame();
|
||||
build_and_send_next_frame();
|
||||
build_and_send_next_frame();
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_tx::build_and_send_next_frame()
|
||||
{
|
||||
// allocate the uniform vector for the samples
|
||||
// FIXME perhaps hold on to this between calls
|
||||
|
||||
#if 1
|
||||
long nsamples_this_frame =
|
||||
std::min(d_nsamples_to_send - d_nsamples_xmitted,
|
||||
d_samples_per_frame);
|
||||
#else
|
||||
long nsamples_this_frame = d_samples_per_frame;
|
||||
#endif
|
||||
|
||||
if (nsamples_this_frame == 0){
|
||||
d_done_sending = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
size_t nshorts = 2 * nsamples_this_frame; // 16-bit I & Q
|
||||
pmt_t uvec = pmt_make_s16vector(nshorts, 0);
|
||||
size_t ignore;
|
||||
int16_t *samples = pmt_s16vector_writable_elements(uvec, ignore);
|
||||
|
||||
// fill in the complex sinusoid
|
||||
|
||||
for (int i = 0; i < nsamples_this_frame; i++){
|
||||
|
||||
if (1){
|
||||
gr_complex s;
|
||||
d_nco.sincos(&s, 1, d_amplitude);
|
||||
// write 16-bit i & q
|
||||
samples[2*i] = (int16_t) s.real();
|
||||
samples[2*i+1] = (int16_t) s.imag();
|
||||
}
|
||||
else {
|
||||
gr_complex s(d_amplitude, d_amplitude);
|
||||
|
||||
// write 16-bit i & q
|
||||
samples[2*i] = (int16_t) s.real();
|
||||
samples[2*i+1] = (int16_t) s.imag();
|
||||
}
|
||||
}
|
||||
|
||||
pmt_t tx_properties = pmt_make_dict();
|
||||
|
||||
pmt_t timestamp = pmt_from_long(0xffffffff); // NOW
|
||||
d_tx->send(s_cmd_xmit_raw_frame,
|
||||
pmt_list5(pmt_from_long(d_nframes_xmitted), // invocation-handle
|
||||
d_tx_chan, // channel
|
||||
uvec, // the samples
|
||||
timestamp,
|
||||
tx_properties));
|
||||
|
||||
d_nsamples_xmitted += nsamples_this_frame;
|
||||
d_nframes_xmitted++;
|
||||
|
||||
if(verbose && 0)
|
||||
std::cout << "[TEST_USRP_INBAND_TX] Transmitted frame\n";
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
test_usrp_tx::handle_xmit_response(pmt_t handle)
|
||||
{
|
||||
if (d_done_sending &&
|
||||
pmt_to_long(handle) == (d_nframes_xmitted - 1)){
|
||||
// We're done sending and have received all responses
|
||||
enter_closing_channel();
|
||||
}
|
||||
|
||||
build_and_send_next_frame();
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_tx::enter_closing_channel()
|
||||
{
|
||||
d_state = CLOSING_CHANNEL;
|
||||
|
||||
d_tx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_tx_chan));
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_tX] Deallocating TX channel\n";
|
||||
}
|
||||
|
||||
REGISTER_MBLOCK_CLASS(test_usrp_tx);
|
||||
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
// handle any command line args here
|
||||
|
||||
mb_runtime_sptr rt = mb_make_runtime();
|
||||
pmt_t result = PMT_NIL;
|
||||
|
||||
rt->run("top", "test_usrp_tx", PMT_F, &result);
|
||||
}
|
|
@ -1,674 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007,2008 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <mblock/mblock.h>
|
||||
#include <mblock/runtime.h>
|
||||
#include <mblock/protocol_class.h>
|
||||
#include <mblock/exception.h>
|
||||
#include <mblock/msg_queue.h>
|
||||
#include <mblock/message.h>
|
||||
#include <mblock/msg_accepter.h>
|
||||
#include <mblock/class_registry.h>
|
||||
#include <pmt.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <iostream>
|
||||
#include <ui_nco.h>
|
||||
|
||||
// Include the symbols needed for communication with USRP server
|
||||
#include <symbols_usrp_server_cs.h>
|
||||
#include <symbols_usrp_channel.h>
|
||||
#include <symbols_usrp_low_level_cs.h>
|
||||
#include <symbols_usrp_tx.h>
|
||||
#include <symbols_usrp_rx.h>
|
||||
|
||||
static bool verbose = true;
|
||||
|
||||
class test_usrp_inband_underrun : public mb_mblock
|
||||
{
|
||||
|
||||
mb_port_sptr d_tx; // Ports connected to the USRP server
|
||||
mb_port_sptr d_rx;
|
||||
mb_port_sptr d_cs;
|
||||
|
||||
pmt_t d_tx_chan; // Returned channel from TX allocation
|
||||
pmt_t d_rx_chan; // Returned channel from RX allocation
|
||||
|
||||
pmt_t d_which_usrp; // The USRP to use for the test
|
||||
|
||||
long d_warm_msgs; // The number of messages to 'warm' the USRP
|
||||
long d_warm_recvd; // The number of msgs received in the 'warm' state
|
||||
|
||||
// Keep track of current state
|
||||
enum state_t {
|
||||
INIT,
|
||||
OPENING_USRP,
|
||||
ALLOCATING_CHANNELS,
|
||||
WRITE_REGISTER,
|
||||
READ_REGISTER,
|
||||
TRANSMITTING,
|
||||
CLOSING_CHANNELS,
|
||||
CLOSING_USRP,
|
||||
};
|
||||
state_t d_state;
|
||||
|
||||
long d_nsamples_to_send;
|
||||
long d_nsamples_xmitted;
|
||||
long d_nframes_xmitted;
|
||||
long d_samples_per_frame;
|
||||
bool d_done_sending;
|
||||
|
||||
// for generating sine wave output
|
||||
ui_nco<float,float> d_nco;
|
||||
double d_amplitude;
|
||||
|
||||
long d_n_underruns;
|
||||
|
||||
public:
|
||||
test_usrp_inband_underrun(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
|
||||
~test_usrp_inband_underrun();
|
||||
void initial_transition();
|
||||
void handle_message(mb_message_sptr msg);
|
||||
|
||||
protected:
|
||||
void opening_usrp();
|
||||
void allocating_channels();
|
||||
void write_register();
|
||||
void read_register();
|
||||
void closing_channels();
|
||||
void closing_usrp();
|
||||
void enter_receiving();
|
||||
void enter_transmitting();
|
||||
void build_and_send_ping();
|
||||
void build_and_send_next_frame();
|
||||
void handle_xmit_response(pmt_t handle);
|
||||
void handle_recv_response(pmt_t dict);
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
// handle any command line args here
|
||||
|
||||
mb_runtime_sptr rt = mb_make_runtime();
|
||||
pmt_t result = PMT_NIL;
|
||||
|
||||
rt->run("top", "test_usrp_inband_underrun", PMT_F, &result);
|
||||
}
|
||||
|
||||
|
||||
test_usrp_inband_underrun::test_usrp_inband_underrun(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
|
||||
: mb_mblock(runtime, instance_name, user_arg),
|
||||
d_tx_chan(PMT_NIL),
|
||||
d_rx_chan(PMT_NIL),
|
||||
d_which_usrp(pmt_from_long(0)),
|
||||
d_state(INIT),
|
||||
d_nsamples_to_send((long) 27e6),
|
||||
d_nsamples_xmitted(0),
|
||||
d_nframes_xmitted(0),
|
||||
d_samples_per_frame(d_nsamples_to_send), // full packet
|
||||
|
||||
d_done_sending(false),
|
||||
d_amplitude(16384),
|
||||
d_n_underruns(0)
|
||||
{
|
||||
|
||||
// A dictionary is used to pass parameters to the USRP
|
||||
pmt_t usrp_dict = pmt_make_dict();
|
||||
|
||||
// Specify the RBF to use
|
||||
pmt_dict_set(usrp_dict,
|
||||
pmt_intern("rbf"),
|
||||
pmt_intern("inband_1rxhb_1tx.rbf"));
|
||||
|
||||
// Set TX and RX interpolations
|
||||
pmt_dict_set(usrp_dict,
|
||||
pmt_intern("interp-tx"),
|
||||
pmt_from_long(64));
|
||||
|
||||
pmt_dict_set(usrp_dict,
|
||||
pmt_intern("decim-rx"),
|
||||
pmt_from_long(128));
|
||||
|
||||
d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
|
||||
d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
|
||||
d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
|
||||
|
||||
// Create an instance of USRP server and connect ports
|
||||
define_component("server", "usrp_server", usrp_dict);
|
||||
connect("self", "tx0", "server", "tx0");
|
||||
connect("self", "rx0", "server", "rx0");
|
||||
connect("self", "cs", "server", "cs");
|
||||
|
||||
// initialize NCO
|
||||
double freq = 100e3;
|
||||
int interp = 32; // 32 -> 4MS/s
|
||||
double sample_rate = 128e6 / interp;
|
||||
d_nco.set_freq(2*M_PI * freq/sample_rate);
|
||||
}
|
||||
|
||||
test_usrp_inband_underrun::~test_usrp_inband_underrun()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_inband_underrun::initial_transition()
|
||||
{
|
||||
opening_usrp();
|
||||
}
|
||||
|
||||
// Handle message reads all incoming messages from USRP server which will be
|
||||
// initialization and ping responses. We perform actions based on the current
|
||||
// state and the event (ie, ping response)
|
||||
void
|
||||
test_usrp_inband_underrun::handle_message(mb_message_sptr msg)
|
||||
{
|
||||
pmt_t event = msg->signal();
|
||||
pmt_t data = msg->data();
|
||||
pmt_t port_id = msg->port_id();
|
||||
|
||||
pmt_t handle = PMT_F;
|
||||
pmt_t status = PMT_F;
|
||||
pmt_t dict = PMT_NIL;
|
||||
std::string error_msg;
|
||||
|
||||
// Check the recv sample responses for underruns and count
|
||||
if(pmt_eq(event, s_response_recv_raw_samples)) {
|
||||
handle = pmt_nth(0, data);
|
||||
status = pmt_nth(1, data);
|
||||
dict = pmt_nth(4, data);
|
||||
|
||||
if(pmt_eq(status, PMT_T)) {
|
||||
handle_recv_response(dict);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "error while receiving samples:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Dispatch based on state
|
||||
switch(d_state) {
|
||||
|
||||
//----------------------------- OPENING_USRP ----------------------------//
|
||||
// We only expect a response from opening the USRP which should be succesful
|
||||
// or failed.
|
||||
case OPENING_USRP:
|
||||
|
||||
if(pmt_eq(event, s_response_open)) {
|
||||
|
||||
status = pmt_nth(1, data); // failed/succes
|
||||
|
||||
if(pmt_eq(status, PMT_T)) {
|
||||
allocating_channels();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "failed to open usrp:";
|
||||
goto bail;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
goto unhandled; // all other messages not handled in this state
|
||||
|
||||
|
||||
//----------------------- ALLOCATING CHANNELS --------------------//
|
||||
// When allocating channels, we need to wait for 2 responses from
|
||||
// USRP server: one for TX and one for RX. Both are initialized to
|
||||
// NIL so we know to continue to the next state once both are set.
|
||||
case ALLOCATING_CHANNELS:
|
||||
|
||||
// A TX allocation response
|
||||
if(pmt_eq(event, s_response_allocate_channel)
|
||||
&& pmt_eq(d_tx->port_symbol(), port_id))
|
||||
{
|
||||
status = pmt_nth(1, data);
|
||||
|
||||
// If successful response, extract the channel
|
||||
if(pmt_eq(status, PMT_T)) {
|
||||
|
||||
d_tx_chan = pmt_nth(2, data);
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_UNDERRUN] Received TX allocation"
|
||||
<< " on channel " << d_tx_chan << std::endl;
|
||||
|
||||
// If the RX has also been allocated already, we can continue
|
||||
if(!pmt_eqv(d_rx_chan, PMT_NIL)) {
|
||||
enter_receiving();
|
||||
enter_transmitting();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else { // TX allocation failed
|
||||
error_msg = "failed to allocate TX channel:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
// A RX allocation response
|
||||
if(pmt_eq(event, s_response_allocate_channel)
|
||||
&& pmt_eq(d_rx->port_symbol(), port_id))
|
||||
{
|
||||
status = pmt_nth(1, data);
|
||||
|
||||
// If successful response, extract the channel
|
||||
if(pmt_eq(status, PMT_T)) {
|
||||
|
||||
d_rx_chan = pmt_nth(2, data);
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_UNDERRUN] Received RX allocation"
|
||||
<< " on channel " << d_rx_chan << std::endl;
|
||||
|
||||
// If the TX has also been allocated already, we can continue
|
||||
if(!pmt_eqv(d_tx_chan, PMT_NIL)) {
|
||||
enter_receiving();
|
||||
enter_transmitting();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else { // RX allocation failed
|
||||
error_msg = "failed to allocate RX channel:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
goto unhandled;
|
||||
|
||||
case WRITE_REGISTER:
|
||||
goto unhandled;
|
||||
|
||||
case READ_REGISTER:
|
||||
goto unhandled;
|
||||
|
||||
//-------------------------- TRANSMITTING ----------------------------//
|
||||
// In the transmit state we count the number of underruns received and
|
||||
// ballpark the number with an expected count (something >1 for starters)
|
||||
case TRANSMITTING:
|
||||
|
||||
// Check that the transmits are OK
|
||||
if (pmt_eq(event, s_response_xmit_raw_frame)){
|
||||
handle = pmt_nth(0, data);
|
||||
status = pmt_nth(1, data);
|
||||
|
||||
if (pmt_eq(status, PMT_T)){
|
||||
handle_xmit_response(handle);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
error_msg = "bad response-xmit-raw-frame:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
goto unhandled;
|
||||
|
||||
//------------------------- CLOSING CHANNELS ----------------------------//
|
||||
// Check deallocation responses, once the TX and RX channels are both
|
||||
// deallocated then we close the USRP.
|
||||
case CLOSING_CHANNELS:
|
||||
|
||||
if (pmt_eq(event, s_response_deallocate_channel)
|
||||
&& pmt_eq(d_tx->port_symbol(), port_id))
|
||||
{
|
||||
status = pmt_nth(1, data);
|
||||
|
||||
// If successful, set the port to NIL
|
||||
if(pmt_eq(status, PMT_T)) {
|
||||
d_tx_chan = PMT_NIL;
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_UNDERRUN] Received TX deallocation\n";
|
||||
|
||||
// If the RX is also deallocated, we can close the USRP
|
||||
if(pmt_eq(d_rx_chan, PMT_NIL))
|
||||
closing_usrp();
|
||||
|
||||
return;
|
||||
|
||||
} else {
|
||||
|
||||
error_msg = "failed to deallocate TX channel:";
|
||||
goto bail;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (pmt_eq(event, s_response_deallocate_channel)
|
||||
&& pmt_eq(d_rx->port_symbol(), port_id))
|
||||
{
|
||||
status = pmt_nth(1, data);
|
||||
|
||||
// If successful, set the port to NIL
|
||||
if(pmt_eq(status, PMT_T)) {
|
||||
d_rx_chan = PMT_NIL;
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_UNDERRUN] Received RX deallocation\n";
|
||||
|
||||
// If the TX is also deallocated, we can close the USRP
|
||||
if(pmt_eq(d_tx_chan, PMT_NIL))
|
||||
closing_usrp();
|
||||
|
||||
return;
|
||||
|
||||
} else {
|
||||
|
||||
error_msg = "failed to deallocate RX channel:";
|
||||
goto bail;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
goto unhandled;
|
||||
|
||||
//--------------------------- CLOSING USRP ------------------------------//
|
||||
// Once we have received a successful USRP close response, we shutdown all
|
||||
// mblocks and exit.
|
||||
case CLOSING_USRP:
|
||||
|
||||
if (pmt_eq(event, s_response_close)) {
|
||||
|
||||
status = pmt_nth(1, data);
|
||||
|
||||
if(pmt_eq(status, PMT_T)) {
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_UNDERRUN] Successfully closed USRP\n";
|
||||
|
||||
std::cout << "\nUnderruns: " << d_n_underruns << std::endl;
|
||||
fflush(stdout);
|
||||
|
||||
shutdown_all(PMT_T);
|
||||
return;
|
||||
|
||||
} else {
|
||||
|
||||
error_msg = "failed to close USRP:";
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
goto unhandled;
|
||||
|
||||
case INIT:
|
||||
goto unhandled;
|
||||
|
||||
}
|
||||
|
||||
// An error occured, print it, and shutdown all m-blocks
|
||||
bail:
|
||||
std::cerr << error_msg << data
|
||||
<< "status = " << status << std::endl;
|
||||
shutdown_all(PMT_F);
|
||||
return;
|
||||
|
||||
// Received an unhandled message for a specific state
|
||||
unhandled:
|
||||
if(verbose && !pmt_eq(event, pmt_intern("%shutdown")))
|
||||
std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
|
||||
<< "in state "<< d_state << std::endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Sends a command to USRP server to open up a connection to the
|
||||
// specified USRP, which is defaulted to USRP 0 on the system
|
||||
void
|
||||
test_usrp_inband_underrun::opening_usrp()
|
||||
{
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_UNDERRUN] Opening USRP "
|
||||
<< d_which_usrp << std::endl;
|
||||
|
||||
d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, d_which_usrp));
|
||||
d_state = OPENING_USRP;
|
||||
}
|
||||
|
||||
// RX and TX channels must be allocated so that the USRP server can
|
||||
// properly share bandwidth across multiple USRPs. No commands will be
|
||||
// successful to the USRP through the USRP server on the TX or RX channels until
|
||||
// a bandwidth allocation has been received.
|
||||
void
|
||||
test_usrp_inband_underrun::allocating_channels()
|
||||
{
|
||||
d_state = ALLOCATING_CHANNELS;
|
||||
|
||||
long capacity = (long) 16e6;
|
||||
d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
|
||||
d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
|
||||
}
|
||||
|
||||
// After allocating the channels, a write register command will be sent to the
|
||||
// USRP.
|
||||
void
|
||||
test_usrp_inband_underrun::write_register()
|
||||
{
|
||||
d_state = WRITE_REGISTER;
|
||||
|
||||
long reg = 0;
|
||||
|
||||
d_tx->send(s_cmd_to_control_channel, // C/S packet
|
||||
pmt_list2(PMT_NIL, // invoc handle
|
||||
pmt_list1(
|
||||
pmt_list2(s_op_write_reg,
|
||||
pmt_list2(
|
||||
pmt_from_long(reg),
|
||||
pmt_from_long(0xbeef))))));
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_REGISTERS] Writing 0xbeef to "
|
||||
<< reg << std::endl;
|
||||
|
||||
read_register(); // immediately transition to read the register
|
||||
}
|
||||
|
||||
// Temporary: for testing pings
|
||||
void
|
||||
test_usrp_inband_underrun::build_and_send_ping()
|
||||
{
|
||||
|
||||
d_tx->send(s_cmd_to_control_channel,
|
||||
pmt_list2(PMT_NIL, pmt_list1(pmt_list2(s_op_ping_fixed,
|
||||
pmt_list2(pmt_from_long(0),
|
||||
pmt_from_long(0))))));
|
||||
|
||||
std::cout << "[TEST_USRP_INBAND_UNDERRUN] Ping sent" << std::endl;
|
||||
}
|
||||
|
||||
// After writing to the register, we want to read the value back and ensure that
|
||||
// it is the same value that we wrote.
|
||||
void
|
||||
test_usrp_inband_underrun::read_register()
|
||||
{
|
||||
d_state = READ_REGISTER;
|
||||
|
||||
long reg = 9;
|
||||
|
||||
d_tx->send(s_cmd_to_control_channel, // C/S packet
|
||||
pmt_list2(PMT_NIL, // invoc handle
|
||||
pmt_list1(
|
||||
pmt_list2(s_op_read_reg,
|
||||
pmt_list2(
|
||||
pmt_from_long(0), // rid
|
||||
pmt_from_long(reg))))));
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_UNDERRUN] Reading from register "
|
||||
<< reg << std::endl;
|
||||
}
|
||||
|
||||
// Used to enter the receiving state
|
||||
void
|
||||
test_usrp_inband_underrun::enter_receiving()
|
||||
{
|
||||
d_rx->send(s_cmd_start_recv_raw_samples,
|
||||
pmt_list2(PMT_F,
|
||||
d_rx_chan));
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_UNDERRUN] Started RX sample stream\n";
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_inband_underrun::enter_transmitting()
|
||||
{
|
||||
d_state = TRANSMITTING;
|
||||
d_nsamples_xmitted = 0;
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_UNDERRUN] Entering transmit state...\n";
|
||||
|
||||
build_and_send_next_frame(); // fire off 4 to start pipeline
|
||||
build_and_send_next_frame();
|
||||
build_and_send_next_frame();
|
||||
build_and_send_next_frame();
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_inband_underrun::build_and_send_next_frame()
|
||||
{
|
||||
|
||||
long nsamples_this_frame =
|
||||
std::min(d_nsamples_to_send - d_nsamples_xmitted,
|
||||
d_samples_per_frame);
|
||||
|
||||
if (nsamples_this_frame == 0){
|
||||
d_done_sending = true;
|
||||
return;
|
||||
}
|
||||
|
||||
size_t nshorts = 2 * nsamples_this_frame; // 16-bit I & Q
|
||||
pmt_t uvec = pmt_make_s16vector(nshorts, 0);
|
||||
size_t ignore;
|
||||
int16_t *samples = pmt_s16vector_writable_elements(uvec, ignore);
|
||||
|
||||
// fill in the complex sinusoid
|
||||
|
||||
for (int i = 0; i < nsamples_this_frame; i++){
|
||||
|
||||
if (1){
|
||||
gr_complex s;
|
||||
d_nco.sincos(&s, 1, d_amplitude);
|
||||
// write 16-bit i & q
|
||||
samples[2*i] = (int16_t) s.real();
|
||||
samples[2*i+1] = (int16_t) s.imag();
|
||||
}
|
||||
else {
|
||||
gr_complex s(d_amplitude, d_amplitude);
|
||||
|
||||
// write 16-bit i & q
|
||||
samples[2*i] = (int16_t) s.real();
|
||||
samples[2*i+1] = (int16_t) s.imag();
|
||||
}
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_TX] Transmitting frame...\n";
|
||||
|
||||
pmt_t timestamp = pmt_from_long(0xffffffff); // NOW
|
||||
d_tx->send(s_cmd_xmit_raw_frame,
|
||||
pmt_list4(pmt_from_long(d_nframes_xmitted), // invocation-handle
|
||||
d_tx_chan, // channel
|
||||
uvec, // the samples
|
||||
timestamp));
|
||||
|
||||
d_nsamples_xmitted += nsamples_this_frame;
|
||||
d_nframes_xmitted++;
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[TEST_USRP_INBAND_TX] Transmitted frame\n";
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_inband_underrun::handle_xmit_response(pmt_t handle)
|
||||
{
|
||||
if (d_done_sending &&
|
||||
pmt_to_long(handle) == (d_nframes_xmitted - 1)){
|
||||
// We're done sending and have received all responses
|
||||
closing_channels();
|
||||
return;
|
||||
}
|
||||
|
||||
build_and_send_next_frame();
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_inband_underrun::handle_recv_response(pmt_t dict)
|
||||
{
|
||||
if(!pmt_is_dict(dict)) {
|
||||
std::cout << "[TEST_USRP_INBAND_UNDERRUN] Recv samples dictionary is improper\n";
|
||||
return;
|
||||
}
|
||||
|
||||
// Read the TX interpolations
|
||||
if(pmt_t underrun = pmt_dict_ref(dict,
|
||||
pmt_intern("underrun"),
|
||||
PMT_NIL)) {
|
||||
if(pmt_eqv(underrun, PMT_T)) {
|
||||
d_n_underruns++;
|
||||
|
||||
if(verbose && 0)
|
||||
std::cout << "[TEST_USRP_INBAND_UNDERRUN] Underrun\n";
|
||||
}
|
||||
else {
|
||||
if(verbose && 0)
|
||||
std::cout << "[TEST_USRP_INBAND_UNDERRUN] No underrun\n" << underrun <<std::endl;
|
||||
}
|
||||
} else {
|
||||
|
||||
if(verbose && 0)
|
||||
std::cout << "[TEST_USRP_INBAND_UNDERRUN] No underrun\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_inband_underrun::closing_channels()
|
||||
{
|
||||
d_state = CLOSING_CHANNELS;
|
||||
|
||||
d_tx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_tx_chan));
|
||||
d_rx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_rx_chan));
|
||||
}
|
||||
|
||||
void
|
||||
test_usrp_inband_underrun::closing_usrp()
|
||||
{
|
||||
d_state = CLOSING_USRP;
|
||||
|
||||
d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
|
||||
}
|
||||
|
||||
REGISTER_MBLOCK_CLASS(test_usrp_inband_underrun);
|
|
@ -1,202 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Radio; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
#ifndef INCLUDED_UI_NCO_H
|
||||
#define INCLUDED_UI_NCO_H
|
||||
|
||||
|
||||
#include <vector>
|
||||
#include <ui_sincos.h>
|
||||
#include <cmath>
|
||||
|
||||
#include <complex>
|
||||
typedef std::complex<float> gr_complex;
|
||||
|
||||
|
||||
/*!
|
||||
* \brief base class template for Numerically Controlled Oscillator (NCO)
|
||||
*/
|
||||
|
||||
|
||||
//FIXME Eventually generalize this to fixed point
|
||||
|
||||
template<class o_type, class i_type>
|
||||
class ui_nco {
|
||||
public:
|
||||
ui_nco () : phase (0), phase_inc(0) {}
|
||||
|
||||
virtual ~ui_nco () {}
|
||||
|
||||
// radians
|
||||
void set_phase (double angle) {
|
||||
phase = angle;
|
||||
}
|
||||
|
||||
void adjust_phase (double delta_phase) {
|
||||
phase += delta_phase;
|
||||
}
|
||||
|
||||
|
||||
// angle_rate is in radians / step
|
||||
void set_freq (double angle_rate){
|
||||
phase_inc = angle_rate;
|
||||
}
|
||||
|
||||
// angle_rate is a delta in radians / step
|
||||
void adjust_freq (double delta_angle_rate)
|
||||
{
|
||||
phase_inc += delta_angle_rate;
|
||||
}
|
||||
|
||||
// increment current phase angle
|
||||
|
||||
void step ()
|
||||
{
|
||||
phase += phase_inc;
|
||||
if (fabs (phase) > M_PI){
|
||||
|
||||
while (phase > M_PI)
|
||||
phase -= 2*M_PI;
|
||||
|
||||
while (phase < -M_PI)
|
||||
phase += 2*M_PI;
|
||||
}
|
||||
}
|
||||
|
||||
void step (int n)
|
||||
{
|
||||
phase += phase_inc * n;
|
||||
if (fabs (phase) > M_PI){
|
||||
|
||||
while (phase > M_PI)
|
||||
phase -= 2*M_PI;
|
||||
|
||||
while (phase < -M_PI)
|
||||
phase += 2*M_PI;
|
||||
}
|
||||
}
|
||||
|
||||
// units are radians / step
|
||||
double get_phase () const { return phase; }
|
||||
double get_freq () const { return phase_inc; }
|
||||
|
||||
// compute sin and cos for current phase angle
|
||||
void sincos (float *sinx, float *cosx) const;
|
||||
|
||||
// compute cos or sin for current phase angle
|
||||
float cos () const { return std::cos (phase); }
|
||||
float sin () const { return std::sin (phase); }
|
||||
|
||||
// compute a block at a time
|
||||
void sin (float *output, int noutput_items, double ampl = 1.0);
|
||||
void cos (float *output, int noutput_items, double ampl = 1.0);
|
||||
void sincos (gr_complex *output, int noutput_items, double ampl = 1.0);
|
||||
void sin (short *output, int noutput_items, double ampl = 1.0);
|
||||
void cos (short *output, int noutput_items, double ampl = 1.0);
|
||||
void sin (int *output, int noutput_items, double ampl = 1.0);
|
||||
void cos (int *output, int noutput_items, double ampl = 1.0);
|
||||
|
||||
protected:
|
||||
double phase;
|
||||
double phase_inc;
|
||||
};
|
||||
|
||||
template<class o_type, class i_type>
|
||||
void
|
||||
ui_nco<o_type,i_type>::sincos (float *sinx, float *cosx) const
|
||||
{
|
||||
ui_sincosf (phase, sinx, cosx);
|
||||
}
|
||||
|
||||
template<class o_type, class i_type>
|
||||
void
|
||||
ui_nco<o_type,i_type>::sin (float *output, int noutput_items, double ampl)
|
||||
{
|
||||
for (int i = 0; i < noutput_items; i++){
|
||||
output[i] = (float)(sin () * ampl);
|
||||
step ();
|
||||
}
|
||||
}
|
||||
|
||||
template<class o_type, class i_type>
|
||||
void
|
||||
ui_nco<o_type,i_type>::cos (float *output, int noutput_items, double ampl)
|
||||
{
|
||||
for (int i = 0; i < noutput_items; i++){
|
||||
output[i] = (float)(cos () * ampl);
|
||||
step ();
|
||||
}
|
||||
}
|
||||
|
||||
template<class o_type, class i_type>
|
||||
void
|
||||
ui_nco<o_type,i_type>::sin (short *output, int noutput_items, double ampl)
|
||||
{
|
||||
for (int i = 0; i < noutput_items; i++){
|
||||
output[i] = (short)(sin() * ampl);
|
||||
step ();
|
||||
}
|
||||
}
|
||||
|
||||
template<class o_type, class i_type>
|
||||
void
|
||||
ui_nco<o_type,i_type>::cos (short *output, int noutput_items, double ampl)
|
||||
{
|
||||
for (int i = 0; i < noutput_items; i++){
|
||||
output[i] = (short)(cos () * ampl);
|
||||
step ();
|
||||
}
|
||||
}
|
||||
|
||||
template<class o_type, class i_type>
|
||||
void
|
||||
ui_nco<o_type,i_type>::sin (int *output, int noutput_items, double ampl)
|
||||
{
|
||||
for (int i = 0; i < noutput_items; i++){
|
||||
output[i] = (int)(sin () * ampl);
|
||||
step ();
|
||||
}
|
||||
}
|
||||
|
||||
template<class o_type, class i_type>
|
||||
void
|
||||
ui_nco<o_type,i_type>::cos (int *output, int noutput_items, double ampl)
|
||||
{
|
||||
for (int i = 0; i < noutput_items; i++){
|
||||
output[i] = (int)(cos () * ampl);
|
||||
step ();
|
||||
}
|
||||
}
|
||||
|
||||
template<class o_type, class i_type>
|
||||
void
|
||||
ui_nco<o_type,i_type>::sincos (gr_complex *output, int noutput_items, double ampl)
|
||||
{
|
||||
for (int i = 0; i < noutput_items; i++){
|
||||
float cosx, sinx;
|
||||
sincos (&sinx, &cosx);
|
||||
output[i] = gr_complex(cosx * ampl, sinx * ampl);
|
||||
step ();
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* INCLUDED_UI_NCO_H */
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2004 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Radio; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#define _GNU_SOURCE // ask for GNU extensions if available
|
||||
|
||||
#include "ui_sincos.h"
|
||||
#include <math.h>
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
#if defined (HAVE_SINCOS)
|
||||
|
||||
void
|
||||
ui_sincos (double x, double *sinx, double *cosx)
|
||||
{
|
||||
sincos (x, sinx, cosx);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void
|
||||
ui_sincos (double x, double *sinx, double *cosx)
|
||||
{
|
||||
*sinx = sin (x);
|
||||
*cosx = cos (x);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
#if defined (HAVE_SINCOSF)
|
||||
|
||||
void
|
||||
ui_sincosf (float x, float *sinx, float *cosx)
|
||||
{
|
||||
sincosf (x, sinx, cosx);
|
||||
}
|
||||
|
||||
#elif defined (HAVE_SINF) && defined (HAVE_COSF)
|
||||
|
||||
void
|
||||
ui_sincosf (float x, float *sinx, float *cosx)
|
||||
{
|
||||
*sinx = sinf (x);
|
||||
*cosx = cosf (x);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void
|
||||
ui_sincosf (float x, float *sinx, float *cosx)
|
||||
{
|
||||
*sinx = sin (x);
|
||||
*cosx = cos (x);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,39 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2002,2004 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Radio; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_UI_SINCOS_H
|
||||
#define INCLUDED_UI_SINCOS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// compute sine and cosine at the same time
|
||||
|
||||
void ui_sincos (double x, double *sin, double *cos);
|
||||
void ui_sincosf (float x, float *sin, float *cos);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* INCLUDED_UI_SINCOS_H */
|
|
@ -1,20 +0,0 @@
|
|||
/Makefile
|
||||
/Makefile.in
|
||||
/.la
|
||||
/.lo
|
||||
/.deps
|
||||
/.libs
|
||||
/*.la
|
||||
/*.lo
|
||||
/*.swp
|
||||
/*.dat
|
||||
/test_fusb
|
||||
/std_paths.h
|
||||
/usrp_dbid.py
|
||||
/usrp_dbid.h
|
||||
/usrp_dbid.cc
|
||||
/usrp_server_mbh.cc
|
||||
/test_inband
|
||||
/test_usrp_inband
|
||||
/test_usrp_tx
|
||||
/*_mbh.cc
|
|
@ -1,114 +0,0 @@
|
|||
#
|
||||
# Copyright 2007,2008 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of GNU Radio
|
||||
#
|
||||
# GNU Radio is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# GNU Radio is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
include $(top_srcdir)/Makefile.common
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
$(DEFINES) $(OMNITHREAD_INCLUDES) $(PMT_INCLUDES) $(MBLOCK_INCLUDES) \
|
||||
$(USRP_INCLUDES) $(BOOST_CPPFLAGS) $(CPPUNIT_INCLUDES) \
|
||||
-I$(srcdir)/../../apps-inband $(WITH_INCLUDES)
|
||||
|
||||
TESTS = test_inband
|
||||
|
||||
EXTRA_DIST = \
|
||||
usrp_server.mbh \
|
||||
usrp_interface.mbh
|
||||
|
||||
lib_LTLIBRARIES = \
|
||||
libusrp-inband.la \
|
||||
libusrp-inband-qa.la
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
# Build the inband library
|
||||
|
||||
BUILT_SOURCES = \
|
||||
usrp_server_mbh.cc \
|
||||
usrp_interface_mbh.cc
|
||||
|
||||
usrp_server_mbh.cc : usrp_server.mbh
|
||||
$(COMPILE_MBH) $(srcdir)/usrp_server.mbh usrp_server_mbh.cc
|
||||
|
||||
usrp_interface_mbh.cc : usrp_interface.mbh
|
||||
$(COMPILE_MBH) $(srcdir)/usrp_interface.mbh usrp_interface_mbh.cc
|
||||
|
||||
libusrp_inband_la_SOURCES = \
|
||||
$(BUILT_SOURCES) \
|
||||
$(srcdir)/../../apps-inband/ui_sincos.c \
|
||||
usrp_inband_usb_packet.cc \
|
||||
usrp_rx.cc \
|
||||
usrp_rx_stub.cc \
|
||||
usrp_server.cc \
|
||||
usrp_tx.cc \
|
||||
usrp_tx_stub.cc \
|
||||
usrp_usb_interface.cc
|
||||
|
||||
libusrp_inband_la_LDFLAGS = $(NO_UNDEFINED) -version-info 0:0:0
|
||||
|
||||
libusrp_inband_la_LIBADD = \
|
||||
$(MBLOCK_LA) \
|
||||
$(USRP_LA) \
|
||||
-lstdc++
|
||||
|
||||
include_HEADERS = \
|
||||
usrp_inband_usb_packet.h \
|
||||
usrp_rx.h \
|
||||
usrp_rx_stub.h \
|
||||
usrp_server.h \
|
||||
usrp_tx.h \
|
||||
usrp_tx_stub.h \
|
||||
usrp_usb_interface.h
|
||||
|
||||
noinst_HEADERS = \
|
||||
qa_inband.h \
|
||||
qa_inband_packet_prims.h \
|
||||
qa_inband_usrp_server.h \
|
||||
symbols_usrp_channel.h \
|
||||
symbols_usrp_interface_cs.h \
|
||||
symbols_usrp_low_level_cs.h \
|
||||
symbols_usrp_rx.h \
|
||||
symbols_usrp_rx_cs.h \
|
||||
symbols_usrp_server_cs.h \
|
||||
symbols_usrp_tx.h \
|
||||
symbols_usrp_tx_cs.h
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
# Build the qa code in its own library
|
||||
|
||||
libusrp_inband_qa_la_SOURCES = \
|
||||
qa_inband.cc \
|
||||
qa_inband_packet_prims.cc \
|
||||
qa_inband_usrp_server.cc
|
||||
|
||||
# magic flags
|
||||
libusrp_inband_qa_la_LDFLAGS = $(NO_UNDEFINED) -avoid-version
|
||||
|
||||
libusrp_inband_qa_la_LIBADD = \
|
||||
libusrp-inband.la \
|
||||
$(PMT_LA) \
|
||||
$(CPPUNIT_LIBS) \
|
||||
-lstdc++
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
|
||||
noinst_PROGRAMS = \
|
||||
test_inband
|
||||
|
||||
test_inband_SOURCES = test_inband.cc
|
||||
test_inband_LDADD = libusrp-inband-qa.la
|
|
@ -1,65 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2007 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of GNU Radio
|
||||
#
|
||||
# GNU Radio is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# GNU Radio is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
import sys
|
||||
import struct
|
||||
from optparse import OptionParser
|
||||
|
||||
from usb_packet import *
|
||||
|
||||
def dump_packet(raw_pkt, outfile, dump_payload):
|
||||
pkt = usb_packet(raw_pkt)
|
||||
outfile.write(pkt.decoded_flags())
|
||||
outfile.write(' chan= %2d len= %3d timestamp= 0x%08x rssi= % 2d tag= %2d\n' % (
|
||||
pkt.chan(), pkt.payload_len(), pkt.timestamp(), pkt.rssi(), pkt.tag()))
|
||||
if dump_payload:
|
||||
assert pkt.payload_len() % 4 == 0
|
||||
shorts = struct.unpack('<%dh' % (pkt.payload_len() // 2), pkt.payload())
|
||||
for i in range(0, len(shorts), 2):
|
||||
outfile.write(' %6d, %6d\n' % (shorts[i], shorts[i+1]))
|
||||
|
||||
|
||||
def dump_packets(infile, outfile, dump_payload):
|
||||
raw_pkt = infile.read(512)
|
||||
while raw_pkt:
|
||||
if len(raw_pkt) != 512:
|
||||
sys.stderr.write("File length is not a multiple of 512 bytes")
|
||||
raise SystemExit, 1
|
||||
|
||||
dump_packet(raw_pkt, outfile, dump_payload)
|
||||
raw_pkt = infile.read(512)
|
||||
|
||||
|
||||
def main():
|
||||
parser = OptionParser()
|
||||
parser.add_option('-p', '--dump-payload', action='store_true', default=False,
|
||||
help='dump payload in decimal and hex')
|
||||
|
||||
(options, files) = parser.parse_args()
|
||||
if len(files) == 0:
|
||||
dump_packets(sys.stdin, sys.stdout, options.dump_payload)
|
||||
else:
|
||||
for f in files:
|
||||
dump_packets(open(f, "r"), sys.stdout, options.dump_payload)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1,88 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import random
|
||||
import struct
|
||||
from pprint import pprint
|
||||
from usb_packet import *
|
||||
|
||||
MAX_PAYLOAD = 504
|
||||
TIME_NOW = 0xffffffff
|
||||
|
||||
|
||||
class sequence_generator(object):
|
||||
def __init__(self):
|
||||
self.i = 0
|
||||
|
||||
def __call__(self):
|
||||
t = self.i
|
||||
self.i += 1
|
||||
return t
|
||||
|
||||
def gen_shuffled_lengths():
|
||||
valid_lengths = range(0, MAX_PAYLOAD+1, 4) # [0, 4, 8, ... 504]
|
||||
random.shuffle(valid_lengths)
|
||||
return valid_lengths
|
||||
|
||||
|
||||
class packet_sequence_generator(object):
|
||||
def __init__(self, channel, lengths):
|
||||
self.next = sequence_generator()
|
||||
self.channel = channel
|
||||
self.lengths = lengths
|
||||
|
||||
def __call__(self, output_file):
|
||||
gen_packet(output_file, self.channel, self.next, self.lengths[0])
|
||||
del self.lengths[0]
|
||||
|
||||
|
||||
def gen_packet(output_file, channel, content_generator, payload_len):
|
||||
assert (payload_len % 4) == 0
|
||||
payload = []
|
||||
n_iq = payload_len // 4
|
||||
for n in range(n_iq):
|
||||
payload.append(content_generator()) # I
|
||||
payload.append(content_generator()) # Q
|
||||
for n in range(MAX_PAYLOAD // 4 - n_iq):
|
||||
payload.append(0x0000)
|
||||
payload.append(0xffff)
|
||||
|
||||
assert (len(payload) == MAX_PAYLOAD // 2)
|
||||
|
||||
#print "\npayload_len =", payload_len
|
||||
#pprint(payload)
|
||||
|
||||
output_file.write(make_header(FL_START_OF_BURST|FL_END_OF_BURST,
|
||||
channel, payload_len, TIME_NOW))
|
||||
output_file.write(struct.pack('<252h', *payload))
|
||||
|
||||
|
||||
def gen_all_valid_packet_lengths_1_channel(output_file):
|
||||
lengths = gen_shuffled_lengths()
|
||||
npkts = len(lengths) # number of packets we'll generator on each stream
|
||||
pkt_gen_0 = packet_sequence_generator(0, lengths)
|
||||
for i in range(npkts):
|
||||
pkt_gen_0(output_file)
|
||||
|
||||
assert pkt_gen_0.next() == 16002 # 2*sum(1, 2, ..., 126) == 126 * 127
|
||||
|
||||
|
||||
def gen_all_valid_packet_lengths_2_channels(output_file):
|
||||
lengths = gen_shuffled_lengths()
|
||||
npkts = len(lengths) # number of packets we'll generator on each stream
|
||||
pkt_gen_0 = packet_sequence_generator(0, lengths)
|
||||
pkt_gen_1 = packet_sequence_generator(0x1f, gen_shuffled_lengths())
|
||||
pkt_gen = (pkt_gen_0, pkt_gen_1)
|
||||
|
||||
which_gen = (npkts * [0]) + (npkts * [1])
|
||||
random.shuffle(which_gen)
|
||||
|
||||
for i in which_gen:
|
||||
pkt_gen[i](output_file)
|
||||
|
||||
assert pkt_gen_0.next() == 16002 # 2*sum(1, 2, ..., 126) == 126 * 127
|
||||
assert pkt_gen_1.next() == 16002 # 2*sum(1, 2, ..., 126) == 126 * 127
|
||||
|
||||
if __name__ == '__main__':
|
||||
random.seed(0)
|
||||
gen_all_valid_packet_lengths_1_channel(open("all_valid_packet_lengths_1_channel.dat", "w"))
|
||||
gen_all_valid_packet_lengths_2_channels(open("all_valid_packet_lengths_2_channels.dat", "w"))
|
|
@ -1,35 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <qa_inband.h>
|
||||
#include <qa_inband_packet_prims.h>
|
||||
#include <qa_inband_usrp_server.h>
|
||||
|
||||
CppUnit::TestSuite *
|
||||
qa_inband::suite()
|
||||
{
|
||||
CppUnit::TestSuite *s = new CppUnit::TestSuite("inband");
|
||||
|
||||
s->addTest (qa_inband_packet_prims::suite());
|
||||
s->addTest (qa_inband_usrp_server::suite());
|
||||
|
||||
return s;
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_QA_INBAND_H
|
||||
#define INCLUDED_QA_INBAND_H
|
||||
|
||||
#include <cppunit/TestSuite.h>
|
||||
|
||||
//! collect all the tests for the user server
|
||||
|
||||
class qa_inband {
|
||||
public:
|
||||
//! return suite of tests for all of usrp server
|
||||
static CppUnit::TestSuite *suite();
|
||||
};
|
||||
|
||||
#endif /* INCLUDED_QA_INBAND_H */
|
|
@ -1,162 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <qa_inband_packet_prims.h>
|
||||
#include <cppunit/TestAssert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <usrp_inband_usb_packet.h> // will change on gigabit crossover
|
||||
|
||||
typedef usrp_inband_usb_packet transport_pkt;
|
||||
|
||||
void
|
||||
qa_inband_packet_prims::test_flags()
|
||||
{
|
||||
transport_pkt pkt;
|
||||
|
||||
// Test each one of the flags while ensuring no other fields become set in the process
|
||||
pkt.set_header(pkt.FL_START_OF_BURST,0,0,0);
|
||||
CPPUNIT_ASSERT_EQUAL(1, pkt.start_of_burst());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.end_of_burst());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.overrun());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.underrun());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.dropped());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
|
||||
|
||||
pkt.set_header(pkt.FL_END_OF_BURST,0,0,0);
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.start_of_burst());
|
||||
CPPUNIT_ASSERT_EQUAL(1, pkt.end_of_burst());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.overrun());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.underrun());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.dropped());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
|
||||
|
||||
pkt.set_header(pkt.FL_OVERRUN,0,0,0);
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.start_of_burst());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.end_of_burst());
|
||||
CPPUNIT_ASSERT_EQUAL(1, pkt.overrun());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.underrun());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.dropped());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
|
||||
|
||||
pkt.set_header(pkt.FL_UNDERRUN,0,0,0);
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.start_of_burst());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.end_of_burst());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.overrun());
|
||||
CPPUNIT_ASSERT_EQUAL(1, pkt.underrun());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.dropped());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
|
||||
|
||||
pkt.set_header(pkt.FL_DROPPED,0,0,0);
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.start_of_burst());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.end_of_burst());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.overrun());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.underrun());
|
||||
CPPUNIT_ASSERT_EQUAL(1, pkt.dropped());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
|
||||
|
||||
// test of all fields set
|
||||
pkt.set_header(
|
||||
pkt.FL_START_OF_BURST |
|
||||
pkt.FL_END_OF_BURST |
|
||||
pkt.FL_UNDERRUN |
|
||||
pkt.FL_OVERRUN |
|
||||
pkt.FL_DROPPED
|
||||
,0,0,0);
|
||||
CPPUNIT_ASSERT_EQUAL(1, pkt.start_of_burst());
|
||||
CPPUNIT_ASSERT_EQUAL(1, pkt.end_of_burst());
|
||||
CPPUNIT_ASSERT_EQUAL(1, pkt.overrun());
|
||||
CPPUNIT_ASSERT_EQUAL(1, pkt.underrun());
|
||||
CPPUNIT_ASSERT_EQUAL(1, pkt.dropped());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
|
||||
|
||||
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
qa_inband_packet_prims::test_fields()
|
||||
{
|
||||
transport_pkt pkt;
|
||||
void * payload;
|
||||
|
||||
// test word0 field exclusiveness
|
||||
//
|
||||
// I want to test max values of each field to ensure field boundaries
|
||||
// but these max values could change based on technology? The
|
||||
// max payload is returned by a private method so the code is not
|
||||
// technology dependent
|
||||
pkt.set_header(0,16,0,0);
|
||||
CPPUNIT_ASSERT_EQUAL(16, pkt.chan());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
|
||||
|
||||
pkt.set_header(0,0,8,0);
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
|
||||
CPPUNIT_ASSERT_EQUAL(8, pkt.tag());
|
||||
CPPUNIT_ASSERT_EQUAL(0,pkt.payload_len());
|
||||
|
||||
pkt.set_header(0,0,0,pkt.max_payload());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
|
||||
CPPUNIT_ASSERT_EQUAL(pkt.max_payload(), pkt.payload_len());
|
||||
|
||||
// test timestamp, shouldn't have to test other fields since
|
||||
// setting the timestamp only has the ability to affect one word
|
||||
pkt.set_timestamp(54);
|
||||
CPPUNIT_ASSERT_EQUAL(uint32_t(54), pkt.timestamp());
|
||||
|
||||
// test the payload, ensure no other fields overwritten
|
||||
//
|
||||
// is there a better test for this?
|
||||
pkt.set_header(0,0,0,0);
|
||||
payload = malloc(pkt.payload_len());
|
||||
memset(payload, 'f', pkt.payload_len());
|
||||
memcpy(pkt.payload(), payload, pkt.payload_len());
|
||||
CPPUNIT_ASSERT_EQUAL(0, memcmp(pkt.payload(), payload, pkt.payload_len()));
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.start_of_burst());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.end_of_burst());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.overrun());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.underrun());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.dropped());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
|
||||
free(payload);
|
||||
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
|
@ -1,41 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef QA_INBAND_PACKET_PRIMS_H
|
||||
#define QA_INBAND_PACKET_PRIMS_H
|
||||
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
#include <cppunit/TestCase.h>
|
||||
|
||||
class qa_inband_packet_prims : public CppUnit::TestCase {
|
||||
|
||||
CPPUNIT_TEST_SUITE(qa_inband_packet_prims);
|
||||
CPPUNIT_TEST(test_flags);
|
||||
CPPUNIT_TEST(test_fields);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
private:
|
||||
void test_flags();
|
||||
void test_fields();
|
||||
|
||||
};
|
||||
|
||||
#endif /* INCLUDED_QA_INBAND_PACKET_PRIMS_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -1,50 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef QA_INBAND_USRP_SERVER_H
|
||||
#define QA_INBAND_USRP_SERVER_H
|
||||
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
#include <cppunit/TestCase.h>
|
||||
|
||||
class qa_inband_usrp_server : public CppUnit::TestCase {
|
||||
|
||||
CPPUNIT_TEST_SUITE(qa_inband_usrp_server);
|
||||
CPPUNIT_TEST(test_open_close);
|
||||
CPPUNIT_TEST(test_chan_allocation);
|
||||
CPPUNIT_TEST(test_chan_deallocation);
|
||||
CPPUNIT_TEST(test_tx);
|
||||
CPPUNIT_TEST(test_rx);
|
||||
CPPUNIT_TEST(test_cs);
|
||||
CPPUNIT_TEST(test_rid);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
private:
|
||||
void test_chan_allocation();
|
||||
void test_chan_deallocation();
|
||||
void test_open_close();
|
||||
void test_tx();
|
||||
void test_rx();
|
||||
void test_cs();
|
||||
void test_rid();
|
||||
};
|
||||
|
||||
#endif /* INCLUDED_QA_INBAND_USRP_SERVER_H */
|
|
@ -1,40 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#ifndef INCLUDED_SYMBOLS_USRP_CHANNEL_H
|
||||
#define INCLUDED_SYMBOLS_USRP_CHANNEL_H
|
||||
|
||||
#include <pmt.h>
|
||||
|
||||
// Outgoing
|
||||
static pmt_t s_cmd_allocate_channel = pmt_intern("cmd-allocate-channel");
|
||||
static pmt_t s_cmd_deallocate_channel = pmt_intern("cmd-deallocate-channel");
|
||||
|
||||
// Incoming
|
||||
static pmt_t s_response_allocate_channel = pmt_intern("response-allocate-channel");
|
||||
static pmt_t s_response_deallocate_channel = pmt_intern("response-deallocate-channel");
|
||||
|
||||
// Errors
|
||||
static pmt_t s_err_requested_capacity_unavailable = pmt_intern("err-requested-capacity-unavailable");
|
||||
static pmt_t s_err_channel_unavailable = pmt_intern("err-channel-unavailable");
|
||||
static pmt_t s_err_channel_invalid = pmt_intern("err-channel-invalid");
|
||||
static pmt_t s_err_channel_permission_denied = pmt_intern("err-channel-permission-denied");
|
||||
|
||||
#endif /* INCLUDED_SYMBOLS_USRP_CHANNEL_H */
|
|
@ -1,43 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#ifndef INCLUDED_SYMBOLS_USRP_INTERFACE_CS_H
|
||||
#define INCLUDED_SYMBOLS_USRP_INTERFACE_CS_H
|
||||
|
||||
#include <pmt.h>
|
||||
|
||||
// Outgoing
|
||||
static pmt_t s_cmd_usrp_open = pmt_intern("cmd-usrp-open");
|
||||
static pmt_t s_cmd_usrp_close = pmt_intern("cmd-usrp-close");
|
||||
static pmt_t s_cmd_usrp_ntx_chan = pmt_intern("cmd-usrp-ntx-chan");
|
||||
static pmt_t s_cmd_usrp_nrx_chan = pmt_intern("cmd-usrp-nrx-chan");
|
||||
static pmt_t s_cmd_usrp_write = pmt_intern("cmd-usrp-write");
|
||||
static pmt_t s_cmd_usrp_start_reading = pmt_intern("cmd-usrp-start-reading");
|
||||
static pmt_t s_cmd_usrp_stop_reading = pmt_intern("cmd-usrp-stop-reading");
|
||||
|
||||
// Incoming
|
||||
static pmt_t s_response_usrp_open = pmt_intern("response-usrp-open");
|
||||
static pmt_t s_response_usrp_close = pmt_intern("response-usrp-close");
|
||||
static pmt_t s_response_usrp_ntx_chan = pmt_intern("response-usrp-ntx-chan");
|
||||
static pmt_t s_response_usrp_nrx_chan = pmt_intern("response-usrp-nrx-chan");
|
||||
static pmt_t s_response_usrp_write = pmt_intern("response-usrp-write");
|
||||
static pmt_t s_response_usrp_read = pmt_intern("response-usrp-read");
|
||||
|
||||
#endif /* INCLUDED_SYMBOLS_USRP_INTERFACE_CS_H */
|
|
@ -1,47 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#ifndef INCLUDED_SYMBOLS_USRP_LOW_LEVEL_CS_H
|
||||
#define INCLUDED_SYMBOLS_USRP_LOW_LEVEL_CS_H
|
||||
|
||||
#include <pmt.h>
|
||||
|
||||
// Outgoing
|
||||
static pmt_t s_cmd_to_control_channel = pmt_intern("cmd-to-control-channel");
|
||||
|
||||
// Incoming
|
||||
static pmt_t s_response_from_control_channel = pmt_intern("response-from-control-channel");
|
||||
|
||||
// Subpackets
|
||||
static pmt_t s_op_ping_fixed = pmt_intern("op-ping-fixed");
|
||||
static pmt_t s_op_ping_fixed_reply = pmt_intern("op-ping-fixed-reply");
|
||||
static pmt_t s_op_write_reg = pmt_intern("op-write-reg");
|
||||
static pmt_t s_op_write_reg_masked = pmt_intern("op-write-reg-masked");
|
||||
static pmt_t s_op_read_reg = pmt_intern("op-read-reg");
|
||||
static pmt_t s_op_read_reg_reply = pmt_intern("op-read-reg-reply");
|
||||
static pmt_t s_op_i2c_write = pmt_intern("op-i2c-write");
|
||||
static pmt_t s_op_i2c_read = pmt_intern("op-i2c-read");
|
||||
static pmt_t s_op_i2c_read_reply = pmt_intern("op-i2c-read-reply");
|
||||
static pmt_t s_op_spi_write = pmt_intern("op-spi-write");
|
||||
static pmt_t s_op_spi_read = pmt_intern("op-spi-read");
|
||||
static pmt_t s_op_spi_read_reply = pmt_intern("op-spi-read-reply");
|
||||
static pmt_t s_op_delay = pmt_intern("op-delay");
|
||||
|
||||
#endif /* INCLUDED_SYMBOLS_USRP_LOW_LEVEL_CS_H */
|
|
@ -1,36 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#ifndef INCLUDED_SYMBOLS_USRP_RX_H
|
||||
#define INCLUDED_SYMBOLS_USRP_RX_H
|
||||
|
||||
#include <pmt.h>
|
||||
|
||||
// Outgoing
|
||||
static pmt_t s_cmd_start_recv_raw_samples = pmt_intern("cmd-start-recv-raw-samples");
|
||||
static pmt_t s_cmd_stop_recv_raw_samples = pmt_intern("cmd-stop-recv-raw-samples");
|
||||
|
||||
// Incoming
|
||||
static pmt_t s_response_recv_raw_samples = pmt_intern("response-recv-raw-samples");
|
||||
|
||||
// Errors
|
||||
static pmt_t s_err_already_receiving = pmt_intern("err-already-receiving");
|
||||
|
||||
#endif /* INCLUDED_SYMBOLS_USRP_RX_H */
|
|
@ -1,32 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#ifndef INCLUDED_SYMBOLS_USRP_RX_CS_H
|
||||
#define INCLUDED_SYMBOLS_USRP_RX_CS_H
|
||||
|
||||
#include <pmt.h>
|
||||
|
||||
// Outgoing
|
||||
static pmt_t s_cmd_usrp_rx_start_reading = pmt_intern("cmd-usrp-rx-start-reading");
|
||||
|
||||
// Incoming
|
||||
static pmt_t s_response_usrp_rx_read = pmt_intern("response-usrp-rx-read");
|
||||
|
||||
#endif /* INCLUDED_SYMBOLS_USRP_RX_CS_H */
|
|
@ -1,47 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#ifndef INCLUDED_SYMBOLS_USRP_SERVER_CS_H
|
||||
#define INCLUDED_SYMBOLS_USRP_SERVER_CS_H
|
||||
|
||||
#include <pmt.h>
|
||||
|
||||
// Outgoing
|
||||
static pmt_t s_cmd_open = pmt_intern("cmd-open");
|
||||
static pmt_t s_cmd_close = pmt_intern("cmd-close");
|
||||
static pmt_t s_cmd_max_capacity = pmt_intern("cmd-max-capacity");
|
||||
static pmt_t s_cmd_ntx_chan = pmt_intern("cmd-ntx-chan");
|
||||
static pmt_t s_cmd_nrx_chan = pmt_intern("cmd-nrx-chan");
|
||||
static pmt_t s_cmd_current_capacity_allocation = pmt_intern("cmd-current-capacity-allocation");
|
||||
|
||||
// Incoming
|
||||
static pmt_t s_response_open = pmt_intern("response-open");
|
||||
static pmt_t s_response_close = pmt_intern("response-close");
|
||||
static pmt_t s_response_max_capacity = pmt_intern("response-max-capacity");
|
||||
static pmt_t s_response_ntx_chan = pmt_intern("response-ntx-chan");
|
||||
static pmt_t s_response_nrx_chan = pmt_intern("response-nrx-chan");
|
||||
static pmt_t s_response_current_capacity_allocation = pmt_intern("response-current-capacity-allocation");
|
||||
|
||||
// Errors
|
||||
static pmt_t s_err_usrp_not_opened = pmt_intern("err-usrp-not-opened");
|
||||
static pmt_t s_err_usrp_already_opened = pmt_intern("err-usrp-already-opened");
|
||||
static pmt_t s_err_usrp_already_closed = pmt_intern("err-usrp-already-closed");
|
||||
|
||||
#endif /* INCLUDED_SYMBOLS_USRP_SERVER_CS_H */
|
|
@ -1,32 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#ifndef INCLUDED_SYMBOLS_USRP_TX_H
|
||||
#define INCLUDED_SYMBOLS_USRP_TX_H
|
||||
|
||||
#include <pmt.h>
|
||||
|
||||
// Outgoing
|
||||
static pmt_t s_cmd_xmit_raw_frame = pmt_intern("cmd-xmit-raw-frame");
|
||||
|
||||
// Incoming
|
||||
static pmt_t s_response_xmit_raw_frame = pmt_intern("response-xmit-raw-frame");
|
||||
|
||||
#endif /* INCLUDED_SYMBOLS_USRP_TX_H */
|
|
@ -1,32 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#ifndef INCLUDED_SYMBOLS_USRP_TX_CS_H
|
||||
#define INCLUDED_SYMBOLS_USRP_TX_CS_H
|
||||
|
||||
#include <pmt.h>
|
||||
|
||||
// Outgoing
|
||||
static pmt_t s_cmd_usrp_tx_write = pmt_intern("cmd-usrp-tx-write");
|
||||
|
||||
// Incoming
|
||||
static pmt_t s_response_usrp_tx_write = pmt_intern("response-usrp-tx-write");
|
||||
|
||||
#endif /* INCLUDED_SYMBOLS_USRP_TX_CS_H */
|
|
@ -1,36 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <cppunit/TextTestRunner.h>
|
||||
#include <qa_inband.h>
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
|
||||
CppUnit::TextTestRunner runner;
|
||||
|
||||
runner.addTest(qa_inband::suite ());
|
||||
|
||||
bool was_successful = runner.run("", false);
|
||||
|
||||
return was_successful ? 0 : 1;
|
||||
}
|
|
@ -1,115 +0,0 @@
|
|||
#
|
||||
# Copyright 2007 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of GNU Radio
|
||||
#
|
||||
# GNU Radio is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# GNU Radio is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
import struct
|
||||
|
||||
|
||||
FL_OVERRUN = 0x80000000
|
||||
FL_UNDERRUN = 0x40000000
|
||||
FL_DROPPED = 0x20000000
|
||||
FL_END_OF_BURST = 0x10000000
|
||||
FL_START_OF_BURST = 0x08000000
|
||||
|
||||
FL_ALL_FLAGS = 0xf8000000
|
||||
|
||||
FL_OVERRUN_SHIFT = 31
|
||||
FL_UNDERRUN_SHIFT = 30
|
||||
FL_DROPPED_SHIFT = 29
|
||||
FL_END_OF_BURST_SHIFT = 28
|
||||
FL_START_OF_BURST_SHIFT = 27
|
||||
|
||||
RSSI_MASK = 0x3f
|
||||
RSSI_SHIFT = 21
|
||||
|
||||
CHAN_MASK = 0x1f
|
||||
CHAN_SHIFT = 16
|
||||
|
||||
TAG_MASK = 0xf
|
||||
TAG_SHIFT = 9
|
||||
|
||||
PAYLOAD_LEN_MASK = 0x1ff
|
||||
PAYLOAD_LEN_SHIFT = 0
|
||||
|
||||
def make_header(flags, chan, payload_len, timestamp, rssi=0, tag=0):
|
||||
word0 = ((flags & FL_ALL_FLAGS)
|
||||
| ((rssi & RSSI_MASK) << RSSI_SHIFT)
|
||||
| ((chan & CHAN_MASK) << CHAN_SHIFT)
|
||||
| ((tag & TAG_MASK) << TAG_SHIFT)
|
||||
| ((payload_len & PAYLOAD_LEN_MASK) << PAYLOAD_LEN_SHIFT))
|
||||
word1 = timestamp
|
||||
return struct.pack('<2I', word0, word1)
|
||||
|
||||
|
||||
def _decode(pred, indicator):
|
||||
if pred:
|
||||
return indicator
|
||||
else:
|
||||
return '-'
|
||||
|
||||
|
||||
class usb_packet(object):
|
||||
def __init__(self, raw_pkt):
|
||||
assert isinstance(raw_pkt, str) and len(raw_pkt) == 512
|
||||
self._raw_pkt = raw_pkt;
|
||||
(self._word0, self._word1) = struct.unpack('<2I', self._raw_pkt[0:8])
|
||||
|
||||
def timestamp(self):
|
||||
return self._word1
|
||||
|
||||
def rssi(self):
|
||||
return (self._word0 >> RSSI_SHIFT) & RSSI_MASK
|
||||
|
||||
def chan(self):
|
||||
return (self._word0 >> CHAN_SHIFT) & CHAN_MASK
|
||||
|
||||
def tag(self):
|
||||
return (self._word0 >> TAG_SHIFT) & TAG_MASK
|
||||
|
||||
def payload_len(self):
|
||||
return (self._word0 >> PAYLOAD_LEN_SHIFT) & PAYLOAD_LEN_MASK
|
||||
|
||||
def flags(self):
|
||||
return self._word0 & FL_ALL_FLAGS
|
||||
|
||||
def overrun(self):
|
||||
return (self._word0 >> FL_OVERRUN_SHIFT) & 0x1
|
||||
|
||||
def underrun(self):
|
||||
return (self._word0 >> FL_UNDERRUN_SHIFT) & 0x1
|
||||
|
||||
def start_of_burst(self):
|
||||
return (self._word0 >> FL_START_OF_BURST_SHIFT) & 0x1
|
||||
|
||||
def end_of_burst(self):
|
||||
return (self._word0 >> FL_END_OF_BURST_SHIFT) & 0x1
|
||||
|
||||
def dropped(self):
|
||||
return (self._word0 >> FL_DROPPED_SHIFT) & 0x1
|
||||
|
||||
def payload(self):
|
||||
return self._raw_pkt[8:8+self.payload_len()]
|
||||
|
||||
def decoded_flags(self):
|
||||
s = (_decode(self.overrun(), 'O')
|
||||
+ _decode(self.underrun(), 'U')
|
||||
+ _decode(self.dropped(), 'D')
|
||||
+ _decode(self.end_of_burst(), 'E')
|
||||
+ _decode(self.start_of_burst(), 'S'))
|
||||
return s
|
|
@ -1,793 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <usrp_inband_usb_packet.h>
|
||||
|
||||
#include <usrp_bytesex.h>
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/*!
|
||||
* \brief Aligns the packet payload on a 32 bit boundary. This is essential to
|
||||
* all control/status packets so that the inband FPGA code can parse them
|
||||
* easily.
|
||||
*
|
||||
* \returns true if successful or if the packet was already aligned; false if it
|
||||
* cannot be aligned.
|
||||
*/
|
||||
bool usrp_inband_usb_packet::align32()
|
||||
{
|
||||
int p_len = payload_len();
|
||||
|
||||
int bytes_needed = 4 - (p_len % 4);
|
||||
|
||||
if(bytes_needed == 4)
|
||||
return true;
|
||||
|
||||
// If the room left in the packet is less than the number of bytes
|
||||
// needed, return false to indicate no room to align
|
||||
if((MAX_PAYLOAD - p_len) < bytes_needed)
|
||||
return false;
|
||||
|
||||
incr_header_len(bytes_needed);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds a ping command to the current control packet.
|
||||
*
|
||||
* The \p rid is the rid to be associated with the ping response and \p ping_val
|
||||
* is currently unused.
|
||||
*
|
||||
* \returns true if adding the ping command was successful, false otherwise
|
||||
* (i.e. no space in the current packet).
|
||||
*/
|
||||
bool usrp_inband_usb_packet::cs_ping(long rid, long ping_val)
|
||||
{
|
||||
if(!align32())
|
||||
return false;
|
||||
|
||||
int p_len = payload_len();
|
||||
|
||||
if((MAX_PAYLOAD - p_len) < (CS_PING_LEN + CS_FIXED_LEN))
|
||||
return false;
|
||||
|
||||
uint32_t ping = (
|
||||
((OP_PING_FIXED & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
|
||||
| ((CS_PING_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
|
||||
| ((rid & CS_RID_MASK) << CS_RID_SHIFT)
|
||||
| (ping_val & CS_PINGVAL_MASK)
|
||||
|
||||
);
|
||||
|
||||
uint32_t *payload = (uint32_t *) (d_payload + p_len);
|
||||
*payload = host_to_usrp_u32(ping);
|
||||
|
||||
// Update payload length
|
||||
incr_header_len(CS_FIXED_LEN + CS_PING_LEN);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds a ping response to the packet. This is used by the fake USRP
|
||||
* code to generate fake responses for pings.
|
||||
*
|
||||
* The \p rid is the RID to be associated with the response and \p ping_val is
|
||||
* currently unused.
|
||||
*
|
||||
* \returns true if the ping reply was added successfully, false otherwise.
|
||||
*/
|
||||
bool usrp_inband_usb_packet::cs_ping_reply(long rid, long ping_val)
|
||||
{
|
||||
if(!align32())
|
||||
return false;
|
||||
|
||||
int p_len = payload_len();
|
||||
|
||||
if((MAX_PAYLOAD - p_len) < (CS_PING_LEN + CS_FIXED_LEN))
|
||||
return false;
|
||||
|
||||
uint32_t ping = (
|
||||
((OP_PING_FIXED_REPLY & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
|
||||
| ((CS_PING_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
|
||||
| ((rid & CS_RID_MASK) << CS_RID_SHIFT)
|
||||
| ((ping_val & CS_PINGVAL_MASK) << CS_PINGVAL_SHIFT)
|
||||
|
||||
);
|
||||
|
||||
uint32_t *payload = (uint32_t *) (d_payload + p_len);
|
||||
*payload = host_to_usrp_u32(ping);
|
||||
|
||||
// Update payload length
|
||||
incr_header_len(CS_FIXED_LEN + CS_PING_LEN);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds a write register command to the packet.
|
||||
*
|
||||
* The \p reg_num is the register number for which the value \p val will be
|
||||
* written to.
|
||||
*
|
||||
* \returns true if the command was added to the packet successfully, false
|
||||
* otherwise.
|
||||
*/
|
||||
bool usrp_inband_usb_packet::cs_write_reg(long reg_num, long val)
|
||||
{
|
||||
if(!align32())
|
||||
return false;
|
||||
|
||||
int p_len = payload_len();
|
||||
|
||||
if((MAX_PAYLOAD - p_len) < (CS_WRITEREG_LEN + CS_FIXED_LEN))
|
||||
return false;
|
||||
|
||||
uint32_t word0 = 0;
|
||||
|
||||
// Build the first word which includes the register number
|
||||
word0 = (
|
||||
((OP_WRITE_REG & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
|
||||
| ((CS_WRITEREG_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
|
||||
| ((reg_num & CS_REGNUM_MASK) << CS_REGNUM_SHIFT)
|
||||
);
|
||||
|
||||
uint32_t *payload = (uint32_t *) (d_payload + p_len);
|
||||
*payload = host_to_usrp_u32(word0);
|
||||
|
||||
// The second word is solely the register value to be written
|
||||
// FIXME: should this be unsigned?
|
||||
payload += 1;
|
||||
*payload = host_to_usrp_u32((uint32_t) val);
|
||||
|
||||
// Rebuild the header to update the payload length
|
||||
incr_header_len(CS_FIXED_LEN + CS_WRITEREG_LEN);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds a write register masked command to the packet.
|
||||
*
|
||||
* The \p reg_num is the register number for which the value \p val will be
|
||||
* written, masked by \p mask
|
||||
*
|
||||
* \returns true if the command was added to the packet, false otherwise.
|
||||
*/
|
||||
bool usrp_inband_usb_packet::cs_write_reg_masked(long reg_num, long val, long mask)
|
||||
{
|
||||
if(!align32())
|
||||
return false;
|
||||
|
||||
int p_len = payload_len();
|
||||
|
||||
if((MAX_PAYLOAD - p_len) < (CS_WRITEREGMASKED_LEN + CS_FIXED_LEN))
|
||||
return false;
|
||||
|
||||
uint32_t word0 = 0;
|
||||
|
||||
// Build the first word which includes the register number
|
||||
word0 = (
|
||||
((OP_WRITE_REG_MASKED & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
|
||||
| ((CS_WRITEREGMASKED_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
|
||||
| ((reg_num & CS_REGNUM_MASK) << CS_REGNUM_SHIFT)
|
||||
);
|
||||
|
||||
uint32_t *payload = (uint32_t *) (d_payload + p_len);
|
||||
*payload = host_to_usrp_u32(word0);
|
||||
|
||||
// Skip over the first word and write the register value
|
||||
payload += 1;
|
||||
*payload = host_to_usrp_u32((uint32_t) val);
|
||||
|
||||
// Skip over the register value and write the mask
|
||||
payload += 1;
|
||||
*payload = host_to_usrp_u32((uint32_t) mask);
|
||||
|
||||
// Rebuild the header to update the payload length
|
||||
incr_header_len(CS_FIXED_LEN + CS_WRITEREGMASKED_LEN);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds a read register message to the packet.
|
||||
*
|
||||
* The \p rid will be the associated RID returned with the response, and \p
|
||||
* reg_num is the register to be read.
|
||||
*
|
||||
* \returns true if the command was added to the packet, false otherwise.
|
||||
*/
|
||||
bool usrp_inband_usb_packet::cs_read_reg(long rid, long reg_num)
|
||||
{
|
||||
if(!align32())
|
||||
return false;
|
||||
|
||||
int p_len = payload_len();
|
||||
|
||||
if((MAX_PAYLOAD - p_len) < (CS_READREG_LEN + CS_FIXED_LEN))
|
||||
return false;
|
||||
|
||||
uint32_t read_reg = (
|
||||
((OP_READ_REG & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
|
||||
| ((CS_READREG_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
|
||||
| ((rid & CS_RID_MASK) << CS_RID_SHIFT)
|
||||
| ((reg_num & CS_REGNUM_MASK) << CS_REGNUM_SHIFT)
|
||||
|
||||
);
|
||||
|
||||
uint32_t *payload = (uint32_t *) (d_payload + p_len);
|
||||
*payload = host_to_usrp_u32(read_reg);
|
||||
|
||||
// Update payload length
|
||||
incr_header_len(CS_FIXED_LEN + CS_READREG_LEN);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds a read register reply response to the current packet. This is
|
||||
* used by the fake USRP code to generate fake register read responses for
|
||||
* testing.
|
||||
*
|
||||
* The \p rid is the associated RID to be included in the response, \p reg_num
|
||||
* is the register the read is coming from, and \p reg_val is the value of the
|
||||
* read.
|
||||
*
|
||||
* \returns true if the command was added to the packet, false otherwise.
|
||||
*/
|
||||
bool usrp_inband_usb_packet::cs_read_reg_reply(long rid, long reg_num, long reg_val)
|
||||
{
|
||||
if(!align32())
|
||||
return false;
|
||||
|
||||
int p_len = payload_len();
|
||||
|
||||
if((MAX_PAYLOAD - p_len) < (CS_READREGREPLY_LEN + CS_FIXED_LEN))
|
||||
return false;
|
||||
|
||||
uint32_t word0 = (
|
||||
((OP_READ_REG_REPLY & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
|
||||
| ((CS_READREGREPLY_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
|
||||
| ((rid & CS_RID_MASK) << CS_RID_SHIFT)
|
||||
| ((reg_num & CS_REGNUM_MASK) << CS_REGNUM_SHIFT)
|
||||
|
||||
);
|
||||
|
||||
uint32_t *payload = (uint32_t *) (d_payload + p_len);
|
||||
*payload = host_to_usrp_u32(word0);
|
||||
|
||||
// Hop to the next word and write the reg value
|
||||
payload += 1;
|
||||
*payload = host_to_usrp_u32((uint32_t) reg_val);
|
||||
|
||||
// Update payload length
|
||||
incr_header_len(CS_FIXED_LEN + CS_READREGREPLY_LEN);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds a delay command to the current packet.
|
||||
*
|
||||
* The \p ticks parameter is the number of clock ticks the FPGA should delay
|
||||
* parsing for, which is added to the packet.
|
||||
*
|
||||
* \returns true if the command was added to the packet, false otherwise.
|
||||
*/
|
||||
bool usrp_inband_usb_packet::cs_delay(long ticks)
|
||||
{
|
||||
if(!align32())
|
||||
return false;
|
||||
|
||||
int p_len = payload_len();
|
||||
|
||||
if((MAX_PAYLOAD - p_len) < (CS_DELAY_LEN + CS_FIXED_LEN))
|
||||
return false;
|
||||
|
||||
uint32_t delay = (
|
||||
((OP_DELAY & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
|
||||
| ((CS_DELAY_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
|
||||
| ((ticks & CS_DELAY_MASK) << CS_DELAY_SHIFT)
|
||||
|
||||
);
|
||||
|
||||
uint32_t *payload = (uint32_t *) (d_payload + p_len);
|
||||
*payload = host_to_usrp_u32(delay);
|
||||
|
||||
// Update payload length
|
||||
incr_header_len(CS_FIXED_LEN + CS_DELAY_LEN);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief
|
||||
*
|
||||
* \returns true if the command was added to the packet, false otherwise.
|
||||
*/
|
||||
bool usrp_inband_usb_packet::cs_i2c_write(long i2c_addr, uint8_t *i2c_data, size_t data_len)
|
||||
{
|
||||
if(!align32())
|
||||
return false;
|
||||
|
||||
int p_len = payload_len();
|
||||
|
||||
int i2c_len = data_len + 2; // 2 bytes between mbz and addr
|
||||
|
||||
if((MAX_PAYLOAD - p_len) < (i2c_len + CS_FIXED_LEN))
|
||||
return false;
|
||||
|
||||
uint32_t word0 = 0;
|
||||
|
||||
word0 = (
|
||||
((OP_I2C_WRITE & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
|
||||
| ((i2c_len & CS_LEN_MASK) << CS_LEN_SHIFT)
|
||||
| ((i2c_addr & CS_I2CADDR_MASK) << CS_I2CADDR_SHIFT)
|
||||
);
|
||||
|
||||
uint32_t *payload = (uint32_t *) (d_payload + p_len);
|
||||
*payload = host_to_usrp_u32(word0);
|
||||
|
||||
// Jump over the first word and write the data
|
||||
// FIXME: Should the data be changed to usrp byte order?
|
||||
payload += 1;
|
||||
memcpy(payload, i2c_data, data_len);
|
||||
|
||||
// Update payload length
|
||||
incr_header_len(CS_FIXED_LEN + i2c_len);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds an I2C read command to the current packet.
|
||||
*
|
||||
* The \p rid is the associated RID to return with the read response, \p
|
||||
* i2c_addr is the address to read from on the I2C bus, and \p n_bytes is the
|
||||
* number of bytes to be read from the bus.
|
||||
*
|
||||
* \returns true if the command was added to the packet, false otherwise.
|
||||
*/
|
||||
bool usrp_inband_usb_packet::cs_i2c_read(long rid, long i2c_addr, long n_bytes)
|
||||
{
|
||||
if(!align32())
|
||||
return false;
|
||||
|
||||
int p_len = payload_len();
|
||||
|
||||
if((MAX_PAYLOAD - p_len) < (CS_I2CREAD_LEN + CS_FIXED_LEN))
|
||||
return false;
|
||||
|
||||
uint32_t word0 = 0;
|
||||
|
||||
word0 = (
|
||||
((OP_I2C_READ & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
|
||||
| ((CS_I2CREAD_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
|
||||
| ((rid & CS_RID_MASK) << CS_RID_SHIFT)
|
||||
| ((i2c_addr & CS_I2CADDR_MASK) << CS_I2CADDR_SHIFT)
|
||||
);
|
||||
|
||||
uint32_t *payload = (uint32_t *) (d_payload + p_len);
|
||||
*payload = host_to_usrp_u32(word0);
|
||||
|
||||
// Jump a word and write the number of bytes to read
|
||||
payload += 1;
|
||||
uint32_t word1 =
|
||||
(n_bytes & CS_I2CREADBYTES_MASK) << CS_I2CREADBYTES_SHIFT;
|
||||
*payload = host_to_usrp_u32(word1);
|
||||
|
||||
// Update payload length
|
||||
incr_header_len(CS_FIXED_LEN + CS_I2CREAD_LEN);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds an I2C read reply response to the current packet. This is used
|
||||
* by the fake USRP code to generate fake I2C responses.
|
||||
*
|
||||
* The \p rid is the RID to be associated with the response, \p i2c_addr is the
|
||||
* address on the I2C bus that the \p i2c_data of \p i2c_data_len was read from.
|
||||
*
|
||||
* \returns true if the command was added to the packet, false otherwise.
|
||||
*/
|
||||
bool usrp_inband_usb_packet::cs_i2c_read_reply(long rid, long i2c_addr, uint8_t *i2c_data, long i2c_data_len)
|
||||
{
|
||||
if(!align32())
|
||||
return false;
|
||||
|
||||
int p_len = payload_len();
|
||||
|
||||
int i2c_len = i2c_data_len + 2;
|
||||
|
||||
if((MAX_PAYLOAD - p_len) < (i2c_len + CS_FIXED_LEN))
|
||||
return false;
|
||||
|
||||
uint32_t word0 = 0;
|
||||
|
||||
word0 = (
|
||||
((OP_I2C_READ_REPLY & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
|
||||
| ((i2c_len & CS_LEN_MASK) << CS_LEN_SHIFT)
|
||||
| ((rid & CS_RID_MASK) << CS_RID_SHIFT)
|
||||
| ((i2c_addr & CS_I2CADDR_MASK) << CS_I2CADDR_SHIFT)
|
||||
);
|
||||
|
||||
uint32_t *payload = (uint32_t *) (d_payload + p_len);
|
||||
*payload = host_to_usrp_u32(word0);
|
||||
|
||||
// Jump a word and write the actual data
|
||||
payload += 1;
|
||||
memcpy(payload, i2c_data, i2c_data_len);
|
||||
|
||||
// Update payload length
|
||||
incr_header_len(CS_FIXED_LEN + i2c_len);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds a SPI write command to the current packet.
|
||||
*
|
||||
* \returns true if the command was added to the packet, false otherwise.
|
||||
*/
|
||||
bool usrp_inband_usb_packet::cs_spi_write(long enables, long format, long opt_header_bytes, uint8_t *spi_data, long spi_data_len)
|
||||
{
|
||||
if(!align32())
|
||||
return false;
|
||||
|
||||
int p_len = payload_len();
|
||||
|
||||
int spi_len = spi_data_len + 6;
|
||||
|
||||
if((MAX_PAYLOAD - p_len) < (spi_len + CS_FIXED_LEN))
|
||||
return false;
|
||||
|
||||
uint32_t word = 0;
|
||||
|
||||
// First word contains the opcode and length, then mbz
|
||||
word = (
|
||||
((OP_SPI_WRITE & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
|
||||
| ((spi_len & CS_LEN_MASK) << CS_LEN_SHIFT)
|
||||
);
|
||||
uint32_t *payload = (uint32_t *) (d_payload + p_len);
|
||||
*payload = host_to_usrp_u32(word);
|
||||
|
||||
payload += 1;
|
||||
|
||||
// Second word contains the enables, format, and optional tx bytes
|
||||
word = 0;
|
||||
word = (
|
||||
((enables & CS_SPIENABLES_MASK) << CS_SPIENABLES_SHIFT)
|
||||
| ((format & CS_SPIFORMAT_MASK) << CS_SPIFORMAT_SHIFT)
|
||||
| ((opt_header_bytes & CS_SPIOPT_MASK) << CS_SPIOPT_SHIFT)
|
||||
);
|
||||
payload = (uint32_t *) (d_payload + p_len);
|
||||
*payload = host_to_usrp_u32(word);
|
||||
|
||||
payload += 1;
|
||||
memcpy(payload, spi_data, spi_data_len);
|
||||
|
||||
// Update payload length
|
||||
incr_header_len(CS_FIXED_LEN + spi_len);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds a SPI bus read command to the packet.
|
||||
*
|
||||
* \returns true if the command was added to the packet, false otherwise.
|
||||
*/
|
||||
bool usrp_inband_usb_packet::cs_spi_read(long rid, long enables, long format, long opt_header_bytes, long n_bytes)
|
||||
{
|
||||
if(!align32())
|
||||
return false;
|
||||
|
||||
int p_len = payload_len();
|
||||
|
||||
if((MAX_PAYLOAD - p_len) < (CS_SPIREAD_LEN + CS_FIXED_LEN))
|
||||
return false;
|
||||
|
||||
uint32_t word = 0;
|
||||
|
||||
// First word contains the opcode, length, and RID
|
||||
word = (
|
||||
((OP_SPI_READ & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
|
||||
| ((CS_SPIREAD_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
|
||||
| ((rid & CS_RID_MASK) << CS_RID_SHIFT)
|
||||
);
|
||||
uint32_t *payload = (uint32_t *) (d_payload + p_len);
|
||||
*payload = host_to_usrp_u32(word);
|
||||
|
||||
payload += 1;
|
||||
|
||||
// Second word contains the enables, format, and optional tx bytes
|
||||
word = 0;
|
||||
word = (
|
||||
((enables & CS_SPIENABLES_MASK) << CS_SPIENABLES_SHIFT)
|
||||
| ((format & CS_SPIFORMAT_MASK) << CS_SPIFORMAT_SHIFT)
|
||||
| ((opt_header_bytes & CS_SPIOPT_MASK) << CS_SPIOPT_SHIFT)
|
||||
);
|
||||
payload = (uint32_t *) (d_payload + p_len);
|
||||
*payload = host_to_usrp_u32(word);
|
||||
|
||||
payload += 1;
|
||||
|
||||
// The third word contains the number of bytes
|
||||
word = 0;
|
||||
word = (
|
||||
((n_bytes & CS_SPINBYTES_MASK) << CS_SPINBYTES_SHIFT)
|
||||
);
|
||||
payload = (uint32_t *) (d_payload + p_len);
|
||||
*payload = host_to_usrp_u32(word);
|
||||
|
||||
// Update payload length
|
||||
incr_header_len(CS_FIXED_LEN + CS_SPIREAD_LEN);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds an SPI read reply to the current packet. This is used by the
|
||||
* fake USRP code to generate fake responses for SPI reads.
|
||||
*
|
||||
* \returns true if the command was added to the packet, false otherwise.
|
||||
*/
|
||||
bool usrp_inband_usb_packet::cs_spi_read_reply(long rid, uint8_t *spi_data, long spi_data_len)
|
||||
{
|
||||
if(!align32())
|
||||
return false;
|
||||
|
||||
int p_len = payload_len();
|
||||
|
||||
int spi_len = spi_data_len + 2;
|
||||
|
||||
if((MAX_PAYLOAD - p_len) < (spi_len + CS_FIXED_LEN))
|
||||
return false;
|
||||
|
||||
uint32_t word = 0;
|
||||
|
||||
// First word contains the opcode, length, and RID
|
||||
word = (
|
||||
((OP_SPI_READ_REPLY & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
|
||||
| ((spi_len & CS_LEN_MASK) << CS_LEN_SHIFT)
|
||||
| ((rid & CS_RID_MASK) << CS_RID_SHIFT)
|
||||
);
|
||||
uint32_t *payload = (uint32_t *) (d_payload + p_len);
|
||||
*payload = host_to_usrp_u32(word);
|
||||
|
||||
// Jump a word and write the actual data
|
||||
payload += 1;
|
||||
memcpy(payload, spi_data, spi_data_len);
|
||||
|
||||
// Update payload length
|
||||
incr_header_len(CS_FIXED_LEN + spi_len);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Since all control packets contain subpackets which have the length of
|
||||
* the subpacket at a uniform location in the subpacket, this will return the
|
||||
* subpacket length given a byte offset of the start of the subpacket from the beginning of the packet.
|
||||
*
|
||||
* \returns the length of the subpacket
|
||||
*/
|
||||
int usrp_inband_usb_packet::cs_len(int payload_offset) {
|
||||
uint32_t subpkt = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset)));
|
||||
return (subpkt >> CS_LEN_SHIFT) & CS_LEN_MASK;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief The following method takes an offset within the packet payload to
|
||||
* extract a control/status subpacket and constructs a pmt response which
|
||||
* includes the proper signal and arguments specified by usrp-low-level-cs. The
|
||||
* USRP server could therefore use this to read subpackets and pass them
|
||||
* responses back up to the application. It's arguable that only reply packets
|
||||
* should be parsed here, however we parse others for use in debugging or
|
||||
* failure reporting on the transmit side of packets.
|
||||
*/
|
||||
pmt_t usrp_inband_usb_packet::read_subpacket(int payload_offset) {
|
||||
|
||||
uint32_t subpkt = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset)));
|
||||
uint32_t opcode = (subpkt >> CS_OPCODE_SHIFT) & CS_OPCODE_MASK;
|
||||
uint32_t len = (subpkt >> CS_LEN_SHIFT) & CS_LEN_MASK;
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case OP_PING_FIXED_REPLY:
|
||||
{
|
||||
pmt_t rid = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
|
||||
pmt_t pingval = pmt_from_long((subpkt >> CS_PINGVAL_SHIFT) & CS_PINGVAL_MASK);
|
||||
return pmt_list3(s_op_ping_fixed_reply, rid, pingval);
|
||||
}
|
||||
|
||||
case OP_READ_REG_REPLY:
|
||||
{
|
||||
pmt_t rid = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
|
||||
pmt_t reg_num = pmt_from_long((subpkt >> CS_REGNUM_SHIFT) & CS_REGNUM_MASK);
|
||||
|
||||
// To get the register value we just read the next 32 bits
|
||||
uint32_t val = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 4)));
|
||||
pmt_t reg_val = pmt_from_long(val);
|
||||
|
||||
return pmt_list4(s_op_read_reg_reply, rid, reg_num, reg_val);
|
||||
}
|
||||
|
||||
case OP_I2C_READ_REPLY:
|
||||
{
|
||||
pmt_t rid = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
|
||||
pmt_t i2c_addr = pmt_from_long((subpkt >> CS_I2CADDR_SHIFT) & CS_I2CADDR_MASK);
|
||||
|
||||
// Make a u8 vector to dump the data from the packet into
|
||||
size_t i2c_data_len;
|
||||
pmt_t i2c_data = pmt_make_u8vector(len - 2, 0); // skip rid+mbz+addr = 2 bytes
|
||||
uint8_t *w_data =
|
||||
(uint8_t *) pmt_u8vector_writable_elements(i2c_data, i2c_data_len);
|
||||
|
||||
memcpy(w_data, d_payload + payload_offset + 4, i2c_data_len); // skip first word
|
||||
|
||||
return pmt_list4(s_op_i2c_read_reply, rid, i2c_addr, i2c_data);
|
||||
}
|
||||
|
||||
case OP_SPI_READ_REPLY:
|
||||
{
|
||||
pmt_t rid = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
|
||||
|
||||
// Make a u8 vector to dump the data from the packet into
|
||||
size_t spi_data_len;
|
||||
pmt_t spi_data = pmt_make_u8vector(len - 2, 0); // skip rid+mbz+addr = 2 bytes
|
||||
uint8_t *w_data =
|
||||
(uint8_t *) pmt_u8vector_writable_elements(spi_data, spi_data_len);
|
||||
|
||||
memcpy(w_data, d_payload + payload_offset + 4, spi_data_len); // skip first word
|
||||
|
||||
return pmt_list3(s_op_spi_read_reply, rid, spi_data);
|
||||
}
|
||||
|
||||
case OP_PING_FIXED:
|
||||
{
|
||||
pmt_t rid = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
|
||||
pmt_t pingval = pmt_from_long((subpkt >> CS_PINGVAL_SHIFT) & CS_PINGVAL_MASK);
|
||||
return pmt_list3(s_op_ping_fixed, rid, pingval);
|
||||
}
|
||||
|
||||
case OP_WRITE_REG:
|
||||
{
|
||||
pmt_t reg_num = pmt_from_long((subpkt >> CS_REGNUM_SHIFT) & CS_REGNUM_MASK);
|
||||
|
||||
// To get the register value we just read the next 32 bits
|
||||
uint32_t val = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 4)));
|
||||
pmt_t reg_val = pmt_from_long(val);
|
||||
|
||||
return pmt_list3(s_op_write_reg, reg_num, reg_val);
|
||||
}
|
||||
|
||||
case OP_WRITE_REG_MASKED:
|
||||
{
|
||||
pmt_t reg_num = pmt_from_long((subpkt >> CS_REGNUM_SHIFT) & CS_REGNUM_MASK);
|
||||
|
||||
// To get the register value we just read the next 32 bits
|
||||
uint32_t val = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 4)));
|
||||
pmt_t reg_val = pmt_from_long(val);
|
||||
|
||||
// The mask is the next 32 bits
|
||||
uint32_t mask = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 8)));
|
||||
pmt_t reg_mask = pmt_from_long(mask);
|
||||
|
||||
return pmt_list4(s_op_write_reg_masked, reg_num, reg_val, reg_mask);
|
||||
}
|
||||
|
||||
case OP_READ_REG:
|
||||
{
|
||||
pmt_t rid = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
|
||||
pmt_t reg_num = pmt_from_long((subpkt >> CS_REGNUM_SHIFT) & CS_REGNUM_MASK);
|
||||
|
||||
return pmt_list3(s_op_read_reg, rid, reg_num);
|
||||
}
|
||||
|
||||
case OP_I2C_WRITE:
|
||||
{
|
||||
pmt_t i2c_addr = pmt_from_long((subpkt >> CS_I2CADDR_SHIFT) & CS_I2CADDR_MASK);
|
||||
|
||||
// The length includes an extra 2 bytes for storing the mbz and addr
|
||||
pmt_t i2c_data = pmt_make_u8vector(len-2, 0);
|
||||
|
||||
// Get a writable address to copy the data from the packet
|
||||
size_t ignore;
|
||||
uint8_t *w_data = (uint8_t *) pmt_u8vector_writable_elements(i2c_data, ignore);
|
||||
memcpy(w_data, d_payload + payload_offset + 4, len-2);
|
||||
|
||||
|
||||
return pmt_list3(s_op_i2c_write, i2c_addr, i2c_data);
|
||||
}
|
||||
|
||||
case OP_I2C_READ:
|
||||
{
|
||||
pmt_t rid = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
|
||||
pmt_t i2c_addr = pmt_from_long((subpkt >> CS_I2CADDR_SHIFT) & CS_I2CADDR_MASK);
|
||||
|
||||
// The number of bytes is in the next word
|
||||
uint32_t bytes = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 4)));
|
||||
bytes = (bytes >> CS_I2CREADBYTES_SHIFT) & CS_I2CREADBYTES_MASK;
|
||||
pmt_t i2c_bytes = pmt_from_long(bytes);
|
||||
|
||||
return pmt_list4(s_op_i2c_read, rid, i2c_addr, i2c_bytes);
|
||||
}
|
||||
|
||||
case OP_SPI_WRITE:
|
||||
{
|
||||
// Nothing interesting in the first word, skip to the next
|
||||
uint32_t word = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 4)));
|
||||
pmt_t enables = pmt_from_long((word >> CS_SPIENABLES_SHIFT) & CS_SPIENABLES_MASK);
|
||||
pmt_t format = pmt_from_long((word >> CS_SPIFORMAT_SHIFT) & CS_SPIFORMAT_MASK);
|
||||
pmt_t opt = pmt_from_long((word >> CS_SPIOPT_SHIFT) & CS_SPIOPT_MASK);
|
||||
|
||||
// From the next word and on is data
|
||||
size_t spi_data_len;
|
||||
pmt_t spi_data = pmt_make_u8vector(len - 6, 0); // skip rid+mbz+addr = 2 bytes
|
||||
uint8_t *w_data =
|
||||
(uint8_t *) pmt_u8vector_writable_elements(spi_data, spi_data_len);
|
||||
|
||||
memcpy(w_data, d_payload + payload_offset + 8, spi_data_len); // skip first 2 words
|
||||
|
||||
return pmt_list5(s_op_spi_write, enables, format, opt, spi_data);
|
||||
}
|
||||
|
||||
case OP_SPI_READ:
|
||||
{
|
||||
// Read the RID from the first word, the rest is mbz
|
||||
pmt_t rid = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
|
||||
|
||||
// Continue at the next word...
|
||||
uint32_t word = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 4)));
|
||||
pmt_t enables = pmt_from_long((word >> CS_SPIENABLES_SHIFT) & CS_SPIENABLES_MASK);
|
||||
pmt_t format = pmt_from_long((word >> CS_SPIFORMAT_SHIFT) & CS_SPIFORMAT_MASK);
|
||||
pmt_t opt = pmt_from_long((word >> CS_SPIOPT_SHIFT) & CS_SPIOPT_MASK);
|
||||
|
||||
// The number of bytes is the only thing to read in the next word
|
||||
word = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 8)));
|
||||
pmt_t n_bytes = pmt_from_long((word >> CS_SPINBYTES_SHIFT) & CS_SPINBYTES_MASK);
|
||||
|
||||
return pmt_list6(s_op_spi_read, rid, enables, format, opt, n_bytes);
|
||||
}
|
||||
|
||||
case OP_DELAY:
|
||||
{
|
||||
pmt_t ticks = pmt_from_long((subpkt >> CS_DELAY_SHIFT) & CS_DELAY_MASK);
|
||||
|
||||
return pmt_list2(s_op_delay, ticks);
|
||||
}
|
||||
|
||||
default:
|
||||
return PMT_NIL;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,240 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007,2008 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_USRP_INBAND_USB_PACKET_H_
|
||||
#define INCLUDED_USRP_INBAND_USB_PACKET_H_
|
||||
|
||||
#include <usrp_bytesex.h>
|
||||
#include <mblock/mblock.h>
|
||||
#include <pmt.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <symbols_usrp_low_level_cs.h>
|
||||
|
||||
static const int USB_PKT_SIZE = 512; // bytes
|
||||
static const int MAX_PAYLOAD = USB_PKT_SIZE-2*sizeof(uint32_t);
|
||||
static const int CONTROL_CHAN = 0x1f;
|
||||
|
||||
class usrp_inband_usb_packet {
|
||||
//
|
||||
// keep raw packet in USRP-endian order
|
||||
//
|
||||
uint32_t d_word0;
|
||||
uint32_t d_timestamp;
|
||||
unsigned char d_payload[MAX_PAYLOAD];
|
||||
|
||||
public:
|
||||
|
||||
enum opcodes {
|
||||
OP_PING_FIXED = 0x00,
|
||||
OP_PING_FIXED_REPLY = 0x01,
|
||||
OP_WRITE_REG = 0x02,
|
||||
OP_WRITE_REG_MASKED = 0x03,
|
||||
OP_READ_REG = 0x04,
|
||||
OP_READ_REG_REPLY = 0x05,
|
||||
OP_I2C_WRITE = 0x06,
|
||||
OP_I2C_READ = 0x07,
|
||||
OP_I2C_READ_REPLY = 0x08,
|
||||
OP_SPI_WRITE = 0x09,
|
||||
OP_SPI_READ = 0x0a,
|
||||
OP_SPI_READ_REPLY = 0x0b,
|
||||
OP_DELAY = 0x0c
|
||||
};
|
||||
|
||||
enum flags {
|
||||
FL_OVERRUN = 0x80000000,
|
||||
FL_UNDERRUN = 0x40000000,
|
||||
FL_DROPPED = 0x20000000,
|
||||
FL_START_OF_BURST = 0x10000000,
|
||||
FL_END_OF_BURST = 0x08000000,
|
||||
FL_CARRIER_SENSE = 0x04000000,
|
||||
|
||||
FL_ALL_FLAGS = 0xfc000000
|
||||
};
|
||||
|
||||
static const int FL_OVERRUN_SHIFT = 31;
|
||||
static const int FL_UNDERRUN_SHIFT = 30;
|
||||
static const int FL_DROPPED_SHIFT = 29;
|
||||
static const int FL_END_OF_BURST_SHIFT = 27;
|
||||
static const int FL_START_OF_BURST_SHIFT = 28;
|
||||
|
||||
static const int RSSI_MASK = 0x3f;
|
||||
static const int RSSI_SHIFT = 21;
|
||||
|
||||
static const int CHAN_MASK = 0x1f;
|
||||
static const int CHAN_SHIFT = 16;
|
||||
|
||||
static const int TAG_MASK = 0xf;
|
||||
static const int TAG_SHIFT = 9;
|
||||
|
||||
static const int PAYLOAD_LEN_MASK = 0x1ff;
|
||||
static const int PAYLOAD_LEN_SHIFT = 0;
|
||||
|
||||
// Fixed size for opcode and length fields
|
||||
static const int CS_FIXED_LEN = 2;
|
||||
|
||||
static const int CS_OPCODE_MASK = 0xff;
|
||||
static const int CS_OPCODE_SHIFT = 24;
|
||||
|
||||
static const int CS_LEN_MASK = 0xff;
|
||||
static const int CS_LEN_SHIFT = 16;
|
||||
|
||||
static const int CS_RID_MASK = 0x3f;
|
||||
static const int CS_RID_SHIFT = 10;
|
||||
|
||||
static const int CS_PING_LEN = 2;
|
||||
static const int CS_PINGVAL_MASK = 0x3ff;
|
||||
static const int CS_PINGVAL_SHIFT = 0;
|
||||
|
||||
static const int CS_WRITEREG_LEN = 6;
|
||||
static const int CS_WRITEREGMASKED_LEN = 10;
|
||||
static const int CS_READREG_LEN = 2;
|
||||
static const int CS_READREGREPLY_LEN = 6;
|
||||
static const int CS_REGNUM_MASK = 0x3ff;
|
||||
static const int CS_REGNUM_SHIFT = 0;
|
||||
|
||||
static const int CS_DELAY_LEN = 2;
|
||||
static const int CS_DELAY_MASK = 0xffff;
|
||||
static const int CS_DELAY_SHIFT = 0;
|
||||
|
||||
static const int CS_I2CADDR_MASK = 0x7f;
|
||||
static const int CS_I2CADDR_SHIFT = 0;
|
||||
|
||||
static const int CS_I2CREAD_LEN = 3;
|
||||
static const int CS_I2CREADBYTES_MASK = 0x7f;
|
||||
static const int CS_I2CREADBYTES_SHIFT = 24;
|
||||
|
||||
static const int CS_SPIOPT_MASK = 0xffff;
|
||||
static const int CS_SPIOPT_SHIFT = 0;
|
||||
static const int CS_SPIFORMAT_MASK = 0xff;
|
||||
static const int CS_SPIFORMAT_SHIFT = 16;
|
||||
static const int CS_SPIENABLES_MASK = 0xff;
|
||||
static const int CS_SPIENABLES_SHIFT = 24;
|
||||
static const int CS_SPIREAD_LEN = 7;
|
||||
static const int CS_SPINBYTES_MASK = 0xff;
|
||||
static const int CS_SPINBYTES_SHIFT = 24;
|
||||
|
||||
public:
|
||||
|
||||
void set_timestamp(uint32_t timestamp){
|
||||
d_timestamp = host_to_usrp_u32(timestamp);
|
||||
}
|
||||
|
||||
void set_end_of_burst() {
|
||||
uint32_t word0 = usrp_to_host_u32(d_word0);
|
||||
word0 |= 1<<FL_END_OF_BURST_SHIFT;
|
||||
d_word0 = host_to_usrp_u32(word0);
|
||||
}
|
||||
|
||||
void set_header(int flags, int chan, int tag, int payload_len){
|
||||
uint32_t word0 = ((flags & FL_ALL_FLAGS)
|
||||
| ((chan & CHAN_MASK) << CHAN_SHIFT)
|
||||
| ((tag & TAG_MASK) << TAG_SHIFT)
|
||||
| ((payload_len & PAYLOAD_LEN_MASK) << PAYLOAD_LEN_SHIFT));
|
||||
d_word0 = host_to_usrp_u32(word0);
|
||||
}
|
||||
|
||||
void incr_header_len(int val) {
|
||||
set_header(flags(), chan(), tag(), payload_len() + val);
|
||||
}
|
||||
|
||||
uint32_t timestamp() const {
|
||||
return usrp_to_host_u32(d_timestamp);
|
||||
}
|
||||
|
||||
int rssi() const {
|
||||
uint32_t word0 = usrp_to_host_u32(d_word0);
|
||||
return (word0 >> RSSI_SHIFT) & RSSI_MASK;
|
||||
}
|
||||
|
||||
int chan() const {
|
||||
uint32_t word0 = usrp_to_host_u32(d_word0);
|
||||
return (word0 >> CHAN_SHIFT) & CHAN_MASK;
|
||||
}
|
||||
|
||||
int tag() const {
|
||||
uint32_t word0 = usrp_to_host_u32(d_word0);
|
||||
return (word0 >> TAG_SHIFT) & TAG_MASK;
|
||||
}
|
||||
|
||||
int payload_len() const {
|
||||
uint32_t word0 = usrp_to_host_u32(d_word0);
|
||||
return (word0 >> PAYLOAD_LEN_SHIFT) & PAYLOAD_LEN_MASK;
|
||||
}
|
||||
|
||||
int flags() const {
|
||||
return usrp_to_host_u32(d_word0) & FL_ALL_FLAGS;
|
||||
}
|
||||
|
||||
int overrun() const {
|
||||
return (usrp_to_host_u32(d_word0) & FL_OVERRUN) >> FL_OVERRUN_SHIFT;
|
||||
}
|
||||
|
||||
|
||||
int underrun() const {
|
||||
return (usrp_to_host_u32(d_word0) & FL_UNDERRUN) >> FL_UNDERRUN_SHIFT;
|
||||
}
|
||||
|
||||
|
||||
int start_of_burst() const {
|
||||
return (usrp_to_host_u32(d_word0) & FL_START_OF_BURST) >> FL_START_OF_BURST_SHIFT;
|
||||
}
|
||||
|
||||
int end_of_burst() const {
|
||||
return (usrp_to_host_u32(d_word0) & FL_END_OF_BURST) >> FL_END_OF_BURST_SHIFT;
|
||||
}
|
||||
|
||||
int dropped() const {
|
||||
return (usrp_to_host_u32(d_word0) & FL_DROPPED) >> FL_DROPPED_SHIFT;
|
||||
}
|
||||
|
||||
unsigned char *payload() {
|
||||
return d_payload;
|
||||
}
|
||||
|
||||
static int max_payload() {
|
||||
return MAX_PAYLOAD;
|
||||
}
|
||||
|
||||
static int max_pkt_size() {
|
||||
return USB_PKT_SIZE;
|
||||
}
|
||||
|
||||
// C/S methods
|
||||
bool align32();
|
||||
bool cs_ping(long rid, long ping_val);
|
||||
bool cs_ping_reply(long rid, long ping_val);
|
||||
bool cs_write_reg(long reg_num, long val);
|
||||
bool cs_write_reg_masked(long reg_num, long val, long mask);
|
||||
bool cs_read_reg(long rid, long reg_num);
|
||||
bool cs_read_reg_reply(long rid, long reg_num, long reg_val);
|
||||
bool cs_delay(long ticks);
|
||||
bool cs_i2c_write(long i2c_addr, uint8_t *i2c_data, size_t data_len);
|
||||
bool cs_i2c_read(long rid, long i2c_addr, long n_bytes);
|
||||
bool cs_i2c_read_reply(long rid, long i2c_addr, uint8_t *i2c_data, long i2c_data_len);
|
||||
bool cs_spi_write(long enables, long format, long opt_header_bytes, uint8_t *spi_data, long spi_data_len);
|
||||
bool cs_spi_read(long rid, long enables, long format, long opt_header_bytes, long n_bytes);
|
||||
bool cs_spi_read_reply(long rid, uint8_t *spi_data, long spi_data_len);
|
||||
int cs_len(int payload_offset);
|
||||
pmt_t read_subpacket(int payload_offset);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,88 +0,0 @@
|
|||
;; -*- scheme -*- ; not really, but tells emacs how to format this
|
||||
;;
|
||||
;; Copyright 2007 Free Software Foundation, Inc.
|
||||
;;
|
||||
;; This file is part of GNU Radio
|
||||
;;
|
||||
;; GNU Radio is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation; either version 2, or (at your option)
|
||||
;; any later version.
|
||||
;;
|
||||
;; GNU Radio is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
;;
|
||||
;; You should have received a copy of the GNU General Public License along
|
||||
;; with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
;; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
;;
|
||||
|
||||
;; ----------------------------------------------------------------
|
||||
;; This is an mblock header file
|
||||
;;
|
||||
;; The format is very much a work-in-progress.
|
||||
;; It'll be compiled to C++.
|
||||
;; ----------------------------------------------------------------
|
||||
|
||||
;; ----------------------------------------------------------------
|
||||
;; usrp-interface-cs
|
||||
;;
|
||||
;; Handles interaction between the usrp_sever and the USB interface
|
||||
|
||||
(define-protocol-class usrp-interface-cs
|
||||
|
||||
(:outgoing
|
||||
(cmd-usrp-open invocation-handle which-usrp)
|
||||
(cmd-usrp-close invocation-handle)
|
||||
(cmd-usrp-ntx-chan invocation-handle)
|
||||
(cmd-usrp-nrx-chan invocation-handle)
|
||||
(cmd-usrp-write invocation-handle channel data)
|
||||
(cmd-usrp-start-reading invocation-handle channel)
|
||||
)
|
||||
|
||||
(:incoming
|
||||
(response-usrp-open invocation-handle status)
|
||||
(response-usrp-close invocation-handle status)
|
||||
(response-usrp-ntx-chan invocation-handle ntx-chan)
|
||||
(response-usrp-nrx-chan invocation-handle nrx-chan)
|
||||
(response-usrp-write invocation-handle status channel)
|
||||
(response-usrp-read invocation-handle status data)
|
||||
)
|
||||
)
|
||||
|
||||
;; ----------------------------------------------------------------
|
||||
;; usrp-tx-cs
|
||||
;;
|
||||
;; Handles interaction between the USB interface and TX interface
|
||||
|
||||
(define-protocol-class usrp-tx-cs
|
||||
|
||||
(:outgoing
|
||||
(cmd-usrp-tx-write invocation-handle channel data tx-handle)
|
||||
)
|
||||
|
||||
(:incoming
|
||||
(response-usrp-tx-write invocation-handle status channel)
|
||||
)
|
||||
)
|
||||
|
||||
;; ----------------------------------------------------------------
|
||||
;; usrp-rx-cs
|
||||
;;
|
||||
;; Handles interaction between the USB interface and RX interface
|
||||
|
||||
(define-protocol-class usrp-rx-cs
|
||||
|
||||
(:outgoing
|
||||
(cmd-usrp-rx-start-reading invocation-handle rx-handle)
|
||||
(cmd-usrp-rx-stop-reading invocation-handle)
|
||||
)
|
||||
|
||||
(:incoming
|
||||
(response-usrp-rx-read invocation-handle status data)
|
||||
|
||||
;; There is currently no response to a stop reading
|
||||
)
|
||||
)
|
|
@ -1,184 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <usrp_rx.h>
|
||||
|
||||
#include <usrp_standard.h>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <usb.h>
|
||||
#include <mblock/class_registry.h>
|
||||
#include <usrp_inband_usb_packet.h>
|
||||
#include <fpga_regs_common.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <symbols_usrp_rx_cs.h>
|
||||
|
||||
typedef usrp_inband_usb_packet transport_pkt;
|
||||
|
||||
static const bool verbose = false;
|
||||
|
||||
bool usrp_rx_stop;
|
||||
|
||||
usrp_rx::usrp_rx(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg)
|
||||
: mb_mblock(rt, instance_name, user_arg),
|
||||
d_disk_write(false),
|
||||
d_disk_write_pkt(false) // if true, writes full packet, else just the payload
|
||||
{
|
||||
d_cs = define_port("cs", "usrp-rx-cs", true, mb_port::EXTERNAL);
|
||||
|
||||
if(d_disk_write) {
|
||||
d_ofile0.open("rx_data_chan0.dat",std::ios::binary|std::ios::out);
|
||||
d_ofile1.open("rx_data_chan1.dat",std::ios::binary|std::ios::out);
|
||||
d_cs_ofile.open("rx_cs.dat",std::ios::binary|std::ios::out);
|
||||
}
|
||||
|
||||
usrp_rx_stop = false;
|
||||
|
||||
}
|
||||
|
||||
usrp_rx::~usrp_rx()
|
||||
{
|
||||
if(d_disk_write) {
|
||||
d_ofile0.close();
|
||||
d_ofile1.close();
|
||||
d_cs_ofile.close();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
usrp_rx::initial_transition()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Handles incoming signals to to the m-block, wihch should only ever be
|
||||
* a single message: cmd-usrrp-rx-start-reading. There is no signal to stop
|
||||
* reading as the m-block goes in to a forever loop to read inband packets from
|
||||
* the bus.
|
||||
*/
|
||||
void
|
||||
usrp_rx::handle_message(mb_message_sptr msg)
|
||||
{
|
||||
pmt_t event = msg->signal();
|
||||
pmt_t port_id = msg->port_id();
|
||||
pmt_t data = msg->data();
|
||||
|
||||
// Theoretically only have 1 message to ever expect, but
|
||||
// want to make sure its at least what we want
|
||||
if(pmt_eq(port_id, d_cs->port_symbol())) {
|
||||
|
||||
if(pmt_eqv(event, s_cmd_usrp_rx_start_reading))
|
||||
read_and_respond(data);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Performs the actual reading of data from the USB bus, called by
|
||||
* handle_message() when a cmd-usrp-rx-start-reading signal is received.
|
||||
*
|
||||
* The method enters a forever loop where it continues to read data from the bus
|
||||
* and generate read responses to the higher layer. Currently, shared memory is
|
||||
* used to exit this loop.
|
||||
*
|
||||
* The \p data parameter is a PMT list which contains only a single element, an
|
||||
* invocation handle which will be returned with all read respones.
|
||||
*/
|
||||
void
|
||||
usrp_rx::read_and_respond(pmt_t data)
|
||||
{
|
||||
size_t ignore;
|
||||
bool underrun;
|
||||
unsigned int n_read;
|
||||
unsigned int pkt_size = sizeof(transport_pkt);
|
||||
|
||||
pmt_t invocation_handle = pmt_nth(0, data);
|
||||
|
||||
// Need the handle to the RX port to send responses, this is passed
|
||||
// by the USRP interface m-block
|
||||
pmt_t handle = pmt_nth(1, data);
|
||||
d_urx =
|
||||
boost::any_cast<usrp_standard_rx_sptr>(pmt_any_ref(handle));
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[usrp_rx] Waiting for packets..\n";
|
||||
|
||||
// Read by 512 which is packet size and send them back up
|
||||
while(!usrp_rx_stop) {
|
||||
|
||||
pmt_t v_pkt = pmt_make_u8vector(pkt_size, 0);
|
||||
transport_pkt *pkt =
|
||||
(transport_pkt *) pmt_u8vector_writable_elements(v_pkt, ignore);
|
||||
|
||||
n_read = d_urx->read(pkt, pkt_size, &underrun);
|
||||
|
||||
if(n_read != pkt_size) {
|
||||
std::cerr << "[usrp_rx] Error reading packet, shutting down\n";
|
||||
d_cs->send(s_response_usrp_rx_read,
|
||||
pmt_list3(PMT_NIL, PMT_F, PMT_NIL));
|
||||
return;
|
||||
}
|
||||
|
||||
if(underrun && verbose && 0)
|
||||
std::cout << "[usrp_rx] Underrun\n";
|
||||
|
||||
d_cs->send(s_response_usrp_rx_read,
|
||||
pmt_list3(PMT_NIL, PMT_T, v_pkt));
|
||||
if(verbose && 0)
|
||||
std::cout << "[usrp_rx] Read 1 packet\n";
|
||||
|
||||
if(d_disk_write) {
|
||||
if(pkt->chan() == CONTROL_CHAN)
|
||||
d_cs_ofile.write((const char *)pkt, transport_pkt::max_pkt_size());
|
||||
else {
|
||||
if(d_disk_write_pkt) {
|
||||
if(pkt->chan() == 0)
|
||||
d_ofile0.write((const char *)pkt, transport_pkt::max_pkt_size());
|
||||
else if(pkt->chan() == 1)
|
||||
d_ofile1.write((const char *)pkt, transport_pkt::max_pkt_size());
|
||||
} else {
|
||||
if(pkt->chan() == 0)
|
||||
d_ofile0.write((const char *)pkt->payload(), transport_pkt::max_payload());
|
||||
else if(pkt->chan() == 1)
|
||||
d_ofile1.write((const char *)pkt->payload(), transport_pkt::max_payload());
|
||||
}
|
||||
}
|
||||
|
||||
d_cs_ofile.flush();
|
||||
d_ofile0.flush();
|
||||
d_ofile1.flush();
|
||||
}
|
||||
}
|
||||
|
||||
usrp_rx_stop = false;
|
||||
|
||||
if(verbose) {
|
||||
std::cout << "[USRP_RX] Stopping...\n";
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
REGISTER_MBLOCK_CLASS(usrp_rx);
|
|
@ -1,58 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007,2008 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#ifndef INCLUDED_USRP_RX_H
|
||||
#define INCLUDED_USRP_RX_H
|
||||
|
||||
#include <mblock/mblock.h>
|
||||
#include <fstream>
|
||||
#include "usrp_standard.h"
|
||||
|
||||
extern bool usrp_rx_stop; // used to communicate a 'stop' to the RX stub
|
||||
|
||||
/*!
|
||||
* \brief Implements the low level usb interface to the USRP
|
||||
*/
|
||||
class usrp_rx : public mb_mblock
|
||||
{
|
||||
mb_port_sptr d_cs;
|
||||
usrp_standard_rx_sptr d_urx;
|
||||
|
||||
bool d_disk_write;
|
||||
bool d_disk_write_pkt;
|
||||
std::ofstream d_ofile0;
|
||||
std::ofstream d_ofile1;
|
||||
std::ofstream d_cs_ofile;
|
||||
|
||||
public:
|
||||
usrp_rx(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
|
||||
~usrp_rx();
|
||||
void initial_transition();
|
||||
void handle_message(mb_message_sptr msg);
|
||||
|
||||
private:
|
||||
void read_and_respond(pmt_t data);
|
||||
void read_data();
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif /* INCLUDED_USRP_RX_H */
|
||||
|
|
@ -1,227 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007,2008 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <usrp_rx_stub.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <usb.h>
|
||||
#include <mblock/class_registry.h>
|
||||
#include <usrp_inband_usb_packet.h>
|
||||
#include <fpga_regs_common.h>
|
||||
#include "usrp_standard.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ui_nco.h>
|
||||
#include <fstream>
|
||||
|
||||
#include <symbols_usrp_rx_cs.h>
|
||||
|
||||
typedef usrp_inband_usb_packet transport_pkt;
|
||||
|
||||
static const bool verbose = false;
|
||||
|
||||
bool usrp_rx_stop_stub;
|
||||
|
||||
// Used for the fake control packet response code to send the responses back up
|
||||
// the RX. The TX stub dumps responses in to this queue.
|
||||
std::queue<pmt_t> d_cs_queue;
|
||||
|
||||
usrp_rx_stub::usrp_rx_stub(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg)
|
||||
: mb_mblock(rt, instance_name, user_arg),
|
||||
d_samples_per_frame((long)(126)),
|
||||
d_decim_rx(128),
|
||||
d_amplitude(16384),
|
||||
d_disk_write(false)
|
||||
{
|
||||
|
||||
// Information about the rates are passed all the way from the app in the form
|
||||
// of a dictionary. We use this to read the RX decimation rate and compute
|
||||
// the approximate number of MS/s as a form of flow control for the stub.
|
||||
pmt_t usrp_dict = user_arg;
|
||||
|
||||
if (pmt_is_dict(usrp_dict)) {
|
||||
// Read the RX decimation rate
|
||||
if(pmt_t decim_rx = pmt_dict_ref(usrp_dict,
|
||||
pmt_intern("decim-rx"),
|
||||
PMT_NIL)) {
|
||||
if(!pmt_eqv(decim_rx, PMT_NIL))
|
||||
d_decim_rx = pmt_to_long(decim_rx);
|
||||
}
|
||||
}
|
||||
|
||||
d_cs = define_port("cs", "usrp-rx-cs", true, mb_port::EXTERNAL);
|
||||
|
||||
// initialize NCO
|
||||
double freq = 100e3;
|
||||
int interp = 32; // 32 -> 4MS/s
|
||||
double sample_rate = 64e6 / interp;
|
||||
d_nco.set_freq(2*M_PI * freq/sample_rate);
|
||||
|
||||
//d_disk_write = true;
|
||||
|
||||
if(d_disk_write)
|
||||
d_ofile.open("raw_rx.dat",std::ios::binary|std::ios::out);
|
||||
|
||||
usrp_rx_stop_stub = false;
|
||||
}
|
||||
|
||||
usrp_rx_stub::~usrp_rx_stub()
|
||||
{
|
||||
if(d_disk_write)
|
||||
d_ofile.close();
|
||||
}
|
||||
|
||||
void
|
||||
usrp_rx_stub::initial_transition()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
usrp_rx_stub::handle_message(mb_message_sptr msg)
|
||||
{
|
||||
pmt_t event = msg->signal();
|
||||
pmt_t port_id = msg->port_id();
|
||||
pmt_t data = msg->data();
|
||||
|
||||
if (pmt_eq(msg->signal(), s_timeout)
|
||||
&& !pmt_eq(msg->data(), s_done)) {
|
||||
|
||||
if(!usrp_rx_stop_stub)
|
||||
read_and_respond();
|
||||
else { // requested to stop
|
||||
cancel_timeout(msg->metadata());
|
||||
usrp_rx_stop_stub=false;
|
||||
if(verbose)
|
||||
std::cout << "[USRP_RX_STUB] Stopping RX stub\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Theoretically only have 1 message to ever expect, but
|
||||
// want to make sure its at least what we want
|
||||
if(pmt_eq(port_id, d_cs->port_symbol())
|
||||
&& pmt_eqv(event, s_cmd_usrp_rx_start_reading)) {
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[USRP_RX_STUB] Starting with decim @ "
|
||||
<< d_decim_rx << std::endl;
|
||||
|
||||
start_packet_timer();
|
||||
}
|
||||
}
|
||||
|
||||
// Setup a periodic timer which will drive packet generation
|
||||
void
|
||||
usrp_rx_stub::start_packet_timer()
|
||||
{
|
||||
d_t0 = mb_time::time(); // current time
|
||||
|
||||
// Calculate the inter-packet arrival time.
|
||||
double samples_per_sec = (64.0/(double)d_decim_rx)*1000000.0;
|
||||
double frames_per_sec = samples_per_sec / (double)d_samples_per_frame;
|
||||
double frame_rate = 1.0 / frames_per_sec;
|
||||
|
||||
if(verbose) {
|
||||
std::cout << "[USRP_RX_STUB] Scheduling periodic packet generator\n";
|
||||
std::cout << "\tsamples_per_sec: " << samples_per_sec << std::endl;
|
||||
std::cout << "\tframes_per_sec: " << frames_per_sec << std::endl;
|
||||
std::cout << "\tframe_rate: " << frame_rate << std::endl;
|
||||
}
|
||||
|
||||
schedule_periodic_timeout(d_t0 + frame_rate, mb_time(frame_rate), PMT_T);
|
||||
}
|
||||
|
||||
void
|
||||
usrp_rx_stub::read_and_respond()
|
||||
{
|
||||
|
||||
long nsamples_this_frame = d_samples_per_frame;
|
||||
|
||||
size_t nshorts = 2 * nsamples_this_frame; // 16-bit I & Q
|
||||
long channel = 0;
|
||||
long n_bytes = nshorts*2;
|
||||
pmt_t uvec = pmt_make_s16vector(nshorts, 0);
|
||||
size_t ignore;
|
||||
int16_t *samples = pmt_s16vector_writable_elements(uvec, ignore);
|
||||
|
||||
// fill in the complex sinusoid
|
||||
|
||||
for (int i = 0; i < nsamples_this_frame; i++){
|
||||
|
||||
if (1){
|
||||
gr_complex s;
|
||||
d_nco.sincos(&s, 1, d_amplitude);
|
||||
// write 16-bit i & q
|
||||
samples[2*i] = (int16_t) s.real();
|
||||
samples[2*i+1] = (int16_t) s.imag();
|
||||
}
|
||||
else {
|
||||
gr_complex s(d_amplitude, d_amplitude);
|
||||
|
||||
// write 16-bit i & q
|
||||
samples[2*i] = (int16_t) s.real();
|
||||
samples[2*i+1] = (int16_t) s.imag();
|
||||
}
|
||||
}
|
||||
|
||||
if(d_disk_write)
|
||||
d_ofile.write((const char *)samples, n_bytes);
|
||||
|
||||
pmt_t v_pkt = pmt_make_u8vector(sizeof(transport_pkt), 0);
|
||||
transport_pkt *pkt =
|
||||
(transport_pkt *) pmt_u8vector_writable_elements(v_pkt, ignore);
|
||||
|
||||
pkt->set_header(0, channel, 0, n_bytes);
|
||||
pkt->set_timestamp(0xffffffff);
|
||||
memcpy(pkt->payload(), samples, n_bytes);
|
||||
|
||||
d_cs->send(s_response_usrp_rx_read, pmt_list3(PMT_NIL, PMT_T, v_pkt));
|
||||
|
||||
// Now lets check the shared CS queue between the TX and RX stub. Each
|
||||
// element in a queue is a list where the first element is an invocation
|
||||
// handle and the second element is a PMT u8 vect representation of the
|
||||
// CS packet response which can just be passed transparently.
|
||||
while(!d_cs_queue.empty()) {
|
||||
|
||||
pmt_t cs_pkt = d_cs_queue.front();
|
||||
d_cs_queue.pop();
|
||||
|
||||
pmt_t invocation_handle = pmt_nth(0, cs_pkt);
|
||||
pmt_t v_pkt = pmt_nth(1, cs_pkt);
|
||||
|
||||
d_cs->send(s_response_usrp_rx_read,
|
||||
pmt_list3(invocation_handle,
|
||||
PMT_T,
|
||||
v_pkt)); // Take the front CS pkt
|
||||
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[USRP_RX_STUB] Received CS response from TX stub\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
REGISTER_MBLOCK_CLASS(usrp_rx_stub);
|
|
@ -1,79 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007,2008 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#ifndef INCLUDED_USRP_RX_STUB_H
|
||||
#define INCLUDED_USRP_RX_STUB_H
|
||||
|
||||
#include <mblock/mblock.h>
|
||||
#include <vector>
|
||||
#include "usrp_standard.h"
|
||||
#include <ui_nco.h>
|
||||
#include <fstream>
|
||||
#include <queue>
|
||||
#include <usrp_inband_usb_packet.h>
|
||||
|
||||
typedef usrp_inband_usb_packet transport_pkt;
|
||||
|
||||
extern bool usrp_rx_stop_stub; // used to communicate a 'stop' to the RX stub
|
||||
extern std::queue<pmt_t> d_cs_queue;
|
||||
|
||||
static pmt_t s_timeout = pmt_intern("%timeout");
|
||||
static pmt_t s_done = pmt_intern("done");
|
||||
|
||||
/*!
|
||||
* \brief Implements the low level usb interface to the USRP
|
||||
*/
|
||||
class usrp_rx_stub : public mb_mblock
|
||||
{
|
||||
public:
|
||||
|
||||
mb_port_sptr d_cs;
|
||||
usrp_standard_rx* d_urx;
|
||||
|
||||
long d_samples_per_frame;
|
||||
long d_decim_rx;
|
||||
|
||||
mb_time d_t0;
|
||||
double d_delta_t;
|
||||
|
||||
// for generating sine wave output
|
||||
ui_nco<float,float> d_nco;
|
||||
double d_amplitude;
|
||||
|
||||
bool d_disk_write;
|
||||
|
||||
std::ofstream d_ofile;
|
||||
|
||||
public:
|
||||
usrp_rx_stub(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
|
||||
~usrp_rx_stub();
|
||||
void initial_transition();
|
||||
void handle_message(mb_message_sptr msg);
|
||||
|
||||
private:
|
||||
void read_and_respond();
|
||||
void read_data();
|
||||
void start_packet_timer();
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif /* INCLUDED_USRP_RX_H */
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,131 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007,2008 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#ifndef INCLUDED_USRP_SERVER_H
|
||||
#define INCLUDED_USRP_SERVER_H
|
||||
|
||||
#include <mblock/mblock.h>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <fstream>
|
||||
#include <usrp_inband_usb_packet.h>
|
||||
|
||||
typedef usrp_inband_usb_packet transport_pkt; // makes conversion to gigabit easy
|
||||
|
||||
/*!
|
||||
* \brief Implements the lowest-level mblock usb_interface to the USRP
|
||||
*/
|
||||
class usrp_server : public mb_mblock
|
||||
{
|
||||
public:
|
||||
|
||||
// our ports
|
||||
enum port_types {
|
||||
RX_PORT = 0,
|
||||
TX_PORT = 1
|
||||
};
|
||||
static const int N_PORTS = 4;
|
||||
std::vector<mb_port_sptr> d_tx, d_rx;
|
||||
mb_port_sptr d_cs;
|
||||
mb_port_sptr d_cs_usrp;
|
||||
|
||||
static const int D_USB_CAPACITY = 32 * 1024 * 1024;
|
||||
static const int D_MAX_CHANNELS = 16;
|
||||
long d_ntx_chan;
|
||||
long d_nrx_chan;
|
||||
|
||||
pmt_t d_usrp_dict;
|
||||
|
||||
bool d_fpga_debug;
|
||||
|
||||
long d_interp_tx;
|
||||
long d_decim_rx;
|
||||
|
||||
// Keep track of the request IDs
|
||||
struct rid_info {
|
||||
pmt_t owner;
|
||||
long user_rid;
|
||||
|
||||
rid_info() {
|
||||
owner = PMT_NIL;
|
||||
user_rid = 0;
|
||||
}
|
||||
};
|
||||
|
||||
static const long D_MAX_RID = 64;
|
||||
std::vector<rid_info> d_rids;
|
||||
|
||||
struct channel_info {
|
||||
long assigned_capacity; // the capacity currently assignedby the channel
|
||||
pmt_t owner; // port ID of the owner of the channel
|
||||
|
||||
channel_info() {
|
||||
assigned_capacity = 0;
|
||||
owner = PMT_NIL;
|
||||
}
|
||||
};
|
||||
|
||||
long d_rx_chan_mask; // A bitmask representing the channels in the
|
||||
// receiving state
|
||||
|
||||
std::vector<struct channel_info> d_chaninfo_tx;
|
||||
std::vector<struct channel_info> d_chaninfo_rx;
|
||||
|
||||
std::queue<mb_message_sptr> d_defer_queue;
|
||||
|
||||
bool d_defer;
|
||||
bool d_opened;
|
||||
|
||||
bool d_fake_rx;
|
||||
|
||||
public:
|
||||
usrp_server(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
|
||||
~usrp_server();
|
||||
|
||||
void initial_transition();
|
||||
void handle_message(mb_message_sptr msg);
|
||||
|
||||
protected:
|
||||
static int max_capacity() { return D_USB_CAPACITY; }
|
||||
|
||||
private:
|
||||
void handle_cmd_allocate_channel(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data);
|
||||
void handle_cmd_deallocate_channel(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data);
|
||||
void handle_cmd_xmit_raw_frame(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data);
|
||||
void handle_cmd_to_control_channel(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data);
|
||||
void handle_cmd_start_recv_raw_samples(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data);
|
||||
void handle_cmd_stop_recv_raw_samples(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data);
|
||||
int rx_port_index(pmt_t port_id);
|
||||
int tx_port_index(pmt_t port_id);
|
||||
long current_capacity_allocation();
|
||||
void recall_defer_queue();
|
||||
void reset_channels();
|
||||
void handle_response_usrp_read(pmt_t data);
|
||||
bool check_valid(mb_port_sptr port, long channel, std::vector<struct channel_info> &chan_info, pmt_t signal_info);
|
||||
void parse_control_pkt(pmt_t invocation_handle, transport_pkt *pkt);
|
||||
long next_rid();
|
||||
void initialize_registers();
|
||||
void set_register(long reg, long val);
|
||||
void read_register(long reg);
|
||||
void check_register_initialization();
|
||||
void reset_all_registers();
|
||||
};
|
||||
|
||||
#endif /* INCLUDED_USRP_SERVER_H */
|
|
@ -1,255 +0,0 @@
|
|||
;; -*- scheme -*- ; not really, but tells emacs how to format this
|
||||
;;
|
||||
;; Copyright 2007 Free Software Foundation, Inc.
|
||||
;;
|
||||
;; This file is part of GNU Radio
|
||||
;;
|
||||
;; GNU Radio is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation; either version 3, or (at your option)
|
||||
;; any later version.
|
||||
;;
|
||||
;; GNU Radio is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
;;
|
||||
;; You should have received a copy of the GNU General Public License along
|
||||
;; with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
;; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
;;
|
||||
|
||||
;; ----------------------------------------------------------------
|
||||
;; This is an mblock header file
|
||||
;;
|
||||
;; The format is very much a work-in-progress.
|
||||
;; It'll be compiled to C++.
|
||||
;; ----------------------------------------------------------------
|
||||
|
||||
;; In the outgoing messages described below, invocation-handle is an
|
||||
;; identifier provided by the client to tag the method invocation.
|
||||
;; The identifier will be returned with the response, to provide the
|
||||
;; client with a mechanism to match asynchronous responses with the
|
||||
;; commands that generate them. The value of the invocation-handle is
|
||||
;; opaque the the server, and is not required by the server to be
|
||||
;; unique.
|
||||
;;
|
||||
;; In the incoming messages described below, invocation-handle is the
|
||||
;; identifier provided by the client in the prompting invocation. The
|
||||
;; identifier is returned with the response, so that the client has a
|
||||
;; mechanism to match asynchronous responses with the commands that
|
||||
;; generated them.
|
||||
;;
|
||||
;; status is either #t, indicating success, or a symbol indicating an error.
|
||||
;; All symbol's names shall begin with %error-
|
||||
|
||||
|
||||
;; ----------------------------------------------------------------
|
||||
;; usrp-channel
|
||||
;;
|
||||
;; The protocol class is defined from the client's point-of-view.
|
||||
;; (The client port is unconjugated, the server port is conjugated.)
|
||||
|
||||
(define-protocol-class usrp-channel
|
||||
|
||||
(:outgoing
|
||||
|
||||
(cmd-allocate-channel invocation-handle capacity-reservation)
|
||||
|
||||
;; The cmd-allocate-channel message requests that the server
|
||||
;; allocates a logical channel in the FPGA for use.
|
||||
;; capacity-reservation specifies the number of bytes/s of
|
||||
;; interconnect capacity (USB or ethernet) to reserve for this
|
||||
;; channel. (The reservation is just a sanity check, no OS
|
||||
;; specific mechanism is used.)
|
||||
|
||||
(cmd-deallocate-channel invocation-handle channel)
|
||||
|
||||
;; The integer channel specifies the channel to deallocate.
|
||||
|
||||
)
|
||||
|
||||
(:incoming
|
||||
|
||||
|
||||
(response-allocate-channel invocation-handle status channel)
|
||||
|
||||
;; If successful, a channel the specified capacity was allocated.
|
||||
;; channel, an integer, indicates which channel was allocated.
|
||||
|
||||
(response-deallocate-channel invocation-handle status)
|
||||
|
||||
;; If successful, the specified channel and associated interconnect
|
||||
;; capacity were deallocated.
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
;; ----------------------------------------------------------------
|
||||
;; usrp-low-level-cs
|
||||
;;
|
||||
;; The protocol class is defined from the client's point-of-view.
|
||||
;; (The client port is unconjugated, the server port is conjugated.)
|
||||
;;
|
||||
;; This defines a low level control and status interface to the usrp.
|
||||
;; This will probably be replaced (or at least augmented) with a
|
||||
;; higher level interface. For now, this will allow us to get on
|
||||
;; the air.
|
||||
;;
|
||||
;; The subpackets are lists containing the relevant parameters. The
|
||||
;; server will marshall them appropriately. Below is a list of
|
||||
;; subpackets. See inband-signaling-usb for details. The opcodes are
|
||||
;; symbols; unless otherwise indicated the remaining parameters are
|
||||
;; integers. rid values are limited to 3-bits.
|
||||
;;
|
||||
;; (op-ping-fixed rid ping-value)
|
||||
;; (op-ping-fixed-reply rid ping-value)
|
||||
;; (op-write-reg reg-number reg-value)
|
||||
;; (op-write-reg-masked reg-number reg-value mask-value)
|
||||
;; (op-read-reg rid reg-number)
|
||||
;; (op-read-reg-reply rid reg-number reg-value)
|
||||
;; (op-i2c-write i2c-addr u8-vec)
|
||||
;; (op-i2c-read rid i2c-addr nbytes)
|
||||
;; (op-i2c-read-reply rid i2c-addr u8-vec)
|
||||
;; (op-spi-write enables format opt-header-bytes u8-vec)
|
||||
;; (op-spi-read rid enables format opt-header-bytes nbytes)
|
||||
;; (op-spi-read-reply rid u8-vec)
|
||||
;; (op-delay ticks)
|
||||
|
||||
|
||||
(define-protocol-class usrp-low-level-cs
|
||||
|
||||
(:outgoing
|
||||
|
||||
(cmd-to-control-channel invocation-handle list-of-subpackets)
|
||||
|
||||
)
|
||||
|
||||
(:incoming
|
||||
|
||||
(response-from-control-channel invocation-handle status list-of-subpackets timestamp)
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
;; ----------------------------------------------------------------
|
||||
;; usrp-tx
|
||||
;;
|
||||
;; The protocol class is defined from the client's point-of-view.
|
||||
;; (The client port is unconjugated, the server port is conjugated.)
|
||||
|
||||
(define-protocol-class usrp-tx
|
||||
(:include usrp-channel)
|
||||
(:include usrp-low-level-cs)
|
||||
|
||||
(:outgoing
|
||||
|
||||
(cmd-xmit-raw-frame invocation-handle channel samples timestamp properties)
|
||||
|
||||
;; The argument channel must be an integer. It specifies the
|
||||
;; channel on which the frame of samples will be be sent.
|
||||
;;
|
||||
;; samples must be a uniform numeric vector. The contents of the
|
||||
;; sample vector is treated as opaque and is passed on to the FPGA
|
||||
;; unmodified. It is the responsibility of the sender to ensure
|
||||
;; that the binary format is sensible for the current FPGA
|
||||
;; configuration.
|
||||
;;
|
||||
;; timestamp is a 32-bit integer that specifies the time at which
|
||||
;; the first sample in samples shall be sent to the D/A converter.
|
||||
;; The format and interpration of time is specified in the file
|
||||
;; inband-signaling-usb
|
||||
)
|
||||
|
||||
(:incoming
|
||||
|
||||
(response-xmit-raw-frame invocation-handle status)
|
||||
|
||||
;; If successful, the samples of the associated frame have been
|
||||
;; transmitted to the USRP. This message may be used to implement
|
||||
;; Tx flow control. The client could for example implement a
|
||||
;; policy of never having more than 4 unacknowledged
|
||||
;; cmd-xmit-raw-frame's outstanding.
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
;; ----------------------------------------------------------------
|
||||
;; usrp-rx
|
||||
;;
|
||||
;; The protocol class is defined from the client's point-of-view.
|
||||
;; (The client port is unconjugated, the server port is conjugated.)
|
||||
|
||||
(define-protocol-class usrp-rx
|
||||
(:include usrp-channel)
|
||||
(:include usrp-low-level-cs)
|
||||
|
||||
(:outgoing
|
||||
|
||||
(cmd-start-recv-raw-samples invocation-handle channel)
|
||||
|
||||
;; The argument channel must be an integer. It specifies the
|
||||
;; channel from which frames of samples will be be received. The
|
||||
;; server will return response-recv-raw-samples messages until a
|
||||
;; cmd-stop-recv-raw-samples message is received.
|
||||
|
||||
(cmd-stop-recv-raw-samples invocation-handle channel)
|
||||
|
||||
;; The argument channel must be an integer. There is no reply to
|
||||
;; this message.
|
||||
|
||||
)
|
||||
|
||||
(:incoming
|
||||
|
||||
(response-recv-raw-samples invocation-handle status samples timestamp channel properties)
|
||||
|
||||
;; samples is a uniform numeric vector. The contents of the sample
|
||||
;; vector is treated as opaque and is passed from the FPGA
|
||||
;; unmodified. It is the responsibility of the receiver to decode
|
||||
;; the binary format as appropriate for the current FPGA
|
||||
;; configuration.
|
||||
;;
|
||||
;; timestamp is a 32-bit integer that specifies the time at which
|
||||
;; the first sample in samples was received from the A/D converter.
|
||||
;; The format and interpretation of time is as specified in the
|
||||
;; file inband-signaling-usb.
|
||||
;;
|
||||
;; properties is a dictionary containing additional (key, value)
|
||||
;; pairs associated with the reception of these samples. In
|
||||
;; particular, the map may contain the Received Signal Strength
|
||||
;; Indication (RSSI) reported by the front end at the time the
|
||||
;; first sample was received from the A/D.
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
;; ----------------------------------------------------------------
|
||||
;; usrp-server-cs
|
||||
;;
|
||||
;; Control and status port for usrp-server
|
||||
;;
|
||||
;; The protocol class is defined from the client's point-of-view.
|
||||
;; (The client port is unconjugated, the server port is conjugated.)
|
||||
|
||||
(define-protocol-class usrp-server-cs
|
||||
|
||||
(:outgoing
|
||||
(cmd-open invocation-handle which-usrp)
|
||||
(cmd-close invocation-handle)
|
||||
(cmd-max-capacity invocation-handle)
|
||||
(cmd-ntx-chan invocation-handle)
|
||||
(cmd-nrx-chan invocation-handle)
|
||||
(cmd-current-capacity-allocation invocation-handle)
|
||||
)
|
||||
|
||||
(:incoming
|
||||
(response-open invocation-handle status)
|
||||
(response-close invocation-handle status)
|
||||
(response-max-capacity invocation-handle status capacity)
|
||||
(response-ntx-chan invocation-handle status ntx-chan)
|
||||
(response-nrx-chan invocation-handle status nrx-chan)
|
||||
(response-current-capacity-allocation invocation-handle status capacity)
|
||||
)
|
||||
)
|
|
@ -1,150 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007,2008 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <usrp_tx.h>
|
||||
#include <iostream>
|
||||
#include <usb.h>
|
||||
#include <mblock/class_registry.h>
|
||||
#include <usrp_inband_usb_packet.h>
|
||||
#include <fpga_regs_common.h>
|
||||
#include <usrp_standard.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <symbols_usrp_tx_cs.h>
|
||||
|
||||
typedef usrp_inband_usb_packet transport_pkt;
|
||||
|
||||
static const bool verbose = false;
|
||||
|
||||
usrp_tx::usrp_tx(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg)
|
||||
: mb_mblock(rt, instance_name, user_arg),
|
||||
d_disk_write(false)
|
||||
{
|
||||
d_cs = define_port("cs", "usrp-tx-cs", true, mb_port::EXTERNAL);
|
||||
|
||||
//d_disk_write=true;
|
||||
|
||||
if(d_disk_write) {
|
||||
d_ofile.open("tx_data.dat",std::ios::binary|std::ios::out);
|
||||
d_cs_ofile.open("tx_cs.dat",std::ios::binary|std::ios::out);
|
||||
}
|
||||
}
|
||||
|
||||
usrp_tx::~usrp_tx()
|
||||
{
|
||||
if(d_disk_write) {
|
||||
d_ofile.close();
|
||||
d_cs_ofile.close();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
usrp_tx::initial_transition()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Handles incoming signals to to the m-block, wihch should only ever be
|
||||
* a single message: cmd-usrp-tx-write.
|
||||
*/
|
||||
void
|
||||
usrp_tx::handle_message(mb_message_sptr msg)
|
||||
{
|
||||
pmt_t event = msg->signal();
|
||||
pmt_t port_id = msg->port_id();
|
||||
pmt_t data = msg->data();
|
||||
|
||||
// Theoretically only have 1 message to ever expect, but
|
||||
// want to make sure its at least what we want
|
||||
if(pmt_eq(port_id, d_cs->port_symbol())) {
|
||||
|
||||
if(pmt_eqv(event, s_cmd_usrp_tx_write))
|
||||
write(data);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Performs the actual writing of data to the USB bus, called by
|
||||
* handle_message() when a cmd-usrp-tx-write signal is received.
|
||||
*
|
||||
* The \p data parameter is a PMT list which contains three mandatory elements,
|
||||
* in the following order: an invocation handle, a channel, and a uniform vector
|
||||
* of memory which contains the packets to be written to the bus.
|
||||
*/
|
||||
void
|
||||
usrp_tx::write(pmt_t data)
|
||||
{
|
||||
pmt_t invocation_handle = pmt_nth(0, data);
|
||||
pmt_t channel = pmt_nth(1, data);
|
||||
pmt_t v_packets = pmt_nth(2, data);
|
||||
d_utx = boost::any_cast<usrp_standard_tx_sptr>(pmt_any_ref(pmt_nth(3, data)));
|
||||
|
||||
size_t n_bytes;
|
||||
bool underrun; // this will need to go, as it is taken care of in the packet headers
|
||||
|
||||
transport_pkt *pkts = (transport_pkt *) pmt_u8vector_writable_elements(v_packets, n_bytes);
|
||||
|
||||
int ret = d_utx->write (pkts, n_bytes, &underrun);
|
||||
|
||||
if (0 && underrun)
|
||||
fprintf(stderr, "uU");
|
||||
|
||||
if (ret == (int) n_bytes) {
|
||||
if (verbose)
|
||||
std::cout << "[usrp_server] Write of " << n_bytes << " successful\n";
|
||||
// need to respond with the channel so the USRP server knows who to forward the result of
|
||||
// the write to by looking up the owner of the channel
|
||||
d_cs->send(s_response_usrp_tx_write,
|
||||
pmt_list3(invocation_handle, PMT_T, channel));
|
||||
}
|
||||
else {
|
||||
if (verbose)
|
||||
std::cout << "[usrp_server] Error writing " << n_bytes << " bytes to USB bus\n";
|
||||
d_cs->send(s_response_usrp_tx_write,
|
||||
pmt_list3(invocation_handle, PMT_F, channel));
|
||||
}
|
||||
|
||||
long n_packets =
|
||||
static_cast<long>(std::ceil(n_bytes / (double)transport_pkt::max_pkt_size()));
|
||||
|
||||
for(int i=0; i < n_packets; i++) {
|
||||
|
||||
if(d_disk_write) {
|
||||
if(pkts[i].chan() == CONTROL_CHAN)
|
||||
d_cs_ofile.write((const char *)&pkts[i], transport_pkt::max_pkt_size());
|
||||
else
|
||||
d_ofile.write((const char *)&pkts[i], transport_pkt::max_pkt_size());
|
||||
|
||||
d_cs_ofile.flush();
|
||||
d_ofile.flush();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
REGISTER_MBLOCK_CLASS(usrp_tx);
|
|
@ -1,52 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007,2008 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#ifndef INCLUDED_USRP_TX_H
|
||||
#define INCLUDED_USRP_TX_H
|
||||
|
||||
#include <mblock/mblock.h>
|
||||
#include <fstream>
|
||||
#include "usrp_standard.h"
|
||||
|
||||
/*!
|
||||
* \brief Implements the low level usb interface to the USRP
|
||||
*/
|
||||
class usrp_tx : public mb_mblock
|
||||
{
|
||||
mb_port_sptr d_cs;
|
||||
usrp_standard_tx_sptr d_utx;
|
||||
|
||||
bool d_disk_write;
|
||||
std::ofstream d_ofile;
|
||||
std::ofstream d_cs_ofile;
|
||||
|
||||
public:
|
||||
usrp_tx(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
|
||||
~usrp_tx();
|
||||
void initial_transition();
|
||||
void handle_message(mb_message_sptr msg);
|
||||
|
||||
private:
|
||||
void write(pmt_t data);
|
||||
};
|
||||
|
||||
|
||||
#endif /* INCLUDED_USRP_TX_H */
|
||||
|
|
@ -1,344 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007,2008 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <usb.h>
|
||||
#include <mblock/class_registry.h>
|
||||
#include <usrp_tx_stub.h>
|
||||
#include <usrp_inband_usb_packet.h>
|
||||
#include <fpga_regs_common.h>
|
||||
#include "usrp_standard.h"
|
||||
#include <stdio.h>
|
||||
#include <fstream>
|
||||
#include <usrp_rx_stub.h>
|
||||
|
||||
#include <symbols_usrp_tx_cs.h>
|
||||
|
||||
typedef usrp_inband_usb_packet transport_pkt;
|
||||
|
||||
static const bool verbose = false;
|
||||
|
||||
usrp_tx_stub::usrp_tx_stub(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg)
|
||||
: mb_mblock(rt, instance_name, user_arg),
|
||||
d_disk_write(false)
|
||||
{
|
||||
d_cs = define_port("cs", "usrp-tx-cs", true, mb_port::EXTERNAL);
|
||||
|
||||
//d_disk_write=true;
|
||||
|
||||
if(d_disk_write) {
|
||||
d_ofile.open("tx_stub_data.dat",std::ios::binary|std::ios::out);
|
||||
d_cs_ofile.open("tx_stub_cs.dat",std::ios::binary|std::ios::out);
|
||||
}
|
||||
}
|
||||
|
||||
usrp_tx_stub::~usrp_tx_stub()
|
||||
{
|
||||
if(d_disk_write) {
|
||||
d_ofile.close();
|
||||
d_cs_ofile.close();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
usrp_tx_stub::initial_transition()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
usrp_tx_stub::handle_message(mb_message_sptr msg)
|
||||
{
|
||||
pmt_t event = msg->signal();
|
||||
pmt_t port_id = msg->port_id();
|
||||
pmt_t data = msg->data();
|
||||
|
||||
// Theoretically only have 1 message to ever expect, but
|
||||
// want to make sure its at least what we want
|
||||
if(pmt_eq(port_id, d_cs->port_symbol())) {
|
||||
|
||||
if(pmt_eqv(event, s_cmd_usrp_tx_write))
|
||||
write(data);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
usrp_tx_stub::write(pmt_t data)
|
||||
{
|
||||
pmt_t invocation_handle = pmt_nth(0, data);
|
||||
pmt_t channel = pmt_nth(1, data);
|
||||
pmt_t v_packets = pmt_nth(2, data);
|
||||
d_utx = boost::any_cast<usrp_standard_tx *>(pmt_any_ref(pmt_nth(3, data)));
|
||||
|
||||
size_t n_bytes;
|
||||
|
||||
transport_pkt *pkts = (transport_pkt *) pmt_u8vector_writable_elements(v_packets, n_bytes);
|
||||
long n_packets = static_cast<long>(std::ceil(n_bytes / (double)transport_pkt::max_pkt_size()));
|
||||
|
||||
// Parse the packets looking for C/S packets and dump them to a disk if
|
||||
// necessary
|
||||
for(long i=0; i<n_packets; i++) {
|
||||
|
||||
if(d_disk_write) {
|
||||
if(pkts[i].chan() == CONTROL_CHAN)
|
||||
d_cs_ofile.write((const char *)&pkts[i], transport_pkt::max_pkt_size());
|
||||
else
|
||||
d_ofile.write((const char *)&pkts[i], transport_pkt::max_pkt_size());
|
||||
|
||||
d_cs_ofile.flush();
|
||||
d_ofile.flush();
|
||||
}
|
||||
|
||||
if(pkts[i].chan() == CONTROL_CHAN)
|
||||
parse_cs(invocation_handle, pkts[i]);
|
||||
}
|
||||
|
||||
d_cs->send(s_response_usrp_tx_write,
|
||||
pmt_list3(invocation_handle, PMT_T, channel));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
usrp_tx_stub::parse_cs(pmt_t invocation_handle, transport_pkt pkt)
|
||||
{
|
||||
|
||||
long payload_len = pkt.payload_len();
|
||||
long curr_payload = 0;
|
||||
|
||||
size_t ignore;
|
||||
|
||||
// There is the possibility that the responses for a single USB packet full of
|
||||
// CS packets will not fit back in a single USB packet, considering some
|
||||
// responses are greater than their commands (read registers).
|
||||
new_packet:
|
||||
pmt_t v_pkt = pmt_make_u8vector(sizeof(transport_pkt), 0);
|
||||
|
||||
transport_pkt *q_pkt =
|
||||
(transport_pkt *) pmt_u8vector_writable_elements(v_pkt, ignore);
|
||||
|
||||
q_pkt->set_header(0, CONTROL_CHAN, 0, 0);
|
||||
q_pkt->set_timestamp(0xffffffff);
|
||||
|
||||
// We dispatch based on the control packet type, however we can extract the
|
||||
// opcode and the length immediately which is consistent in all responses.
|
||||
//
|
||||
// Since each control packet can have multiple responses, we keep reading the
|
||||
// lengths of each subpacket until we reach the payload length.
|
||||
while(curr_payload < payload_len) {
|
||||
|
||||
pmt_t sub_packet = pkt.read_subpacket(curr_payload);
|
||||
pmt_t op_symbol = pmt_nth(0, sub_packet);
|
||||
|
||||
int len = pkt.cs_len(curr_payload);
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[USRP_TX_STUB] Parsing subpacket "
|
||||
<< op_symbol << " ... length " << len << std::endl;
|
||||
|
||||
//----------------- PING FIXED ------------------//
|
||||
if(pmt_eq(op_symbol, s_op_ping_fixed)) {
|
||||
|
||||
long rid = pmt_to_long(pmt_nth(1, sub_packet));
|
||||
long pingval = pmt_to_long(pmt_nth(2, sub_packet));
|
||||
|
||||
// Generate a reply and put it in the queue for the RX stub to read
|
||||
if(!q_pkt->cs_ping_reply(rid, pingval))
|
||||
goto new_packet;
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[USRP_TX_STUB] Generated ping response "
|
||||
<< "("
|
||||
<< "RID: " << rid << ", "
|
||||
<< "VAL: " << pingval
|
||||
<< ")\n";
|
||||
}
|
||||
|
||||
//----------------- READ REG ------------------//
|
||||
if(pmt_eq(op_symbol, s_op_read_reg)) {
|
||||
|
||||
long rid = pmt_to_long(pmt_nth(1, sub_packet));
|
||||
long reg_num = pmt_to_long(pmt_nth(2, sub_packet));
|
||||
long reg_val = 0xdeef;
|
||||
|
||||
// Generate a reply and put it in the queue for the RX stub to read
|
||||
if(!q_pkt->cs_read_reg_reply(rid, reg_num, reg_val))
|
||||
goto new_packet;
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[USRP_TX_STUB] Generated read register response "
|
||||
<< "("
|
||||
<< "RID: " << rid << ", "
|
||||
<< "REG: " << reg_num << ", "
|
||||
<< "VAL: " << reg_val
|
||||
<< ")\n";
|
||||
}
|
||||
|
||||
//----------------- DELAY ------------------//
|
||||
if(pmt_eq(op_symbol, s_op_delay)) {
|
||||
|
||||
long ticks = pmt_to_long(pmt_nth(1, sub_packet));
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[USRP_TX_STUB] Received delay command "
|
||||
<< "("
|
||||
<< "Ticks: " << ticks
|
||||
<< ")\n";
|
||||
}
|
||||
|
||||
//----------------- WRITE REG ------------------//
|
||||
if(pmt_eq(op_symbol, s_op_write_reg)) {
|
||||
|
||||
pmt_t reg_num = pmt_nth(1, sub_packet);
|
||||
pmt_t reg_val = pmt_nth(2, sub_packet);
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[USRP_TX_STUB] Received write register command "
|
||||
<< "("
|
||||
<< "RegNum: " << reg_num << ", "
|
||||
<< "Val: " << reg_val
|
||||
<< ")\n";
|
||||
}
|
||||
|
||||
//----------------- WRITE REG MASK ---------------//
|
||||
if(pmt_eq(op_symbol, s_op_write_reg_masked)) {
|
||||
|
||||
pmt_t reg_num = pmt_nth(1, sub_packet);
|
||||
pmt_t reg_val = pmt_nth(2, sub_packet);
|
||||
pmt_t mask = pmt_nth(3, sub_packet);
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[USRP_TX_STUB] Received write register command "
|
||||
<< "("
|
||||
<< "RegNum: " << reg_num << ", "
|
||||
<< "Val: " << reg_val << ", "
|
||||
<< "Mask: " << mask
|
||||
<< ")\n";
|
||||
}
|
||||
|
||||
//---------------- I2C WRITE ------------------//
|
||||
if(pmt_eq(op_symbol, s_op_i2c_write)) {
|
||||
pmt_t i2c_addr = pmt_nth(1, sub_packet);
|
||||
pmt_t i2c_data = pmt_nth(2, sub_packet);
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[USRP_TX_STUB] Received i2c write command "
|
||||
<< "("
|
||||
<< "Addr: " << i2c_addr << ", "
|
||||
<< "Data: " << i2c_data
|
||||
<< ")\n";
|
||||
}
|
||||
|
||||
//---------------- I2C READ ------------------//
|
||||
if(pmt_eq(op_symbol, s_op_i2c_read)) {
|
||||
long rid = pmt_to_long(pmt_nth(1, sub_packet));
|
||||
long i2c_addr = pmt_to_long(pmt_nth(2, sub_packet));
|
||||
long i2c_bytes = pmt_to_long(pmt_nth(3, sub_packet));
|
||||
|
||||
// Create data to place as a response, filled with 0xff
|
||||
size_t ignore;
|
||||
pmt_t i2c_data = pmt_make_u8vector(i2c_bytes, 0xff);
|
||||
uint8_t *w_data = (uint8_t *) pmt_u8vector_writable_elements(i2c_data, ignore);
|
||||
|
||||
// Generate a reply and put it in the queue for the RX stub to read
|
||||
if(!q_pkt->cs_i2c_read_reply(rid, i2c_addr, w_data, i2c_bytes))
|
||||
goto new_packet;
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[USRP_TX_STUB] Received i2c read "
|
||||
<< "("
|
||||
<< "RID: " << rid << ", "
|
||||
<< "Addr: " << i2c_addr << ", "
|
||||
<< "Bytes: " << i2c_bytes
|
||||
<< ")\n";
|
||||
}
|
||||
|
||||
//---------------- SPI WRITE ------------------//
|
||||
if(pmt_eq(op_symbol, s_op_spi_write)) {
|
||||
long enables = pmt_to_long(pmt_nth(1, sub_packet));
|
||||
long format = pmt_to_long(pmt_nth(2, sub_packet));
|
||||
long opt = pmt_to_long(pmt_nth(3, sub_packet));
|
||||
pmt_t data = pmt_nth(4, sub_packet);
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[USRP_TX_STUB] Received spi write command "
|
||||
<< "("
|
||||
<< "Enables: " << enables << ", "
|
||||
<< "Format: " << format << ", "
|
||||
<< "Options: " << opt << ", "
|
||||
<< "Data: " << data
|
||||
<< ")\n";
|
||||
}
|
||||
|
||||
//---------------- SPI READ ------------------//
|
||||
if(pmt_eq(op_symbol, s_op_spi_read)) {
|
||||
long rid = pmt_to_long(pmt_nth(1, sub_packet));
|
||||
long enables = pmt_to_long(pmt_nth(2, sub_packet));
|
||||
long format = pmt_to_long(pmt_nth(3, sub_packet));
|
||||
long opt = pmt_to_long(pmt_nth(4, sub_packet));
|
||||
long n_bytes = pmt_to_long(pmt_nth(5, sub_packet));
|
||||
|
||||
// Create data to place as a fake response
|
||||
size_t ignore;
|
||||
pmt_t spi_data = pmt_make_u8vector(n_bytes, 0xff);
|
||||
uint8_t *w_data = (uint8_t *) pmt_u8vector_writable_elements(spi_data, ignore);
|
||||
|
||||
// Generate a reply and put it in the queue for the RX stub to read
|
||||
if(!q_pkt->cs_spi_read_reply(rid, w_data, n_bytes))
|
||||
goto new_packet;
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[USRP_TX_STUB] Received spi read command "
|
||||
<< "("
|
||||
<< "RID: " << rid << ", "
|
||||
<< "Enables: " << enables << ", "
|
||||
<< "Format: " << format << ", "
|
||||
<< "Options: " << opt << ", "
|
||||
<< "Bytes: " << n_bytes
|
||||
<< ")\n";
|
||||
|
||||
}
|
||||
|
||||
// Each subpacket has an unaccounted for 2 bytes which is the opcode
|
||||
// and the length field
|
||||
curr_payload += len + 2;
|
||||
|
||||
// All subpackets are 32-bit aligned
|
||||
int align_offset = 4 - (curr_payload % 4);
|
||||
|
||||
if(align_offset != 4)
|
||||
curr_payload += align_offset;
|
||||
|
||||
}
|
||||
|
||||
// If the packet has data in the payload, it needs queued
|
||||
if(q_pkt->payload_len() > 0)
|
||||
d_cs_queue.push(pmt_list2(invocation_handle, v_pkt));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
REGISTER_MBLOCK_CLASS(usrp_tx_stub);
|
|
@ -1,61 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007,2008 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#ifndef INCLUDED_USRP_TX_STUB_H
|
||||
#define INCLUDED_USRP_TX_STUB_H
|
||||
|
||||
#include <mblock/mblock.h>
|
||||
#include <vector>
|
||||
#include "usrp_standard.h"
|
||||
#include <fstream>
|
||||
#include <usrp_inband_usb_packet.h>
|
||||
|
||||
typedef usrp_inband_usb_packet transport_pkt;
|
||||
|
||||
/*!
|
||||
* \brief Implements the low level usb interface to the USRP
|
||||
*/
|
||||
class usrp_tx_stub : public mb_mblock
|
||||
{
|
||||
public:
|
||||
|
||||
mb_port_sptr d_cs;
|
||||
usrp_standard_tx* d_utx;
|
||||
|
||||
std::ofstream d_ofile;
|
||||
std::ofstream d_cs_ofile;
|
||||
|
||||
bool d_disk_write;
|
||||
|
||||
public:
|
||||
usrp_tx_stub(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
|
||||
~usrp_tx_stub();
|
||||
void initial_transition();
|
||||
void handle_message(mb_message_sptr msg);
|
||||
|
||||
private:
|
||||
void write(pmt_t data);
|
||||
void parse_cs(pmt_t invocation_handle, transport_pkt pkt);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif /* INCLUDED_USRP_TX_STUB_H */
|
||||
|
|
@ -1,601 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007,2008,2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <usrp_usb_interface.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <usb.h>
|
||||
#include <mblock/class_registry.h>
|
||||
#include <usrp_inband_usb_packet.h>
|
||||
#include <fpga_regs_common.h>
|
||||
#include "usrp_rx.h"
|
||||
#include <usrp_rx_stub.h>
|
||||
#include "usrp_tx.h"
|
||||
#include "usrp_standard.h"
|
||||
#include <stdio.h>
|
||||
#include <usrp_dbid.h>
|
||||
|
||||
typedef usrp_inband_usb_packet transport_pkt;
|
||||
|
||||
#include <symbols_usrp_interface_cs.h>
|
||||
#include <symbols_usrp_tx_cs.h>
|
||||
#include <symbols_usrp_rx_cs.h>
|
||||
static pmt_t s_shutdown = pmt_intern("%shutdown");
|
||||
|
||||
static const bool verbose = false;
|
||||
|
||||
|
||||
/*!
|
||||
* \brief Initializes the USB interface m-block.
|
||||
*
|
||||
* The \p user_arg should be a PMT dictionary which can contain optional
|
||||
* arguments for the block, such as the decimatoin and interpolation rate.
|
||||
*/
|
||||
usrp_usb_interface::usrp_usb_interface(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg)
|
||||
: mb_mblock(rt, instance_name, user_arg),
|
||||
d_fake_usrp(false),
|
||||
d_rx_reading(false),
|
||||
d_interp_tx(128),
|
||||
d_decim_rx(128),
|
||||
d_rf_freq(-1),
|
||||
d_rbf("inband_tx_rx.rbf")
|
||||
{
|
||||
// Dictionary for arguments to all of the components
|
||||
pmt_t usrp_dict = user_arg;
|
||||
|
||||
// Default TX/RX interface
|
||||
std::string tx_interface = "usrp_tx";
|
||||
std::string rx_interface = "usrp_rx";
|
||||
|
||||
if (pmt_is_dict(usrp_dict)) {
|
||||
|
||||
// The 'fake-usrp' key enables the TX and RX stubs if PMT_T
|
||||
if(pmt_t fake_usrp = pmt_dict_ref(usrp_dict,
|
||||
pmt_intern("fake-usrp"),
|
||||
PMT_NIL)) {
|
||||
if(pmt_eqv(fake_usrp, PMT_T)) {
|
||||
tx_interface = "usrp_tx_stub";
|
||||
rx_interface = "usrp_rx_stub";
|
||||
d_fake_usrp=true;
|
||||
}
|
||||
}
|
||||
|
||||
// Read the TX interpolations
|
||||
if(pmt_t interp_tx = pmt_dict_ref(usrp_dict,
|
||||
pmt_intern("interp-tx"),
|
||||
PMT_NIL)) {
|
||||
if(!pmt_eqv(interp_tx, PMT_NIL))
|
||||
d_interp_tx = pmt_to_long(interp_tx);
|
||||
}
|
||||
|
||||
// Read the RX decimation rate
|
||||
if(pmt_t decim_rx = pmt_dict_ref(usrp_dict,
|
||||
pmt_intern("decim-rx"),
|
||||
PMT_NIL)) {
|
||||
if(!pmt_eqv(decim_rx, PMT_NIL))
|
||||
d_decim_rx = pmt_to_long(decim_rx);
|
||||
}
|
||||
|
||||
// Read the RBF
|
||||
if(pmt_t rbf = pmt_dict_ref(usrp_dict,
|
||||
pmt_intern("rbf"),
|
||||
PMT_NIL)) {
|
||||
if(!pmt_eqv(rbf, PMT_NIL))
|
||||
d_rbf = pmt_symbol_to_string(rbf);
|
||||
}
|
||||
|
||||
// The RF center frequency
|
||||
if(pmt_t rf_freq = pmt_dict_ref(usrp_dict,
|
||||
pmt_intern("rf-freq"),
|
||||
PMT_NIL)) {
|
||||
if(!pmt_eqv(rf_freq, PMT_NIL))
|
||||
d_rf_freq = pmt_to_double(rf_freq);
|
||||
}
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
std::cout << "[USRP_USB_INTERFACE] Setting USRP RBF to "
|
||||
<< d_rbf << std::endl;
|
||||
|
||||
std::cout << "[USRP_USB_INTERFACE] Setting TX interpolation to "
|
||||
<< d_interp_tx << std::endl;
|
||||
|
||||
std::cout << "[USRP_USB_INTERFACE] Setting RX interpolation to "
|
||||
<< d_decim_rx << std::endl;
|
||||
|
||||
std::cout << "[USRP_USB_INTERFACE] Using TX interface: "
|
||||
<< tx_interface << "\n";
|
||||
|
||||
std::cout << "[USRP_USB_INTERFACE] Using RX interface: "
|
||||
<< rx_interface << "\n";
|
||||
|
||||
}
|
||||
|
||||
d_cs = define_port("cs", "usrp-interface-cs", true, mb_port::EXTERNAL);
|
||||
d_rx_cs = define_port("rx_cs", "usrp-rx-cs", false, mb_port::INTERNAL);
|
||||
d_tx_cs = define_port("tx_cs", "usrp-tx-cs", false, mb_port::INTERNAL);
|
||||
|
||||
// Connect to TX and RX
|
||||
define_component("tx", tx_interface, usrp_dict);
|
||||
define_component("rx", rx_interface, usrp_dict);
|
||||
connect("self", "rx_cs", "rx", "cs");
|
||||
connect("self", "tx_cs", "tx", "cs");
|
||||
|
||||
// FIXME: the code should query the FPGA to retrieve the number of channels and such
|
||||
d_ntx_chan = 2;
|
||||
d_nrx_chan = 2;
|
||||
}
|
||||
|
||||
usrp_usb_interface::~usrp_usb_interface()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
usrp_usb_interface::initial_transition()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Handles all incoming signals to the block from the lowest m-blocks
|
||||
* which read/write to the bus, or the higher m-block which is the USRP server.
|
||||
*/
|
||||
void
|
||||
usrp_usb_interface::handle_message(mb_message_sptr msg)
|
||||
{
|
||||
pmt_t event = msg->signal(); // the "name" of the message
|
||||
pmt_t port_id = msg->port_id(); // which port it came in on
|
||||
pmt_t data = msg->data();
|
||||
pmt_t invocation_handle;
|
||||
|
||||
if (pmt_eq(event, s_shutdown)) // ignore (for now)
|
||||
return;
|
||||
|
||||
//------------- CONTROL / STATUS -------------//
|
||||
if (pmt_eq(port_id, d_cs->port_symbol())) {
|
||||
|
||||
//------------ OPEN --------------//
|
||||
if (pmt_eq(event, s_cmd_usrp_open)){
|
||||
handle_cmd_open(data);
|
||||
return;
|
||||
}
|
||||
//----------- CLOSE -------------//
|
||||
else if (pmt_eq(event, s_cmd_usrp_close)) {
|
||||
handle_cmd_close(data);
|
||||
return;
|
||||
}
|
||||
//---------- NTX CHAN ----------//
|
||||
else if (pmt_eq(event, s_cmd_usrp_ntx_chan)) {
|
||||
invocation_handle = pmt_nth(0, data);
|
||||
d_cs->send(s_response_usrp_ntx_chan,
|
||||
pmt_list2(invocation_handle,
|
||||
pmt_from_long(d_ntx_chan)));
|
||||
return;
|
||||
}
|
||||
//---------- NRX CHAN ----------//
|
||||
else if (pmt_eq(event, s_cmd_usrp_nrx_chan)) {
|
||||
invocation_handle = pmt_nth(0, data);
|
||||
d_cs->send(s_response_usrp_nrx_chan,
|
||||
pmt_list2(invocation_handle,
|
||||
pmt_from_long(d_nrx_chan)));
|
||||
return;
|
||||
}
|
||||
//------------ WRITE -----------//
|
||||
else if(pmt_eq(event, s_cmd_usrp_write)) {
|
||||
handle_cmd_write(data);
|
||||
return;
|
||||
}
|
||||
//-------- START READING --------//
|
||||
else if(pmt_eq(event, s_cmd_usrp_start_reading)) {
|
||||
handle_cmd_start_reading(data);
|
||||
return;
|
||||
}
|
||||
//-------- STOP READING --------//
|
||||
else if(pmt_eq(event, s_cmd_usrp_stop_reading)) {
|
||||
handle_cmd_stop_reading(data);
|
||||
return;
|
||||
}
|
||||
|
||||
goto unhandled;
|
||||
}
|
||||
|
||||
//---------------- RX ------------------//
|
||||
if (pmt_eq(port_id, d_rx_cs->port_symbol())) {
|
||||
|
||||
// Relay reads back up
|
||||
if(pmt_eq(event, s_response_usrp_rx_read)) {
|
||||
d_cs->send(s_response_usrp_read, data);
|
||||
return;
|
||||
}
|
||||
|
||||
goto unhandled;
|
||||
}
|
||||
|
||||
//---------------- TX ------------------//
|
||||
if (pmt_eq(port_id, d_tx_cs->port_symbol())) {
|
||||
|
||||
if(pmt_eq(event, s_response_usrp_tx_write)) {
|
||||
|
||||
pmt_t invocation_handle = pmt_nth(0, data);
|
||||
pmt_t status = pmt_nth(1, data);
|
||||
pmt_t channel = pmt_nth(2, data);
|
||||
|
||||
d_cs->send(s_response_usrp_write,
|
||||
pmt_list3(invocation_handle,
|
||||
status,
|
||||
channel));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
goto unhandled;
|
||||
}
|
||||
|
||||
unhandled:
|
||||
std::cout << "[USRP_USB_INTERFACE] unhandled msg: " << msg << std::endl;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Called by the handle_message() method when the incoming signal is to
|
||||
* open a USB connection to the USRP (cmd-usrp-open).
|
||||
*
|
||||
* The \p data parameter is a PMT list, where the elements are an invocation
|
||||
* handle and the USRP number.
|
||||
*/
|
||||
void
|
||||
usrp_usb_interface::handle_cmd_open(pmt_t data)
|
||||
{
|
||||
pmt_t invocation_handle = pmt_nth(0, data);
|
||||
long which_usrp = pmt_to_long(pmt_nth(1, data));
|
||||
pmt_t reply_data;
|
||||
|
||||
if(d_fake_usrp) {
|
||||
d_cs->send(s_response_usrp_open, pmt_list2(invocation_handle, PMT_T));
|
||||
return;
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
std::cout << "[USRP_USB_INTERFACE] Handling open request for USRP " << which_usrp << "\n";
|
||||
|
||||
// Open up a standard RX and TX for communication with the USRP
|
||||
|
||||
d_utx = usrp_standard_tx::make(which_usrp,
|
||||
d_interp_tx,
|
||||
1, // 1 channel
|
||||
-1, // mux
|
||||
4096, // USB block size
|
||||
16, // nblocks for async transfers
|
||||
d_rbf
|
||||
);
|
||||
|
||||
if(d_utx==0) {
|
||||
if (verbose)
|
||||
std::cout << "[USRP_USB_INTERFACE] Failed to open TX\n";
|
||||
reply_data = pmt_list2(invocation_handle, PMT_F);
|
||||
d_cs->send(s_response_usrp_open, reply_data);
|
||||
return;
|
||||
}
|
||||
|
||||
// Perform TX daughterboard tuning
|
||||
double target_freq;
|
||||
unsigned int mux;
|
||||
int tgain, rgain;
|
||||
float input_rate;
|
||||
bool ok;
|
||||
usrp_tune_result r;
|
||||
|
||||
// Cast to usrp_basic and then detect daughterboards
|
||||
d_ub_tx = d_utx;
|
||||
usrp_subdev_spec tspec = pick_tx_subdevice();
|
||||
db_base_sptr tsubdev = d_ub_tx->selected_subdev(tspec);
|
||||
|
||||
// Set the TX mux value
|
||||
mux = d_utx->determine_tx_mux_value(tspec);
|
||||
d_utx->set_mux(mux);
|
||||
|
||||
// Set the TX gain and determine rate
|
||||
tgain = tsubdev->gain_max();
|
||||
tsubdev->set_gain(tgain);
|
||||
input_rate = d_ub_tx->converter_rate() / d_utx->interp_rate();
|
||||
|
||||
// Perform the actual tuning, if no frequency specified then pick
|
||||
if(d_rf_freq==-1)
|
||||
target_freq = tsubdev->freq_min()+((tsubdev->freq_max()-tsubdev->freq_min())/2.0);
|
||||
else
|
||||
target_freq = d_rf_freq;
|
||||
ok = d_utx->tune(tsubdev->which(), tsubdev, target_freq, &r);
|
||||
tsubdev->set_enable(true);
|
||||
|
||||
if(verbose) {
|
||||
printf("TX Subdevice name is %s\n", tsubdev->name().c_str());
|
||||
printf("TX Subdevice freq range: (%g, %g)\n",
|
||||
tsubdev->freq_min(), tsubdev->freq_max());
|
||||
printf("mux: %#08x\n", mux);
|
||||
printf("target_freq: %f\n", target_freq);
|
||||
printf("ok: %s\n", ok ? "true" : "false");
|
||||
printf("gain: %d\n", tgain);
|
||||
printf("r.baseband_freq: %f\n", r.baseband_freq);
|
||||
printf("r.dxc_freq: %f\n", r.dxc_freq);
|
||||
printf("r.residual_freq: %f\n", r.residual_freq);
|
||||
printf("r.inverted: %d\n", r.inverted);
|
||||
}
|
||||
|
||||
if(!ok) {
|
||||
std::cerr << "[USRP_USB_INTERFACE] Failed to set center frequency on TX\n";
|
||||
reply_data = pmt_list2(invocation_handle, PMT_F);
|
||||
d_cs->send(s_response_usrp_open, reply_data);
|
||||
return;
|
||||
}
|
||||
|
||||
d_utx->start();
|
||||
|
||||
if (verbose)
|
||||
std::cout << "[USRP_USB_INTERFACE] Setup TX channel\n";
|
||||
|
||||
d_urx =
|
||||
usrp_standard_rx::make (which_usrp,
|
||||
d_decim_rx,
|
||||
1, // nchan
|
||||
-1, // mux
|
||||
0, // set blank mode to start
|
||||
4096, // USB block size
|
||||
16, // number of blocks for async transfers
|
||||
d_rbf);
|
||||
|
||||
if(!d_urx) {
|
||||
if (verbose)
|
||||
std::cout << "[usrp_server] Failed to open RX\n";
|
||||
reply_data = pmt_list2(invocation_handle, PMT_F);
|
||||
d_cs->send(s_response_usrp_open, reply_data);
|
||||
return;
|
||||
}
|
||||
|
||||
// Cast to usrp_basic and then detect daughterboards
|
||||
d_ub_rx = d_urx;
|
||||
usrp_subdev_spec rspec = pick_rx_subdevice();
|
||||
db_base_sptr rsubdev = d_ub_rx->selected_subdev(rspec);
|
||||
|
||||
// Set the RX mux value
|
||||
mux = d_urx->determine_rx_mux_value(rspec);
|
||||
d_urx->set_mux(mux);
|
||||
|
||||
// Set the RX gain and determine rate
|
||||
rgain = rsubdev->gain_max()/2.0;
|
||||
rsubdev->set_gain(rgain);
|
||||
input_rate = d_ub_rx->converter_rate() / d_urx->decim_rate();
|
||||
|
||||
ok = d_urx->tune(rsubdev->which(), rsubdev, target_freq, &r);
|
||||
rsubdev->set_enable(true);
|
||||
|
||||
if(verbose) {
|
||||
printf("RX Subdevice name is %s\n", rsubdev->name().c_str());
|
||||
printf("RX Subdevice freq range: (%g, %g)\n",
|
||||
rsubdev->freq_min(), rsubdev->freq_max());
|
||||
printf("mux: %#08x\n", mux);
|
||||
printf("target_freq: %f\n", target_freq);
|
||||
printf("ok: %s\n", ok ? "true" : "false");
|
||||
printf("gain: %d\n", rgain);
|
||||
printf("r.baseband_freq: %f\n", r.baseband_freq);
|
||||
printf("r.dxc_freq: %f\n", r.dxc_freq);
|
||||
printf("r.residual_freq: %f\n", r.residual_freq);
|
||||
printf("r.inverted: %d\n", r.inverted);
|
||||
}
|
||||
|
||||
if(!ok) {
|
||||
std::cerr << "[USRP_USB_INTERFACE] Failed to set center frequency on RX\n";
|
||||
reply_data = pmt_list2(invocation_handle, PMT_F);
|
||||
d_cs->send(s_response_usrp_open, reply_data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
std::cout << "[USRP_USB_INTERFACE] Setup RX channel\n";
|
||||
|
||||
// d_utx->_write_fpga_reg(FR_DEBUG_EN,0xf);
|
||||
// d_utx->_write_oe(0, 0xffff, 0xffff);
|
||||
// d_urx->_write_oe(0, 0xffff, 0xffff);
|
||||
// d_utx->_write_oe(1, 0xffff, 0xffff);
|
||||
// d_urx->_write_oe(1, 0xffff, 0xffff);
|
||||
|
||||
d_cs->send(s_response_usrp_open, pmt_list2(invocation_handle, PMT_T));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Called by the handle_message() method when the incoming signal is to
|
||||
* write data to the USB bus (cmd-usrp-write).
|
||||
*
|
||||
* The \p data parameter is a PMT list containing 3 mandatory elements in the
|
||||
* following order: an invocation handle, channel, and a uniform vector
|
||||
* representation of the packets.
|
||||
*/
|
||||
void
|
||||
usrp_usb_interface::handle_cmd_write(pmt_t data)
|
||||
{
|
||||
pmt_t invocation_handle = pmt_nth(0, data);
|
||||
pmt_t channel = pmt_nth(1, data);
|
||||
pmt_t pkts = pmt_nth(2, data);
|
||||
|
||||
pmt_t tx_handle = pmt_make_any(d_utx);
|
||||
|
||||
d_tx_cs->send(s_cmd_usrp_tx_write,
|
||||
pmt_list4(invocation_handle,
|
||||
channel,
|
||||
pkts,
|
||||
tx_handle));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Called by the handle_message() method when the incoming signal is to
|
||||
* start reading data from the USB bus (cmd-usrp-start-reading).
|
||||
*
|
||||
* The \p data parameter is a PMT list with a single element: an invocation
|
||||
* handle which can be returned with the response.
|
||||
*/
|
||||
void
|
||||
usrp_usb_interface::handle_cmd_start_reading(pmt_t data)
|
||||
{
|
||||
pmt_t invocation_handle = pmt_nth(0, data);
|
||||
|
||||
if(verbose)
|
||||
std::cout << "[USRP_USB_INTERFACE] Starting RX...\n";
|
||||
|
||||
if(!d_fake_usrp)
|
||||
d_urx->start();
|
||||
|
||||
pmt_t rx_handle = pmt_make_any(d_urx);
|
||||
|
||||
d_rx_cs->send(s_cmd_usrp_rx_start_reading, pmt_list2(PMT_NIL, rx_handle));
|
||||
|
||||
d_rx_reading = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Called by the handle_message() method when the incoming signal is to
|
||||
* stop reading data from the USB bus (cmd-usrp-stop-reading).
|
||||
*
|
||||
* The \p data parameter is a PMT list with a single element: an invocation
|
||||
* handle which can be returned with the response.
|
||||
*/
|
||||
void
|
||||
usrp_usb_interface::handle_cmd_stop_reading(pmt_t data)
|
||||
{
|
||||
pmt_t invocation_handle = pmt_nth(0, data);
|
||||
|
||||
if(!d_fake_usrp) {
|
||||
if(verbose)
|
||||
std::cout << "[USRP_USB_INTERFACE] Stopping RX...\n";
|
||||
usrp_rx_stop = true;
|
||||
|
||||
// Used to allow a read() being called by a lower layer to complete before
|
||||
// stopping, else there can be partial data left on the bus and can generate
|
||||
// errors.
|
||||
while(usrp_rx_stop) {usleep(1);}
|
||||
d_urx->stop();
|
||||
}
|
||||
else {
|
||||
if(verbose)
|
||||
std::cout << "[USRP_USB_INTERFACE] Stopping fake RX...\n";
|
||||
usrp_rx_stop_stub = true; // extern to communicate with stub to wait
|
||||
}
|
||||
|
||||
d_rx_reading = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Called by the handle_message() method when the incoming signal is to
|
||||
* close the USB connection to the USRP.
|
||||
*
|
||||
* The \p data parameter is a PMT list with a single element: an invocation
|
||||
* handle which can be returned with the response.
|
||||
*/
|
||||
void
|
||||
usrp_usb_interface::handle_cmd_close(pmt_t data)
|
||||
{
|
||||
pmt_t invocation_handle = pmt_nth(0, data);
|
||||
|
||||
if(d_rx_reading)
|
||||
handle_cmd_stop_reading(PMT_NIL);
|
||||
|
||||
if(d_fake_usrp) {
|
||||
d_cs->send(s_response_usrp_close, pmt_list2(invocation_handle, PMT_T));
|
||||
return;
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
std::cout << "[USRP_USB_INTERFACE] Handling close request for USRP\n";
|
||||
|
||||
d_utx.reset();
|
||||
d_urx.reset();
|
||||
|
||||
d_cs->send(s_response_usrp_close, pmt_list2(invocation_handle, PMT_T));
|
||||
|
||||
// FIXME This seems like a _very_ strange place to be calling shutdown_all.
|
||||
// That decision should be left to high-level code, not low-level code like this.
|
||||
shutdown_all(PMT_T);
|
||||
}
|
||||
|
||||
usrp_subdev_spec
|
||||
usrp_usb_interface::pick_rx_subdevice()
|
||||
{
|
||||
int dbids[] = {
|
||||
USRP_DBID_FLEX_400_RX,
|
||||
USRP_DBID_FLEX_900_RX,
|
||||
USRP_DBID_FLEX_1200_RX,
|
||||
USRP_DBID_FLEX_2400_RX,
|
||||
USRP_DBID_TV_RX,
|
||||
USRP_DBID_TV_RX_REV_2,
|
||||
USRP_DBID_DBS_RX,
|
||||
USRP_DBID_BASIC_RX
|
||||
};
|
||||
|
||||
std::vector<int> candidates(dbids, dbids+(sizeof(dbids)/sizeof(int)));
|
||||
return pick_subdev(d_ub_rx, candidates);
|
||||
}
|
||||
|
||||
usrp_subdev_spec
|
||||
usrp_usb_interface::pick_tx_subdevice()
|
||||
{
|
||||
int dbids[] = {
|
||||
USRP_DBID_FLEX_400_TX,
|
||||
USRP_DBID_FLEX_900_TX,
|
||||
USRP_DBID_FLEX_1200_TX,
|
||||
USRP_DBID_FLEX_2400_TX,
|
||||
USRP_DBID_BASIC_TX
|
||||
};
|
||||
|
||||
std::vector<int> candidates(dbids, dbids+(sizeof(dbids)/sizeof(int)));
|
||||
return pick_subdev(d_ub_tx, candidates);
|
||||
}
|
||||
|
||||
usrp_subdev_spec
|
||||
usrp_usb_interface::pick_subdev(boost::shared_ptr<usrp_basic> d_usrp_basic, std::vector<int> candidates)
|
||||
{
|
||||
int dbid0 = d_usrp_basic->selected_subdev(usrp_subdev_spec(0, 0))->dbid();
|
||||
int dbid1 = d_usrp_basic->selected_subdev(usrp_subdev_spec(1, 0))->dbid();
|
||||
|
||||
for (int i = 0; i < candidates.size(); i++) {
|
||||
int dbid = candidates[i];
|
||||
if (dbid0 == dbid)
|
||||
return usrp_subdev_spec(0, 0);
|
||||
if (dbid1 == dbid)
|
||||
return usrp_subdev_spec(1, 0);
|
||||
}
|
||||
|
||||
if (dbid0 >= 0)
|
||||
return usrp_subdev_spec(0, 0);
|
||||
if (dbid1 >= 0)
|
||||
return usrp_subdev_spec(1, 0);
|
||||
|
||||
throw std::runtime_error("No suitable daughterboard found!");
|
||||
}
|
||||
|
||||
|
||||
REGISTER_MBLOCK_CLASS(usrp_usb_interface);
|
|
@ -1,78 +0,0 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2007,2008 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#ifndef INCLUDED_USRP_USB_INTERFACE_H
|
||||
#define INCLUDED_USRP_USB_INTERFACE_H
|
||||
|
||||
#include <mblock/mblock.h>
|
||||
#include <vector>
|
||||
#include "usrp_standard.h"
|
||||
|
||||
/*!
|
||||
* \brief Implements the low level usb interface to the USRP
|
||||
*/
|
||||
class usrp_usb_interface : public mb_mblock
|
||||
{
|
||||
public:
|
||||
|
||||
usrp_standard_tx_sptr d_utx;
|
||||
usrp_standard_rx_sptr d_urx;
|
||||
|
||||
boost::shared_ptr<usrp_basic> d_ub_tx;
|
||||
boost::shared_ptr<usrp_basic> d_ub_rx;
|
||||
|
||||
mb_port_sptr d_cs;
|
||||
mb_port_sptr d_rx_cs;
|
||||
mb_port_sptr d_tx_cs;
|
||||
|
||||
long d_ntx_chan;
|
||||
long d_nrx_chan;
|
||||
|
||||
bool d_fake_usrp;
|
||||
|
||||
bool d_rx_reading;
|
||||
|
||||
long d_interp_tx;
|
||||
long d_decim_rx;
|
||||
|
||||
double d_rf_freq;
|
||||
|
||||
std::string d_rbf;
|
||||
|
||||
public:
|
||||
usrp_usb_interface(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
|
||||
~usrp_usb_interface();
|
||||
void initial_transition();
|
||||
void handle_message(mb_message_sptr msg);
|
||||
usrp_subdev_spec pick_rx_subdevice();
|
||||
usrp_subdev_spec pick_tx_subdevice();
|
||||
usrp_subdev_spec pick_subdev(boost::shared_ptr<usrp_basic> d_usrp_basic, std::vector<int> candidates);
|
||||
|
||||
private:
|
||||
void handle_cmd_open(pmt_t data);
|
||||
void handle_cmd_close(pmt_t data);
|
||||
void handle_cmd_write(pmt_t data);
|
||||
void handle_cmd_start_reading(pmt_t data);
|
||||
void handle_cmd_stop_reading(pmt_t data);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif /* INCLUDED_USRP_USB_INTERFACE_H */
|
Loading…
Reference in New Issue