summaryrefslogtreecommitdiff
path: root/usrp/host
diff options
context:
space:
mode:
Diffstat (limited to 'usrp/host')
-rw-r--r--usrp/host/apps-inband/Makefile.am31
-rw-r--r--usrp/host/apps-inband/gmac.cc690
-rw-r--r--usrp/host/apps-inband/gmac.h91
-rw-r--r--usrp/host/apps-inband/gmac.mbh146
-rw-r--r--usrp/host/apps-inband/gmac_symbols.h47
-rw-r--r--usrp/host/apps-inband/test_gmac_tx.cc330
-rw-r--r--usrp/host/apps-inband/test_usrp_inband_2rx.cc371
-rw-r--r--usrp/host/apps-inband/test_usrp_inband_2tx.cc (renamed from usrp/host/apps-inband/test_usrp_inband_cs.cc)212
-rw-r--r--usrp/host/apps-inband/test_usrp_inband_overrun.cc5
-rw-r--r--usrp/host/apps-inband/test_usrp_inband_registers.cc2
-rw-r--r--usrp/host/apps-inband/test_usrp_inband_rx.cc26
-rw-r--r--usrp/host/apps-inband/test_usrp_inband_timestamps.cc2
-rw-r--r--usrp/host/apps-inband/test_usrp_inband_tx.cc83
-rw-r--r--usrp/host/apps-inband/test_usrp_inband_underrun.cc8
-rw-r--r--usrp/host/lib/inband/Makefile.am7
-rw-r--r--usrp/host/lib/inband/fake_usrp.cc135
-rw-r--r--usrp/host/lib/inband/fake_usrp.h43
-rw-r--r--usrp/host/lib/inband/qa_inband_usrp_server.cc239
-rw-r--r--usrp/host/lib/inband/qa_inband_usrp_server.h2
-rw-r--r--usrp/host/lib/inband/test_usrp_inband.cc298
-rw-r--r--usrp/host/lib/inband/usrp_inband_usb_packet.cc235
-rw-r--r--usrp/host/lib/inband/usrp_inband_usb_packet.h5
-rw-r--r--usrp/host/lib/inband/usrp_rx.cc63
-rw-r--r--usrp/host/lib/inband/usrp_rx.h6
-rw-r--r--usrp/host/lib/inband/usrp_rx_stub.cc181
-rw-r--r--usrp/host/lib/inband/usrp_rx_stub.h12
-rw-r--r--usrp/host/lib/inband/usrp_server.cc512
-rw-r--r--usrp/host/lib/inband/usrp_server.h12
-rw-r--r--usrp/host/lib/inband/usrp_server.mbh2
-rw-r--r--usrp/host/lib/inband/usrp_tx.cc14
-rw-r--r--usrp/host/lib/inband/usrp_tx_stub.cc6
-rw-r--r--usrp/host/lib/inband/usrp_usb_interface.cc114
-rw-r--r--usrp/host/lib/inband/usrp_usb_interface.h4
-rw-r--r--usrp/host/lib/legacy/fusb_linux.cc26
34 files changed, 1680 insertions, 2280 deletions
diff --git a/usrp/host/apps-inband/Makefile.am b/usrp/host/apps-inband/Makefile.am
index 86bb40618..f231b57f7 100644
--- a/usrp/host/apps-inband/Makefile.am
+++ b/usrp/host/apps-inband/Makefile.am
@@ -30,46 +30,31 @@ AM_CPPFLAGS = \
bin_PROGRAMS =
noinst_PROGRAMS = \
- test_usrp_inband_cs \
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 \
- test_gmac_tx \
read_packets
noinst_HEADERS = \
ui_nco.h \
- ui_sincos.h \
- gmac.h \
- gmac_symbols.h
+ ui_sincos.h
-EXTRA_DIST = \
- gmac.mbh
-
-#------------------------------------------------------------------
-# Build gmac sources
-
-BUILT_SOURCES = \
- gmac_mbh.cc
-
-gmac_mbh.cc : gmac.mbh
- $(COMPILE_MBH) $(srcdir)/gmac.mbh gmac_mbh.cc
-
-
-test_usrp_inband_cs_SOURCES = test_usrp_inband_cs.cc ui_sincos.c
-test_usrp_inband_cs_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
-
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)
@@ -85,8 +70,8 @@ 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_gmac_tx_SOURCES = test_gmac_tx.cc gmac.cc gmac_mbh.cc ui_sincos.c
-test_gmac_tx_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)
diff --git a/usrp/host/apps-inband/gmac.cc b/usrp/host/apps-inband/gmac.cc
deleted file mode 100644
index 107582e12..000000000
--- a/usrp/host/apps-inband/gmac.cc
+++ /dev/null
@@ -1,690 +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 <gmac.h>
-
-#include <mb_mblock.h>
-#include <mb_runtime.h>
-#include <mb_protocol_class.h>
-#include <mb_exception.h>
-#include <mb_msg_queue.h>
-#include <mb_message.h>
-#include <mb_msg_accepter.h>
-#include <mb_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>
-#include <symbols_usrp_rx.h>
-
-#include <gmac_symbols.h>
-
-static bool verbose = true;
-
-gmac::gmac(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg)
- : mb_mblock(rt, instance_name, user_arg),
- d_us_rx_chan(PMT_NIL), d_us_tx_chan(PMT_NIL)
-{
-
- // When the MAC layer is initialized, we must connect to the USRP and setup
- // channels. We begin by defining ports to connect to the 'usrp_server' block
- // and then initialize the USRP by opening it through the 'usrp_server.'
-
- // Initialize the ports
- define_ports();
-
- // Initialize the connection to the USRP
- initialize_usrp();
-
-}
-
-gmac::~gmac()
-{
-}
-
-// The full functionality of GMAC is based on messages passed back and forth
-// between the application and a physical layer and/or usrp_server. Each
-// message triggers additional events, states, and messages to be sent.
-void gmac::handle_message(mb_message_sptr msg)
-{
-
- // The MAC functionality is dispatched based on the event, which is the
- // driving force of the MAC. The event can be anything from incoming samples
- // to a message to change the carrier sense threshold.
- 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;
-
- switch(d_state) {
-
- //---------------------------- INIT ------------------------------------//
- // In the INIT state, there should be no messages across the ports.
- case INIT:
- error_msg = "no messages should be passed during the INIT state:";
- goto unhandled;
-
- //-------------------------- OPENING USRP -------------------------------//
- // In this state we expect a response from usrp_server over the CS channel
- // as to whether or not the opening of the USRP was successful. If so, we
- // switch states to allocating the channels for use.
- case OPENING_USRP:
-
- if(pmt_eq(event, s_response_open)
- && pmt_eq(d_us_cs->port_symbol(), port_id)) {
-
- status = pmt_nth(1, data); // PMT_T or PMT_F
-
- if(pmt_eq(status, PMT_T)) { // on success, allocate channels!
- allocate_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:
-
- // ************* TX ALLOCATION RESPONSE ***************** //
- if(pmt_eq(event, s_response_allocate_channel)
- && pmt_eq(d_us_tx->port_symbol(), port_id))
- {
- status = pmt_nth(1, data);
-
- if(pmt_eq(status, PMT_T)) { // extract channel on success
- d_us_tx_chan = pmt_nth(2, data);
-
- if(verbose)
- std::cout << "[GMAC] Received TX allocation"
- << " on channel " << d_us_tx_chan << std::endl;
-
- // If the RX has also been allocated already, we can continue
- if(!pmt_eqv(d_us_rx_chan, PMT_NIL)) {
- //enter_receiving();
- initialize_gmac();
- }
-
- return;
- }
- else { // TX allocation failed
- error_msg = "failed to allocate TX channel:";
- goto bail;
- }
- }
-
- // ************* RX ALLOCATION RESPONSE ****************//
- if(pmt_eq(event, s_response_allocate_channel)
- && pmt_eq(d_us_rx->port_symbol(), port_id))
- {
- status = pmt_nth(1, data);
-
- if(pmt_eq(status, PMT_T)) {
-
- d_us_rx_chan = pmt_nth(2, data);
-
- if(verbose)
- std::cout << "[GMAC] Received RX allocation"
- << " on channel " << d_us_rx_chan << std::endl;
-
- // If the TX has also been allocated already, we can continue
- if(!pmt_eqv(d_us_tx_chan, PMT_NIL)) {
- //enter_receiving();
- initialize_gmac();
- }
-
- return;
- }
- else { // RX allocation failed
- error_msg = "failed to allocate RX channel:";
- goto bail;
- }
- }
-
- goto unhandled;
-
- //----------------------------- INIT GMAC --------------------------------//
- // In the INIT_GMAC state, now that the USRP is initialized we can do things
- // like right the carrier sense threshold to the FPGA register.
- case INIT_GMAC:
- goto unhandled;
-
-
- //----------------------------- IDLE ------------------------------------//
- // In the idle state the MAC is not quite 'idle', it is just not doing
- // anything specific. It is still being passive with data between the
- // application and the lower layer.
- case IDLE:
-
- //-------- TX PORT ----------------------------------------------------//
- if(pmt_eq(d_tx->port_symbol(), port_id)) {
-
- //-------- INCOMING PACKET ------------------------------------------//
- if(pmt_eq(event, s_cmd_tx_pkt)) {
- handle_cmd_tx_pkt(data);
- return;
- }
-
- }
-
- //--------- USRP TX PORT ----------------------------------------------//
- if(pmt_eq(d_us_tx->port_symbol(), port_id)) {
-
- //-------- INCOMING PACKET RESPONSE ---------------------------------//
- if(pmt_eq(event, s_response_xmit_raw_frame)) {
- handle_response_xmit_raw_frame(data);
- return;
- }
-
- }
-
- //--------- CS PORT ---------------------------------------------------//
- if(pmt_eq(d_cs->port_symbol(), port_id)) {
-
- //------- ENABLE CARRIER SENSE --------------------------------------//
- if(pmt_eq(event, s_cmd_carrier_sense_enable)) {
- handle_cmd_carrier_sense_enable(data);
- return;
- }
-
- //------- CARRIER SENSE THRESHOLD -----------------------------------//
- if(pmt_eq(event, s_cmd_carrier_sense_threshold)) {
- handle_cmd_carrier_sense_threshold(data);
- return;
- }
-
- //------- CARRIER SENSE DEADLINE ------------------------------------//
- if(pmt_eq(event, s_cmd_carrier_sense_deadline)) {
- handle_cmd_carrier_sense_deadline(data);
- return;
- }
-
- //------- DISABLE CARRIER SENSE -------------------------------------//
- if(pmt_eq(event, s_cmd_carrier_sense_disable)) {
- handle_cmd_carrier_sense_disable(data);
- return;
- }
-
- }
-
- goto unhandled;
-
- //------------------------ CLOSING CHANNELS -----------------------------//
- case CLOSING_CHANNELS:
-
- if (pmt_eq(event, s_response_deallocate_channel)
- && pmt_eq(d_us_tx->port_symbol(), port_id))
- {
- status = pmt_nth(1, data);
-
- if(pmt_eq(status, PMT_T)) {
- d_us_tx_chan = PMT_NIL;
-
- if(verbose)
- std::cout << "[GMAC] Received TX deallocation\n";
-
- // If the RX is also deallocated, we can close the USRP
- if(pmt_eq(d_us_rx_chan, PMT_NIL))
- close_usrp();
-
- return;
-
- } else {
-
- error_msg = "failed to deallocate TX channel:";
- goto bail;
-
- }
- }
-
- if (pmt_eq(event, s_response_deallocate_channel)
- && pmt_eq(d_us_rx->port_symbol(), port_id))
- {
- status = pmt_nth(1, data);
-
- // If successful, set the port to NIL
- if(pmt_eq(status, PMT_T)) {
- d_us_rx_chan = PMT_NIL;
-
- if(verbose)
- std::cout << "[GMAC] Received RX deallocation\n";
-
- // If the TX is also deallocated, we can close the USRP
- if(pmt_eq(d_us_tx_chan, PMT_NIL))
- close_usrp();
-
- return;
-
- } else {
-
- error_msg = "failed to deallocate RX channel:";
- goto bail;
-
- }
- }
-
- goto unhandled;
-
- //-------------------------- CLOSING USRP -------------------------------//
- case CLOSING_USRP:
- 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(0 && verbose && !pmt_eq(event, pmt_intern("%shutdown")))
- std::cout << "[GMAC] unhandled msg: " << msg
- << "in state "<< d_state << std::endl;
-}
-
-// The MAC layer connects to 'usrp_server' which has a control/status channel,
-// a TX, and an RX port. The MAC layer can then relay TX/RX data back and
-// forth to the application, or a physical layer once available.
-void gmac::define_ports()
-{
- // Ports we use to connect to usrp_server
- d_us_tx = define_port("us-tx0", "usrp-tx", false, mb_port::INTERNAL);
- d_us_rx = define_port("us-rx0", "usrp-rx", false, mb_port::INTERNAL);
- d_us_cs = define_port("us-cs", "usrp-server-cs", false, mb_port::INTERNAL);
-
- // Ports applications used to connect to us
- d_tx = define_port("tx0", "gmac-tx", true, mb_port::EXTERNAL);
- d_rx = define_port("rx0", "gmac-rx", true, mb_port::EXTERNAL);
- d_cs = define_port("cs", "gmac-cs", true, mb_port::EXTERNAL);
-}
-
-// To initialize the USRP we must pass several parameters to 'usrp_server' such
-// as the RBF to use, and the interpolation/decimation rate. The MAC layer will
-// then pass these parameters to the block with a message to establish the
-// connection to the USRP.
-void gmac::initialize_usrp()
-{
-
- if(verbose)
- std::cout << "[GMAC] Initializing USRP\n";
-
- // The initialization parameters are passed to usrp_server via a PMT
- // dictionary.
- pmt_t usrp_dict = pmt_make_dict();
-
- // Specify the RBF to use
- pmt_dict_set(usrp_dict,
- pmt_intern("rbf"),
- pmt_intern("test2.rbf"));
-
- 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));
-
- // Center frequency
- pmt_dict_set(usrp_dict,
- pmt_intern("rf-freq"),
- pmt_from_long((long)10e6));
-
- // Default is to use USRP considered '0' (incase of multiple)
- d_which_usrp = pmt_from_long(0);
-
- define_component("USRP-SERVER", "usrp_server", usrp_dict);
-
- connect("self", "us-tx0", "USRP-SERVER", "tx0");
- connect("self", "us-rx0", "USRP-SERVER", "rx0");
- connect("self", "us-cs", "USRP-SERVER", "cs");
-
- // Finally, enter the OPENING_USRP state by sending a request to open the
- // USRP.
- open_usrp();
-
-}
-
-// In the initialization state of the MAC layer we set default values for
-// several functionalities.
-void gmac::initialize_gmac()
-{
-
- // The initial state is the INIT state.
- d_state = INIT_GMAC;
-
- // Set carrier sense to enabled by default with the specified threshold and
- // the deadline to 0 -- which is wait forever.
- set_carrier_sense(true, 25, 0, PMT_NIL);
-
- // Can now notify the application that we are initialized
- d_cs->send(s_response_gmac_initialized,
- pmt_list2(PMT_NIL, PMT_T));
-
- // The MAC enters an IDLE state where it waits for messages and dispatches
- // based on them
- enter_idle();
-}
-
-// Method for setting the carrier sense and an associated threshold which is
-// written to a register on the FPGA, which it will read if the CS flag is set
-// and perform carrier sense based on.
-//
-// We currently do not wait for the successful response for the write to
-// register command, we assume it will succeed else the MAC must
-void gmac::set_carrier_sense(bool toggle, long threshold, long deadline, pmt_t invocation)
-{
- d_carrier_sense = toggle;
-
- // Only waste the bandwidth and processing of a C/S packet if needed
- if(threshold != d_cs_thresh) {
- d_us_tx->send(s_cmd_to_control_channel, // C/S packet
- pmt_list2(invocation, // invoc handle
- pmt_list1(
- pmt_list2(s_op_write_reg,
- pmt_list2(
- pmt_from_long(REG_CS_THRESH),
- pmt_from_long(threshold))))));
- d_cs_thresh = threshold;
-
- if(verbose)
- std::cout << "[GMAC] Changing CS threshold: " << d_cs_thresh << std::endl;
- }
-
- if(deadline != d_cs_deadline) {
- d_us_tx->send(s_cmd_to_control_channel, // C/S packet
- pmt_list2(invocation, // invoc handle
- pmt_list1(
- pmt_list2(s_op_write_reg,
- pmt_list2(
- pmt_from_long(REG_CS_DEADLINE),
- pmt_from_long(deadline))))));
- d_cs_deadline = deadline;
-
- if(verbose)
- std::cout << "[GMAC] Changing CS deadline: " << d_cs_deadline << std::endl;
- }
-
- if(verbose)
- std::cout << "[GMAC] Setting carrier sense to " << toggle << std::endl;
-}
-
-// The following sends a command to open the USRP, which will upload the
-// specified RBF when creating the instance of the USRP server and set all other
-// relevant parameters.
-void gmac::open_usrp()
-{
- d_state = OPENING_USRP;
-
- d_us_cs->send(s_cmd_open, pmt_list2(PMT_NIL, d_which_usrp));
-
- if(verbose)
- std::cout << "[GMAC] Opening USRP "
- << d_which_usrp << std::endl;
-}
-
-// Before sending the close to the USRP we wait a couple seconds to let any data
-// through the USB exit, else a bug in the driver will kick an error and cause
-// an abnormal termination.
-void gmac::close_usrp()
-{
- d_state = CLOSING_USRP;
-
- sleep(2);
-
- d_us_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
-}
-
-// 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 gmac::allocate_channels()
-{
- d_state = ALLOCATING_CHANNELS;
-
- if(verbose)
- std::cout << "[GMAC] Sending channel allocation requests\n";
-
- long capacity = (long) 16e6;
- d_us_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
- d_us_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
-
-}
-
-// Before closing the USRP connection, we deallocate our channels so that the
-// capacity can be reused.
-void gmac::close_channels()
-{
- d_state = CLOSING_CHANNELS;
-
- d_us_tx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_us_tx_chan));
- d_us_rx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_us_rx_chan));
-
- if(verbose)
- std::cout << "[GMAC] Closing channels...\n";
-}
-
-// Used to enter the receiving state
-void gmac::enter_receiving()
-{
- d_us_rx->send(s_cmd_start_recv_raw_samples,
- pmt_list2(PMT_F,
- d_us_rx_chan));
-
- if(verbose)
- std::cout << "[GMAC] Started RX sample stream\n";
-}
-
-// A simple idle state, nothing more to it.
-void gmac::enter_idle()
-{
- d_state = IDLE;
-}
-
-// Handles the transmission of a pkt from the application. The invocation
-// handle is passed on but a response is not given back to the application until
-// the response is passed from usrp_server. This ensures that the MAC passes
-// back the success or failure. Furthermore, the MAC could decide to retransmit
-// on a failure based on the result of the packet transmission.
-//
-// This should eventually be connected to a physically layer rather than
-// directly to usrp_server. (d_us_tx should be replaced with a different
-// connection)
-void gmac::handle_cmd_tx_pkt(pmt_t data)
-{
- pmt_t invocation_handle = pmt_nth(0, data);
- pmt_t dst = pmt_nth(1, data);
- pmt_t samples = pmt_nth(2, data);
- pmt_t pkt_properties = pmt_nth(3, data);
-
- pmt_t us_tx_properties = pmt_make_dict();
-
- // Set the packet to be carrier sensed?
- if(carrier_sense_pkt(pkt_properties))
- pmt_dict_set(us_tx_properties,
- pmt_intern("carrier-sense"),
- PMT_T);
-
- pmt_t timestamp = pmt_from_long(0xffffffff); // NOW
-
- // Construct the proper message for USRP server
- d_us_tx->send(s_cmd_xmit_raw_frame,
- pmt_list5(invocation_handle,
- d_us_tx_chan,
- samples,
- timestamp,
- us_tx_properties));
-
- if(verbose && 0)
- std::cout << "[GMAC] Transmitted packet\n";
-}
-
-// Handles a response from the USRP server about the transmission of a frame,
-// whether it was successful or failed. This should eventually be replaced with
-// a response from the PHY layer. This is where a retransmit could be
-// implemented.
-void gmac::handle_response_xmit_raw_frame(pmt_t data)
-{
- pmt_t invocation_handle = pmt_nth(0, data);
- pmt_t status = pmt_nth(1, data);
-
- d_tx->send(s_response_tx_pkt,
- pmt_list2(invocation_handle,
- status));
-}
-
-// This method determines whether carrier sense should be enabled based on two
-// properties. The first is the MAC setting, which the user can set to carrier
-// sense packets by default or not. The second is a per packet setting, which
-// can be used to override the MAC setting for the given packet only.
-bool gmac::carrier_sense_pkt(pmt_t pkt_properties)
-{
- // First we extract the per packet properties to check the per packet setting
- // if it exists
- if(pmt_is_dict(pkt_properties)) {
-
- if(pmt_t pkt_cs = pmt_dict_ref(pkt_properties,
- pmt_intern("carrier-sense"),
- PMT_NIL)) {
- // If the per packet property says true, enable carrier sense regardless
- // of the MAC setting
- if(pmt_eqv(pkt_cs, PMT_T))
- return true;
- // If the per packet setting says false, disable carrier sense regardless
- // of the MAC setting
- else if(pmt_eqv(pkt_cs, PMT_F))
- return false;
- }
- }
-
- // If we've hit this point, the packet properties did not state whether
- // carrier sense should be used or not, so we use the MAC setting
- if(d_carrier_sense)
- return true;
- else
- return false;
-
-}
-
-// This method is envoked by an incoming cmd-enable-carrier-sense signal on the
-// C/S port. It can be used to re-adjust the threshold or simply enabled
-// carrier sense. When a threshold is not provided, the MAC will use an
-// averaging algorithm to determine the threshold (in the future).
-void gmac::handle_cmd_carrier_sense_enable(pmt_t data)
-{
- pmt_t invocation_handle = pmt_nth(0, data);
- pmt_t threshold = pmt_nth(1, data);
- pmt_t deadline = pmt_nth(2, data);
- long l_threshold, l_deadline;
-
- // FIXME: for now, if threshold is NIL, we do not change the threshold.
- // This should be replaced with an averaging algorithm
- if(pmt_eqv(threshold, PMT_NIL))
- l_threshold = d_cs_thresh;
- else
- l_threshold = pmt_to_long(threshold);
-
- // If the deadline is NIL, we do not change the value
- if(pmt_eqv(threshold, PMT_NIL))
- l_deadline = d_cs_deadline;
- else
- l_deadline = pmt_to_long(deadline);
-
- set_carrier_sense(true, l_threshold, l_deadline, invocation_handle);
-}
-
-// This method is called when an incoming disable carrier sense command is sent
-// over the control status channel. It so far does not ellicit a response, this
-// needs to be added correctly. It needs to wait for the response for the C/S
-// packet from usrp_server.
-void gmac::handle_cmd_carrier_sense_disable(pmt_t data)
-{
- pmt_t invocation_handle = pmt_nth(0, data);
-
- // We don't change the threshold, we leave it as is because the application
- // did not request that it changes, only to disable carrier sense.
- set_carrier_sense(false, d_cs_thresh, d_cs_deadline, invocation_handle);
-}
-
-// When the app requests that the threshold changes, the state of the carrier
-// sense should not change. If it was enabled, it should remain enabled.
-// Likewise if it was disabled. The deadline value should also remain
-// unchanged.
-void gmac::handle_cmd_carrier_sense_threshold(pmt_t data)
-{
- pmt_t invocation_handle = pmt_nth(0, data);
- pmt_t threshold = pmt_nth(1, data);
- long l_threshold;
-
- // FIXME: for now, if threshold is NIL, we do not change the threshold.
- // This should be replaced with an averaging algorithm
- if(pmt_eqv(threshold, PMT_NIL))
- l_threshold = d_cs_thresh;
- else
- l_threshold = pmt_to_long(threshold);
-
- set_carrier_sense(d_carrier_sense, l_threshold, d_cs_deadline, invocation_handle);
-}
-
-// Ability to change the deadline using a C/S packet. The state of all other
-// carrier sense parameters should not change.
-void gmac::handle_cmd_carrier_sense_deadline(pmt_t data)
-{
- pmt_t invocation_handle = pmt_nth(0, data);
- pmt_t deadline = pmt_nth(1, data);
- long l_deadline;
-
- // If the deadline passed is NIL, do *not* change the value.
- if(pmt_eqv(deadline, PMT_NIL))
- l_deadline = d_cs_deadline;
- else
- l_deadline = pmt_to_long(deadline);
-
- set_carrier_sense(d_carrier_sense, d_cs_thresh, l_deadline, invocation_handle);
-}
-
-REGISTER_MBLOCK_CLASS(gmac);
diff --git a/usrp/host/apps-inband/gmac.h b/usrp/host/apps-inband/gmac.h
deleted file mode 100644
index a6d0bcb12..000000000
--- a/usrp/host/apps-inband/gmac.h
+++ /dev/null
@@ -1,91 +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_GMAC_H
-#define INCLUDED_GMAC_H
-
-#include <mb_mblock.h>
-
-class gmac;
-
-class gmac : public mb_mblock
-{
-
- // The state is used to determine how to handle incoming messages and of
- // course, the state of the MAC protocol.
- enum state_t {
- INIT,
- OPENING_USRP,
- ALLOCATING_CHANNELS,
- INIT_GMAC,
- IDLE,
- CLOSING_CHANNELS,
- CLOSING_USRP,
- };
- state_t d_state;
-
- // Ports used for applications to connect to this block
- mb_port_sptr d_tx, d_rx, d_cs;
-
- // Ports to connect to usrp_server (us)
- mb_port_sptr d_us_tx, d_us_rx, d_us_cs;
-
- // The channel numbers assigned for use
- pmt_t d_us_rx_chan, d_us_tx_chan;
-
- pmt_t d_which_usrp;
-
- bool d_carrier_sense;
- long d_cs_thresh;
- long d_cs_deadline;
-
- enum FPGA_REGISTERS {
- REG_CS_THRESH = 1,
- REG_CS_DEADLINE = 2
- };
-
- public:
- gmac(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
- ~gmac();
- void handle_message(mb_message_sptr msg);
-
- private:
- void define_ports();
- void initialize_usrp();
- void initialize_gmac();
- void set_carrier_sense(bool toggle, long threshold, long deadline, pmt_t invocation);
- void allocate_channels();
- void enter_receiving();
- void enter_idle();
- void close_channels();
- void open_usrp();
- void close_usrp();
- void handle_cmd_tx_pkt(pmt_t data);
- void handle_response_xmit_raw_frame(pmt_t data);
- bool carrier_sense_pkt(pmt_t pkt_properties);
- void handle_cmd_carrier_sense_enable(pmt_t data);
- void handle_cmd_carrier_sense_threshold(pmt_t data);
- void handle_cmd_carrier_sense_disable(pmt_t data);
- void handle_cmd_carrier_sense_deadline(pmt_t data);
-
-};
-
-#endif // INCLUDED_GMAC_H
diff --git a/usrp/host/apps-inband/gmac.mbh b/usrp/host/apps-inband/gmac.mbh
deleted file mode 100644
index 4fa9a062f..000000000
--- a/usrp/host/apps-inband/gmac.mbh
+++ /dev/null
@@ -1,146 +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++.
-;; ----------------------------------------------------------------
-
-;; 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-
-
-
-;; ----------------------------------------------------------------
-;; gmac-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 gmac-tx
-
- (:outgoing
-
- ;; Transmitting packets can carry an invocation handle so the application
- ;; can get TX results on specific packets, such as whether a packet tagged
- ;; as #1 was successfully transmitted or not. This would allow the
- ;; application to implement something sliding window like.
- ;;
- ;; 'dst' is the destination MAC address (given a MAC addressing scheme)
- ;;
- ;; 'data' will be treated transparently and passed on as samples.
- ;;
- ;; 'properties' can be used in the future to set per-packet options such as
- ;; carrier sense overriding functionality.
- (cmd-tx-pkt invocation-handle dst data properties)
-
- )
-
- (:incoming
-
- ;; The response will carry the same invocation-handle passed with cmd-tx-pkt
- (response-tx-pkt invocation-handle status)
-
- )
- )
-
-;; ----------------------------------------------------------------
-;; gmac-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 gmac-rx
-
- (:outgoing
-
- ;; There are currently no outgoing commands, I believe that the RX
- ;; should always be enabled, there is no point in having an enable/disable
- ;; that I can see.
-
- )
-
- (:incoming
-
- ;; Contains packets decoded by the MAC destined for this machine, sent by
- ;; the specified address.
- (response-rx-pkt invocation-handle src data)
-
- )
- )
-
-
-;; ----------------------------------------------------------------
-;; gmac-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 control/status interface to the MAC layer, for control over
-;; functionality such as carrier sense and future functionality such as channel
-;; hopping.
-
-
-(define-protocol-class gmac-cs
-
- (:outgoing
-
- ;; Threshold represents the carrier sense threshold based on the digital
- ;; reading out of the DAC. If the threshold is set to PMT_NIL then the
- ;; MAC will use averaging to determine an appropriate threshold.
- (cmd-carrier-sense-enable invocation-handle threshold deadline)
- (cmd-carrier-sense-threshold invocation-handle threshold)
- (cmd-carrier-sense-disable invocation-handle)
-
- ;; Setting the number of fast transmission retries on a failure before
- ;; reporting a loss back to the application.
- (cmd-set-tx-retries invocation-handle retries)
-
- )
-
- (:incoming
-
- (response-gmac-initialized invocation-handle status)
-
- (response-carrier-sense-enable invocation-handle status)
- (response-carrier-sense-threshold invocation-handle status)
- (response-carrier-sense-deadline invocation-handle status)
- (response-carrier-sense-disable invocation-handle status)
-
- (response-set-tx-retries invocation-handle status)
-
- )
- )
diff --git a/usrp/host/apps-inband/gmac_symbols.h b/usrp/host/apps-inband/gmac_symbols.h
deleted file mode 100644
index 0d7804be1..000000000
--- a/usrp/host/apps-inband/gmac_symbols.h
+++ /dev/null
@@ -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_GMAC_SYMBOLS_H
-#define INCLUDED_GMAC_SYMBOLS_H
-
-#include <pmt.h>
-
-// TX
-static pmt_t s_cmd_tx_pkt = pmt_intern("cmd-tx-pkt");
-static pmt_t s_response_tx_pkt = pmt_intern("response-tx-pkt");
-
-// RX
-static pmt_t s_response_rx_pkt = pmt_intern("response-rx-pkt");
-
-// CS
-static pmt_t s_cmd_carrier_sense_enable = pmt_intern("cmd-carrier-sense-enable");
-static pmt_t s_cmd_carrier_sense_threshold = pmt_intern("cmd-carrier-sense-threshold");
-static pmt_t s_cmd_carrier_sense_deadline = pmt_intern("cmd-carrier-sense-deadline");
-static pmt_t s_cmd_carrier_sense_disable = pmt_intern("cmd-carrier-sense-disable");
-static pmt_t s_cmd_set_tx_retries = pmt_intern("cmd-set-tx-retries");
-static pmt_t s_response_gmac_initialized = pmt_intern("response-gmac-initialized");
-static pmt_t s_response_carrier_sense_enable = pmt_intern("response-carrier-sense-enable");
-static pmt_t s_response_carrier_sense_treshold = pmt_intern("response-carrier-sense-threshold");
-static pmt_t s_response_carrier_sense_deadline = pmt_intern("response-carrier-sense-deadline");
-static pmt_t s_response_carrier_sense_disable = pmt_intern("response-carrier-sense-disable");
-static pmt_t s_response_set_tx_retries = pmt_intern("response-set-tx-retries");
-
-#endif // INCLUDED_GMAC_SYMBOLS_H
diff --git a/usrp/host/apps-inband/test_gmac_tx.cc b/usrp/host/apps-inband/test_gmac_tx.cc
deleted file mode 100644
index 74f16c669..000000000
--- a/usrp/host/apps-inband/test_gmac_tx.cc
+++ /dev/null
@@ -1,330 +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 <mb_mblock.h>
-#include <mb_runtime.h>
-#include <mb_protocol_class.h>
-#include <mb_exception.h>
-#include <mb_msg_queue.h>
-#include <mb_message.h>
-#include <mb_msg_accepter.h>
-#include <mb_class_registry.h>
-#include <pmt.h>
-#include <stdio.h>
-#include <string.h>
-#include <iostream>
-
-#include <ui_nco.h>
-#include <gmac.h>
-#include <gmac_symbols.h>
-
-static bool verbose = true;
-
-class test_gmac_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,
- TRANSMITTING,
- };
-
- 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_gmac_tx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
- ~test_gmac_tx();
- 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_gmac_tx::test_gmac_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) 40e6),
- d_nsamples_xmitted(0),
- d_nframes_xmitted(0),
- d_samples_per_frame((long)(126 * 4)), // full packet
- d_done_sending(false),
- d_amplitude(16384)
-{
-
- define_component("GMAC", "gmac", PMT_NIL);
- d_tx = define_port("tx0", "gmac-tx", false, mb_port::INTERNAL);
- d_cs = define_port("cs", "gmac-cs", false, mb_port::INTERNAL);
-
- connect("self", "tx0", "GMAC", "tx0");
- connect("self", "cs", "GMAC", "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_gmac_tx::~test_gmac_tx()
-{
-}
-
-void
-test_gmac_tx::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;
-
- // Dispatch based on state
- switch(d_state) {
-
- //------------------------------ INIT ---------------------------------//
- // When GMAC is done initializing, it will send a response
- case INIT:
-
- if(pmt_eq(event, s_response_gmac_initialized)) {
- handle = pmt_nth(0, data);
- status = pmt_nth(1, data);
-
- if(pmt_eq(status, PMT_T)) {
- enter_transmitting();
- return;
- }
- else {
- error_msg = "error initializing gmac:";
- goto bail;
- }
- }
- 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_tx_pkt)){
- 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-tx-pkt:";
- goto bail;
- }
- }
-
- 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_GMAC_TX] unhandled msg: " << msg
- << "in state "<< d_state << std::endl;
-}
-
-void
-test_gmac_tx::enter_transmitting()
-{
- d_state = TRANSMITTING;
- d_nsamples_xmitted = 0;
-
- d_cs->send(s_cmd_carrier_sense_deadline,
- pmt_list2(PMT_NIL,
- pmt_from_long(50000000)));
-
- 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_gmac_tx::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_writeable_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();
- }
- }
-
- // Per packet properties
- pmt_t tx_properties = pmt_make_dict();
-
- if(d_nframes_xmitted > 25000) {
- pmt_dict_set(tx_properties,
- pmt_intern("carrier-sense"),
- PMT_F);
- }
-
- if(d_nframes_xmitted > 35000) {
- pmt_dict_set(tx_properties,
- pmt_intern("carrier-sense"),
- PMT_NIL);
- }
-
- if(d_nframes_xmitted == 45000) {
- d_cs->send(s_cmd_carrier_sense_threshold,
- pmt_list2(PMT_NIL,
- pmt_from_long(100)));
- }
-
- if(d_nframes_xmitted == 60000) {
- d_cs->send(s_cmd_carrier_sense_threshold,
- pmt_list2(PMT_NIL,
- pmt_from_long(25)));
- }
-
- if(d_nframes_xmitted == 75000) {
- d_cs->send(s_cmd_carrier_sense_disable,
- pmt_list1(PMT_NIL));
- }
-
- if(d_nframes_xmitted > 90000 && d_nframes_xmitted < 110000) {
- pmt_dict_set(tx_properties,
- pmt_intern("carrier-sense"),
- PMT_T);
- }
-
- if(d_nframes_xmitted > 110000) {
-
- if(d_nframes_xmitted % 100 == 0)
- pmt_dict_set(tx_properties,
- pmt_intern("carrier-sense"),
- PMT_T);
-}
-
- pmt_t timestamp = pmt_from_long(0xffffffff); // NOW
- d_tx->send(s_cmd_tx_pkt,
- pmt_list4(PMT_NIL, // invocation-handle
- PMT_NIL, // destination
- uvec, // the samples
- tx_properties)); // per pkt properties
-
- d_nsamples_xmitted += nsamples_this_frame;
- d_nframes_xmitted++;
-
- if(verbose && 0)
- std::cout << "[TEST_GMAC_TX] Transmitted frame\n";
-}
-
-
-void
-test_gmac_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
- }
-
- build_and_send_next_frame();
-}
-
-REGISTER_MBLOCK_CLASS(test_gmac_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("test_gmac_tx", "test_gmac_tx", PMT_F, &result);
-}
diff --git a/usrp/host/apps-inband/test_usrp_inband_2rx.cc b/usrp/host/apps-inband/test_usrp_inband_2rx.cc
new file mode 100644
index 000000000..da8d7271c
--- /dev/null
+++ b/usrp/host/apps-inband/test_usrp_inband_2rx.cc
@@ -0,0 +1,371 @@
+/* -*- 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 <mb_mblock.h>
+#include <mb_runtime.h>
+#include <mb_runtime_nop.h> // QA only
+#include <mb_protocol_class.h>
+#include <mb_exception.h>
+#include <mb_msg_queue.h>
+#include <mb_message.h>
+#include <mb_mblock_impl.h>
+#include <mb_msg_accepter.h>
+#include <mb_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);
+
+}
diff --git a/usrp/host/apps-inband/test_usrp_inband_cs.cc b/usrp/host/apps-inband/test_usrp_inband_2tx.cc
index 2497f8d5c..5ab9be06a 100644
--- a/usrp/host/apps-inband/test_usrp_inband_cs.cc
+++ b/usrp/host/apps-inband/test_usrp_inband_2tx.cc
@@ -25,16 +25,17 @@
#include <mb_mblock.h>
#include <mb_runtime.h>
+#include <mb_runtime_nop.h> // QA only
#include <mb_protocol_class.h>
#include <mb_exception.h>
#include <mb_msg_queue.h>
#include <mb_message.h>
+#include <mb_mblock_impl.h>
#include <mb_msg_accepter.h>
#include <mb_class_registry.h>
#include <pmt.h>
#include <stdio.h>
#include <string.h>
-#include <sys/time.h>
#include <iostream>
#include <ui_nco.h>
@@ -42,21 +43,14 @@
#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;
-static bool verbose = false;
-
-class test_usrp_cs : public mb_mblock
+class test_usrp_tx : 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];
+ pmt_t d_tx_chan0, d_tx_chan1;
enum state_t {
INIT,
@@ -79,8 +73,8 @@ class test_usrp_cs : public mb_mblock
double d_amplitude;
public:
- test_usrp_cs(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
- ~test_usrp_cs();
+ 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);
@@ -89,32 +83,25 @@ class test_usrp_cs : public mb_mblock
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_cs::test_usrp_cs(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+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_chan(PMT_NIL),
- d_rx_chan(PMT_NIL),
- d_state(INIT), d_nsamples_to_send((long) 40e6),
+ 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)),
- //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_CS] Initializing...\n";
+ // std::cout << "[TEST_USRP_TX] 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 = true;
@@ -129,6 +116,11 @@ test_usrp_cs::test_usrp_cs(mb_runtime *runtime, const std::string &instance_name
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,
@@ -136,18 +128,12 @@ test_usrp_cs::test_usrp_cs(mb_runtime *runtime, const std::string &instance_name
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("boe.rbf"));
+ pmt_intern("rf-freq"),
+ pmt_from_long(10e6));
define_component("server", "usrp_server", usrp_dict);
connect("self", "tx0", "server", "tx0");
- connect("self", "rx0", "server", "rx0");
connect("self", "cs", "server", "cs");
// initialize NCO
@@ -160,22 +146,21 @@ test_usrp_cs::test_usrp_cs(mb_runtime *runtime, const std::string &instance_name
// for now, we'll have the low-level code hardwire it.
}
-test_usrp_cs::~test_usrp_cs()
+test_usrp_tx::~test_usrp_tx()
{
}
void
-test_usrp_cs::initial_transition()
+test_usrp_tx::initial_transition()
{
open_usrp();
}
void
-test_usrp_cs::handle_message(mb_message_sptr msg)
+test_usrp_tx::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;
@@ -200,48 +185,21 @@ test_usrp_cs::handle_message(mb_message_sptr msg)
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(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_CS] 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(status, PMT_T) && !pmt_eqv(d_tx_chan1, PMT_NIL)){
+ enter_transmitting();
+ return;
}
-
- 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_CS] 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;
- }
+ else if(pmt_eq(status, PMT_F)){
+ error_msg = "failed to allocate channel:";
+ goto bail;
}
+ return;
}
goto unhandled;
@@ -303,81 +261,64 @@ test_usrp_cs::handle_message(mb_message_sptr msg)
return;
unhandled:
- if(verbose)
- std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
- << "in state "<< d_state << std::endl;
+ std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
+ << "in state "<< d_state << std::endl;
}
void
-test_usrp_cs::open_usrp()
+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_cs::close_usrp()
+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_CS] Closing USRP\n";
+ std::cout << "[TEST_USRP_INBAND_TX] Closing the USRP\n";
}
void
-test_usrp_cs::allocate_channel()
+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_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_TX] Requesting TX channel allocation\n";
}
void
-test_usrp_cs::enter_receiving()
-{
- d_rx->send(s_cmd_start_recv_raw_samples,
- pmt_list2(PMT_F,
- d_rx_chan));
-}
-
-void
-test_usrp_cs::enter_transmitting()
+test_usrp_tx::enter_transmitting()
{
d_state = TRANSMITTING;
d_nsamples_xmitted = 0;
-
- if(verbose)
- std::cout << "[TEST_USRP_INBAND_CS] Beginning transmission\n";
-
- sleep(1);
-
-// build_and_send_next_frame(); // fire off 4 to start pipeline
-
- build_and_send_ping();
- build_and_send_ping();
- build_and_send_ping();
-}
-
-void
-test_usrp_cs::build_and_send_ping()
-{
+ if(verbose)
+ std::cout << "[TEST_USRP_INBAND_TX] Transmitting...\n";
- 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;
+ 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_cs::build_and_send_next_frame()
+test_usrp_tx::build_and_send_next_frame()
{
// allocate the uniform vector for the samples
// FIXME perhaps hold on to this between calls
@@ -421,23 +362,34 @@ test_usrp_cs::build_and_send_next_frame()
}
}
+ pmt_t tx_properties = pmt_make_dict();
+
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
+ pmt_list5(pmt_from_long(d_nframes_xmitted), // invocation-handle
+ d_tx_chan0, // channel
uvec, // the samples
- timestamp));
+ 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)
- std::cout << "[TEST_USRP_INBAND_CS] Transmitted frame\n";
+ if(verbose && 0)
+ std::cout << "[TEST_USRP_INBAND_TX] Transmitted frame\n";
}
void
-test_usrp_cs::handle_xmit_response(pmt_t handle)
+test_usrp_tx::handle_xmit_response(pmt_t handle)
{
if (d_done_sending &&
pmt_to_long(handle) == (d_nframes_xmitted - 1)){
@@ -445,21 +397,23 @@ test_usrp_cs::handle_xmit_response(pmt_t handle)
enter_closing_channel();
}
- //build_and_send_next_frame();
+ build_and_send_next_frame();
}
void
-test_usrp_cs::enter_closing_channel()
+test_usrp_tx::enter_closing_channel()
{
d_state = CLOSING_CHANNEL;
- d_tx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_tx_chan));
-
+ // 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_CS] Closing channel\n";
+ std::cout << "[TEST_USRP_INBAND_tX] Deallocating TX channel\n";
}
-REGISTER_MBLOCK_CLASS(test_usrp_cs);
+REGISTER_MBLOCK_CLASS(test_usrp_tx);
// ----------------------------------------------------------------
@@ -472,5 +426,5 @@ main (int argc, char **argv)
mb_runtime_sptr rt = mb_make_runtime();
pmt_t result = PMT_NIL;
- rt->run("top", "test_usrp_cs", PMT_F, &result);
+ rt->run("top", "test_usrp_tx", PMT_F, &result);
}
diff --git a/usrp/host/apps-inband/test_usrp_inband_overrun.cc b/usrp/host/apps-inband/test_usrp_inband_overrun.cc
index 9041a0984..107668b89 100644
--- a/usrp/host/apps-inband/test_usrp_inband_overrun.cc
+++ b/usrp/host/apps-inband/test_usrp_inband_overrun.cc
@@ -102,7 +102,7 @@ test_usrp_rx::test_usrp_rx(mb_runtime *runtime, const std::string &instance_name
// Specify the RBF to use
pmt_dict_set(usrp_dict,
pmt_intern("rbf"),
- pmt_intern("nanocell9.rbf"));
+ pmt_intern("inband_1rxhb_1tx.rbf"));
pmt_dict_set(usrp_dict,
pmt_intern("decim-rx"),
@@ -306,7 +306,8 @@ test_usrp_rx::handle_response_recv_raw_samples(pmt_t 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 properties = pmt_nth(4, data);
+ pmt_t channel = pmt_nth(4, data);
+ pmt_t properties = pmt_nth(5, data);
d_samples_recvd += pmt_length(v_samples) / 4;
diff --git a/usrp/host/apps-inband/test_usrp_inband_registers.cc b/usrp/host/apps-inband/test_usrp_inband_registers.cc
index 017ccdbf5..a1d9cc141 100644
--- a/usrp/host/apps-inband/test_usrp_inband_registers.cc
+++ b/usrp/host/apps-inband/test_usrp_inband_registers.cc
@@ -118,7 +118,7 @@ test_usrp_inband_registers::test_usrp_inband_registers(mb_runtime *runtime, cons
// Specify the RBF to use
pmt_dict_set(usrp_dict,
pmt_intern("rbf"),
- pmt_intern("boe2.rbf"));
+ pmt_intern("inband_1rxhb_1tx.rbf"));
// Set TX and RX interpolations
pmt_dict_set(usrp_dict,
diff --git a/usrp/host/apps-inband/test_usrp_inband_rx.cc b/usrp/host/apps-inband/test_usrp_inband_rx.cc
index 0429951f3..cff2aa723 100644
--- a/usrp/host/apps-inband/test_usrp_inband_rx.cc
+++ b/usrp/host/apps-inband/test_usrp_inband_rx.cc
@@ -87,23 +87,30 @@ class test_usrp_rx : public mb_mblock
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(5e6)
+ 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("nanocell9.rbf"));
+ pmt_intern("inband_1rxhb_1tx.rbf"));
pmt_dict_set(usrp_dict,
pmt_intern("decim-rx"),
- pmt_from_long(128));
+ pmt_from_long(64));
define_component("server", "usrp_server", usrp_dict);
@@ -264,6 +271,7 @@ test_usrp_rx::open_usrp()
void
test_usrp_rx::close_usrp()
{
+
d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
d_state = CLOSING_USRP;
@@ -302,7 +310,8 @@ test_usrp_rx::handle_response_recv_raw_samples(pmt_t 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 properties = pmt_nth(4, data);
+ pmt_t channel = pmt_nth(4, data);
+ pmt_t properties = pmt_nth(5, data);
d_samples_recvd += pmt_length(v_samples) / 4;
@@ -325,9 +334,7 @@ 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)
@@ -342,10 +349,9 @@ 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);
+
}
diff --git a/usrp/host/apps-inband/test_usrp_inband_timestamps.cc b/usrp/host/apps-inband/test_usrp_inband_timestamps.cc
index 8824a72fe..297c7126a 100644
--- a/usrp/host/apps-inband/test_usrp_inband_timestamps.cc
+++ b/usrp/host/apps-inband/test_usrp_inband_timestamps.cc
@@ -147,7 +147,7 @@ test_usrp_inband_timestamps::test_usrp_inband_timestamps(mb_runtime *runtime, co
// Specify the RBF to use
pmt_dict_set(usrp_dict,
pmt_intern("rbf"),
- pmt_intern("tmac5.rbf"));
+ pmt_intern("inband_1rxhb_1tx.rbf"));
define_component("server", "usrp_server", usrp_dict);
diff --git a/usrp/host/apps-inband/test_usrp_inband_tx.cc b/usrp/host/apps-inband/test_usrp_inband_tx.cc
index 7118d2d0f..7f894a4c3 100644
--- a/usrp/host/apps-inband/test_usrp_inband_tx.cc
+++ b/usrp/host/apps-inband/test_usrp_inband_tx.cc
@@ -42,7 +42,7 @@
#include <symbols_usrp_low_level_cs.h>
#include <symbols_usrp_tx.h>
-static bool verbose = false;
+static bool verbose = true;
class test_usrp_tx : public mb_mblock
{
@@ -89,11 +89,9 @@ class test_usrp_tx : public mb_mblock
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) 40e6),
+ d_state(INIT), d_nsamples_to_send((long) 80e6),
d_nsamples_xmitted(0),
d_nframes_xmitted(0),
- //d_samples_per_frame((long)(126)),
- //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)
@@ -119,18 +117,14 @@ test_usrp_tx::test_usrp_tx(mb_runtime *runtime, const std::string &instance_name
// Specify the RBF to use
pmt_dict_set(usrp_dict,
pmt_intern("rbf"),
- pmt_intern("cs1.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_from_long(64));
pmt_dict_set(usrp_dict,
- pmt_intern("decim-rx"),
- pmt_from_long(16));
-
- pmt_dict_set(usrp_dict,
pmt_intern("rf-freq"),
pmt_from_long(10e6));
@@ -176,12 +170,12 @@ test_usrp_tx::handle_message(mb_message_sptr msg)
if (pmt_eq(event, s_response_open)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
- allocate_channel();
- return;
+ allocate_channel();
+ return;
}
else {
- error_msg = "failed to open usrp:";
- goto bail;
+ error_msg = "failed to open usrp:";
+ goto bail;
}
}
goto unhandled;
@@ -192,12 +186,12 @@ test_usrp_tx::handle_message(mb_message_sptr msg)
d_tx_chan = pmt_nth(2, data);
if (pmt_eq(status, PMT_T)){
- enter_transmitting();
- return;
+ enter_transmitting();
+ return;
}
else {
- error_msg = "failed to allocate channel:";
- goto bail;
+ error_msg = "failed to allocate channel:";
+ goto bail;
}
}
goto unhandled;
@@ -208,12 +202,12 @@ test_usrp_tx::handle_message(mb_message_sptr msg)
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
- handle_xmit_response(handle);
- return;
+ handle_xmit_response(handle);
+ return;
}
else {
- error_msg = "bad response-xmit-raw-frame:";
- goto bail;
+ error_msg = "bad response-xmit-raw-frame:";
+ goto bail;
}
}
goto unhandled;
@@ -223,12 +217,12 @@ test_usrp_tx::handle_message(mb_message_sptr msg)
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
- close_usrp();
- return;
+ close_usrp();
+ return;
}
else {
- error_msg = "failed to deallocate channel:";
- goto bail;
+ error_msg = "failed to deallocate channel:";
+ goto bail;
}
}
goto unhandled;
@@ -238,12 +232,12 @@ test_usrp_tx::handle_message(mb_message_sptr msg)
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
- shutdown_all(PMT_T);
- return;
+ shutdown_all(PMT_T);
+ return;
}
else {
- error_msg = "failed to close USRP:";
- goto bail;
+ error_msg = "failed to close USRP:";
+ goto bail;
}
}
goto unhandled;
@@ -272,6 +266,9 @@ test_usrp_tx::open_usrp()
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
@@ -279,6 +276,9 @@ 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
@@ -287,6 +287,9 @@ 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
@@ -295,15 +298,9 @@ test_usrp_tx::enter_transmitting()
d_state = TRANSMITTING;
d_nsamples_xmitted = 0;
- // FIXME: carrier sense hack
- 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(1),
- pmt_from_long(21))))));
-
+ 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();
@@ -356,9 +353,6 @@ test_usrp_tx::build_and_send_next_frame()
}
pmt_t tx_properties = pmt_make_dict();
- pmt_dict_set(tx_properties,
- pmt_intern("carrier-sense"),
- PMT_T);
pmt_t timestamp = pmt_from_long(0xffffffff); // NOW
d_tx->send(s_cmd_xmit_raw_frame,
@@ -371,7 +365,7 @@ test_usrp_tx::build_and_send_next_frame()
d_nsamples_xmitted += nsamples_this_frame;
d_nframes_xmitted++;
- if(verbose)
+ if(verbose && 0)
std::cout << "[TEST_USRP_INBAND_TX] Transmitted frame\n";
}
@@ -394,6 +388,9 @@ 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);
diff --git a/usrp/host/apps-inband/test_usrp_inband_underrun.cc b/usrp/host/apps-inband/test_usrp_inband_underrun.cc
index 0404208b4..c9630cec2 100644
--- a/usrp/host/apps-inband/test_usrp_inband_underrun.cc
+++ b/usrp/host/apps-inband/test_usrp_inband_underrun.cc
@@ -127,7 +127,7 @@ test_usrp_inband_underrun::test_usrp_inband_underrun(mb_runtime *runtime, const
d_rx_chan(PMT_NIL),
d_which_usrp(pmt_from_long(0)),
d_state(INIT),
- d_nsamples_to_send((long) 20e6),
+ d_nsamples_to_send((long) 27e6),
d_nsamples_xmitted(0),
d_nframes_xmitted(0),
d_samples_per_frame(d_nsamples_to_send), // full packet
@@ -143,12 +143,12 @@ test_usrp_inband_underrun::test_usrp_inband_underrun(mb_runtime *runtime, const
// Specify the RBF to use
pmt_dict_set(usrp_dict,
pmt_intern("rbf"),
- pmt_intern("nanocell9.rbf"));
+ pmt_intern("inband_1rxhb_1tx.rbf"));
// Set TX and RX interpolations
pmt_dict_set(usrp_dict,
pmt_intern("interp-tx"),
- pmt_from_long(8));
+ pmt_from_long(64));
pmt_dict_set(usrp_dict,
pmt_intern("decim-rx"),
@@ -668,8 +668,6 @@ test_usrp_inband_underrun::closing_usrp()
{
d_state = CLOSING_USRP;
- sleep(2);
-
d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
}
diff --git a/usrp/host/lib/inband/Makefile.am b/usrp/host/lib/inband/Makefile.am
index 77d1f6699..a41ac18b8 100644
--- a/usrp/host/lib/inband/Makefile.am
+++ b/usrp/host/lib/inband/Makefile.am
@@ -76,7 +76,6 @@ include_HEADERS = \
usrp_usb_interface.h
noinst_HEADERS = \
- fake_usrp.h \
qa_inband.h \
qa_inband_packet_prims.h \
qa_inband_usrp_server.h \
@@ -109,14 +108,10 @@ libusrp_inband_qa_la_LIBADD = \
# ------------------------------------------------------------------------
noinst_PROGRAMS = \
- test_inband \
- test_usrp_inband
+ test_inband
test_inband_SOURCES = test_inband.cc
test_inband_LDADD = libusrp_inband-qa.la
-test_usrp_inband_SOURCES = test_usrp_inband.cc
-test_usrp_inband_LDADD = libusrp_inband-qa.la
-
MOSTLYCLEANFILES = \
$(BUILT_SOURCES) *~ *.pyc
diff --git a/usrp/host/lib/inband/fake_usrp.cc b/usrp/host/lib/inband/fake_usrp.cc
deleted file mode 100644
index 8a66d5c18..000000000
--- a/usrp/host/lib/inband/fake_usrp.cc
+++ /dev/null
@@ -1,135 +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 <fake_usrp.h>
-#include <iostream>
-#include <usrp_inband_usb_packet.h>
-#include <mb_class_registry.h>
-#include <vector>
-
-typedef usrp_inband_usb_packet transport_pkt; // makes conversion to gigabit easy
-
-fake_usrp::fake_usrp()
-{
- std::cout << "[fake_usrp] Initializing...\n";
-}
-
-fake_usrp::~fake_usrp() {}
-
-long
-fake_usrp::write_bus(transport_pkt *pkts, long n_bytes)
-{
- std::cout << "[fake_usrp] Bytes over bus: " << n_bytes << "\n";
-
- // I'm assuming that a control packet cannot exist in a burst of data packets,
- // therefore i read only the first packet's channel in the current burst
- if(pkts[0].chan() == 0x1f) {
- return control_block(pkts, n_bytes);
- } else {
- return data_block(pkts, n_bytes);
- }
-
-}
-
-long
-fake_usrp::data_block(transport_pkt *pkts, long n_bytes)
-{
- std::cout << "[fake_usrp] Entering data block\n";
-
- // Infer the number of packets from the byte count to do logical tests
- long n_pkts = static_cast<long>(std::ceil(n_bytes / (double)transport_pkt::max_pkt_size()));
-
- std::cout << "[fake_usrp] Number of packets: " << n_pkts << "\n";
-
- // The first packet should have the start of burst, and the last packet should have end of burst
- if(pkts[0].start_of_burst() && pkts[n_pkts-1].end_of_burst()) {
- std::cout << "[fake_usrp] Correct burst flags set\n";
- } else {
- std::cout << "[fake_usrp] Incorrect burst flags set!\n";
- return 0;
- }
-
- // All other flags should be set to 0 (e.g., overrun should not be set yet) on ALL packets
- for(int i=0; i < n_pkts; i++) {
- if(pkts[i].overrun()) {
- std::cout << "[fake_usrp] Incorrect set of overrun flag on transmit\n";
- return 0;
- } else if(pkts[i].underrun()) {
- std::cout << "[fake_usrp] Incorrect set of underrun flag on transmit\n";
- return 0;
- } else if(pkts[i].dropped()) {
- std::cout << "[fake_usrp] Incorrect set of drop flag on transmit\n";
- return 0;
- }
- }
- std::cout << "[fake_usrp] Correct overrun, underrun, and drop flags on transmit (initialized to 0)\n";
-
- // The first packet should have a timestamp, other packets should have "NOW"
- if(pkts[0].timestamp() != 0xffffffff) {
- std::cout << "[fake_usrp] Correct timestamp on first packet\n";
- } else {
- std::cout << "[fake_usrp] Initial packet should not have the 0xffffffff timestamp\n";
- return 0;
- }
-
- // Check that all of the other packets include the NOW timestamp
- int check_stamps=1;
- for(int i=1; i < n_pkts; i++) // start at 1 to skip the first packet
- if(pkts[i].timestamp() != 0xffffffff)
- check_stamps=0;
-
- if(check_stamps) {
- std::cout << "[fake_usrp] Correct NOW timestamps (0xffffffff) on intermediate burst packets\n";
- } else {
- std::cout << "[fake_usrp] Incorrect timestamps on intermediate burst packets\n";
- return 0;
- }
-
- // Since we are being transparent about samples, we do not ensure the payload is correct, however
- // it should be the case that if there are >1 packets, all packets except the last packet should
- // have a full payload size
- if(n_pkts > 1) {
- int check_size=1;
- for(int i=0; i < n_pkts-1; i++)
- if(pkts[i].payload_len() != transport_pkt::max_payload())
- check_size=0;
-
- if(check_size) {
- std::cout << "[fake_usrp] Correct payload size sanity check on packets\n";
- } else {
- std::cout << "[fake_usrp] Failed payload size sanity check\n";
- return 0;
- }
- }
-
- return 1;
-}
-
-long
-fake_usrp::control_block(transport_pkt *pkts, long n_bytes)
-{
- std::cout << "[fake_usrp] Entering control block\n";
-
- return 1;
-}
diff --git a/usrp/host/lib/inband/fake_usrp.h b/usrp/host/lib/inband/fake_usrp.h
deleted file mode 100644
index 818c5a506..000000000
--- a/usrp/host/lib/inband/fake_usrp.h
+++ /dev/null
@@ -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_FAKE_USRP_H
-#define INCLUDED_FAKE_USRP_H
-
-#include <usrp_inband_usb_packet.h>
-typedef usrp_inband_usb_packet transport_pkt;
-
-/*!
- * \brief Implements a fake USRP for testing without hardware
- */
-class fake_usrp
-{
- public:
- fake_usrp();
- ~fake_usrp();
- long write_bus(transport_pkt *pkts, long n_bytes);
-
- protected:
- long data_block(transport_pkt *pkts, long n_bytes);
- long control_block(transport_pkt *pkts, long n_bytes);
-};
-
-#endif /* INCLUDED_FAKE_USRP_H */
-
diff --git a/usrp/host/lib/inband/qa_inband_usrp_server.cc b/usrp/host/lib/inband/qa_inband_usrp_server.cc
index b01e74e00..e457e8d64 100644
--- a/usrp/host/lib/inband/qa_inband_usrp_server.cc
+++ b/usrp/host/lib/inband/qa_inband_usrp_server.cc
@@ -46,6 +46,8 @@ typedef usrp_inband_usb_packet transport_pkt; // makes conversion to gigabit e
static bool verbose = false;
+static pmt_t s_timeout = pmt_intern("%timeout");
+
// ----------------------------------------------------------------------------------------------
class qa_alloc_top : public mb_mblock
@@ -903,10 +905,10 @@ class qa_rx_top : public mb_mblock
long d_rx_chan;
- long d_got_response_recv;
+ bool d_got_response_recv;
- long d_nmsg_to_recv;
- long d_nmsg_recvd;
+ mb_time d_t0;
+ double d_delta_t;
public:
qa_rx_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
@@ -927,18 +929,19 @@ qa_rx_top::qa_rx_top(mb_runtime *runtime, const std::string &instance_name, pmt_
d_got_response_recv(false)
{
- d_nmsg_to_recv=12;
- d_nmsg_recvd=0;
-
d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
// Use the stub with the usrp_server
- pmt_t usrp_server_dict = pmt_make_dict();
- pmt_dict_set(usrp_server_dict, pmt_intern("fake-usrp"), PMT_T);
+ pmt_t usrp_dict = pmt_make_dict();
+ // Set TX and RX interpolations
+ pmt_dict_set(usrp_dict,
+ pmt_intern("decim-rx"),
+ pmt_from_long(128));
+ pmt_dict_set(usrp_dict, pmt_intern("fake-usrp"), PMT_T);
// Test the TX side
- define_component("server", "usrp_server", usrp_server_dict);
+ define_component("server", "usrp_server", usrp_dict);
connect("self", "rx0", "server", "rx0");
connect("self", "cs", "server", "cs");
}
@@ -967,17 +970,10 @@ qa_rx_top::run_tests()
pmt_list2(PMT_NIL,
pmt_from_long(0)));
- // A small sleep is used to ensure, if working properly, a recv
- // response comes through successfully before the close gets
- // through
- usleep(1000);
-
- d_rx->send(s_cmd_stop_recv_raw_samples,
- pmt_list2(PMT_NIL,
- pmt_from_long(0)));
-
- d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close,PMT_T)));
-
+ // Schedule a small timeout in which we expect to have received at least one
+ // packet worth of samples from the stub
+ d_t0 = mb_time::time();
+ schedule_one_shot_timeout(d_t0 + 0.01, PMT_NIL);
}
@@ -992,26 +988,37 @@ qa_rx_top::handle_message(mb_message_sptr msg)
pmt_t expected = pmt_nth(0, data);
pmt_t status = pmt_nth(1, data);
+
+ // If we get a timeout we shutdown
+ if(pmt_eq(event, s_timeout)) {
+ if(verbose)
+ std::cout << "[qa_rx_top] Got timeout\n";
+ d_rx->send(s_cmd_stop_recv_raw_samples,
+ pmt_list2(PMT_NIL,
+ pmt_from_long(0)));
+
+ d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close,PMT_T)));
+ return;
+ }
// For testing RX, an invocation handle is not generated by the stub,
// therefore the same approach for testing is not used. We simply
// expect all responses to be true.
if(pmt_eq(event, s_response_recv_raw_samples)) {
- if(!pmt_eqv(status, PMT_T)) {
- if(verbose)
- std::cout << "Got: " << status << " Expected: " << PMT_T << "\n";
- shutdown_all(PMT_F);
- return;
- }
- else {
+ if(pmt_eqv(status, PMT_T)) {
+
if(verbose)
std::cout << "[qa_rx_top] Received expected response for message "
- << d_nmsg_recvd
<< " (" << event << ")\n";
// All we want is 1 response receive! Can't guarantee exact numbers
d_got_response_recv = true;
}
+ else {
+ if(verbose)
+ std::cout << "Got: " << status << " Expected: " << PMT_T << "\n";
+ shutdown_all(PMT_F);
+ }
return;
}
@@ -1026,8 +1033,7 @@ qa_rx_top::handle_message(mb_message_sptr msg)
} else {
if(verbose)
std::cout << "[qa_rx_top] Received expected response for message "
- << d_nmsg_recvd
- << " (" << event << ")\n";
+ << " (" << event << ")\n";
}
if (pmt_eq(msg->port_id(), d_rx->port_symbol())) {
@@ -1051,12 +1057,7 @@ qa_rx_top::handle_message(mb_message_sptr msg)
std::cout << "[qa_rx_top] No response message before close\n";
return;
}
-
}
-
-
- d_nmsg_recvd++;
-
}
@@ -1079,6 +1080,160 @@ qa_rx_top::check_allocation(mb_message_sptr msg)
REGISTER_MBLOCK_CLASS(qa_rx_top);
+// ----------------------------------------------------------------------------------------------
+
+class qa_rid_top : public mb_mblock
+{
+ mb_port_sptr d_tx;
+ mb_port_sptr d_rx;
+ mb_port_sptr d_cs;
+
+ long d_npongs;
+ long d_tcycles;
+ long d_cycles;
+ long d_max_rid;
+
+ mb_time d_t0;
+ double d_delta_t;
+
+ public:
+ qa_rid_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+ ~qa_rid_top();
+ void initial_transition();
+ void handle_message(mb_message_sptr msg);
+
+ protected:
+ void run_tests();
+ void send_max_pings();
+};
+
+qa_rid_top::qa_rid_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+ : mb_mblock(runtime, instance_name, user_arg)
+{
+ d_npongs = 0;
+ d_tcycles = 3;
+ d_cycles = d_tcycles;
+ d_max_rid = usrp_server::D_MAX_RID;
+ d_delta_t = 0.1;
+
+
+ d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
+ d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
+ d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
+
+ // Use the stub with the usrp_server
+ pmt_t usrp_server_dict = pmt_make_dict();
+ pmt_dict_set(usrp_server_dict, pmt_intern("fake-usrp"),PMT_T);
+
+ // Test the TX side
+ define_component("server", "usrp_server", usrp_server_dict);
+ connect("self", "tx0", "server", "tx0");
+ connect("self", "rx0", "server", "rx0");
+ connect("self", "cs", "server", "cs");
+
+}
+
+qa_rid_top::~qa_rid_top(){}
+
+void
+qa_rid_top::initial_transition()
+{
+ run_tests();
+}
+
+void
+qa_rid_top::run_tests()
+{
+ if(verbose)
+ std::cout << "[qa_rid_top] Starting tests...\n";
+
+ // Retrieve information about the USRP, then run tests
+ d_cs->send(s_cmd_open,
+ pmt_list2(pmt_list2(s_response_open, PMT_T),
+ pmt_from_long(0)));
+
+ // should be able to allocate 1 byte
+ d_tx->send(s_cmd_allocate_channel,
+ pmt_list2(pmt_list2(s_response_allocate_channel, PMT_T),
+ pmt_from_long(1)));
+
+ d_rx->send(s_cmd_allocate_channel,
+ pmt_list2(pmt_list2(s_response_allocate_channel, PMT_T),
+ pmt_from_long(1)));
+
+ // Need to start receiving to read from the USRP to get C/S responses
+ d_rx->send(s_cmd_start_recv_raw_samples,
+ pmt_list2(PMT_NIL,
+ pmt_from_long(0)));
+
+ // Build a subpacket of MAX_RID pings and wait a small amount for all of the
+ // responses and fire off another MAX_RID. If MAX_RID*2 responses are
+ // received, the RID recycling is working correctly.
+ // Schedule a timer in which we expect to have received all of the responses,
+ // which will send off another MAX_RID worth.
+ send_max_pings();
+ d_t0 = mb_time::time();
+ schedule_one_shot_timeout(d_t0 + d_delta_t, PMT_NIL);
+}
+
+void
+qa_rid_top::send_max_pings()
+{
+ pmt_t ping = pmt_list2(s_op_ping_fixed,
+ pmt_list2(pmt_from_long(0),
+ pmt_from_long(0)));
+
+ pmt_t sub_packets = PMT_NIL;
+
+ for(int i=0; i<d_max_rid; i++)
+ sub_packets = pmt_list_add(sub_packets, ping);
+
+ d_tx->send(s_cmd_to_control_channel,
+ pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T),
+ sub_packets));
+}
+
+void
+qa_rid_top::handle_message(mb_message_sptr msg)
+{
+ pmt_t data = msg->data();
+ pmt_t event = msg->signal();
+
+ // If we get a timeout we ensure we got a maximum RID number of responses.
+ if(pmt_eq(event, s_timeout)) {
+ if(verbose)
+ std::cout << "[qa_rid_top] Got timeout, received so far: "
+ << d_npongs << "\n";
+
+ d_cycles--;
+
+ if(d_cycles==0 && d_npongs == d_max_rid*d_tcycles) {
+ shutdown_all(PMT_T);
+ }
+ else if(d_cycles==0) {
+
+ std::cout << "[qa_rid_top] d_npongs: " << d_npongs
+ << " expected: " << d_max_rid*d_tcycles
+ << std::endl;
+
+ shutdown_all(PMT_F);
+ }
+ else {
+ send_max_pings();
+ d_t0 = mb_time::time();
+ schedule_one_shot_timeout(d_t0 + d_delta_t, PMT_NIL);
+ }
+
+ }
+ else if(pmt_eq(event, s_response_from_control_channel))
+ {
+ d_npongs++;
+ }
+
+}
+
+REGISTER_MBLOCK_CLASS(qa_rid_top);
+
// ----------------------------------------------------------------------------------------------
@@ -1398,3 +1553,17 @@ qa_inband_usrp_server::test_cs()
CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
}
+
+void
+qa_inband_usrp_server::test_rid()
+{
+ mb_runtime_sptr rt = mb_make_runtime();
+ pmt_t result = PMT_T;
+
+ // std::cout << "\n\n-----------------\n";
+ // std::cout << " RUNNING RID TESTS \n";
+
+ rt->run("top", "qa_rid_top", PMT_F, &result);
+
+ CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
+}
diff --git a/usrp/host/lib/inband/qa_inband_usrp_server.h b/usrp/host/lib/inband/qa_inband_usrp_server.h
index 5db57c3ed..52a4a0b06 100644
--- a/usrp/host/lib/inband/qa_inband_usrp_server.h
+++ b/usrp/host/lib/inband/qa_inband_usrp_server.h
@@ -34,6 +34,7 @@ class qa_inband_usrp_server : public CppUnit::TestCase {
CPPUNIT_TEST(test_tx);
CPPUNIT_TEST(test_rx);
CPPUNIT_TEST(test_cs);
+ CPPUNIT_TEST(test_rid);
CPPUNIT_TEST_SUITE_END();
private:
@@ -43,6 +44,7 @@ class qa_inband_usrp_server : public CppUnit::TestCase {
void test_tx();
void test_rx();
void test_cs();
+ void test_rid();
};
#endif /* INCLUDED_QA_INBAND_USRP_SERVER_H */
diff --git a/usrp/host/lib/inband/test_usrp_inband.cc b/usrp/host/lib/inband/test_usrp_inband.cc
deleted file mode 100644
index 64fbf3a97..000000000
--- a/usrp/host/lib/inband/test_usrp_inband.cc
+++ /dev/null
@@ -1,298 +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 <stdio.h>
-#include <string.h>
-#include <iostream>
-#include <usrp_inband_usb_packet.h>
-#include <mb_mblock.h>
-#include <mb_runtime.h>
-#include <mb_protocol_class.h>
-#include <mb_class_registry.h>
-#include <pmt.h>
-#include "usrp_standard.h"
-
-typedef usrp_inband_usb_packet transport_pkt;
-
-// Signal set for the USRP server
-static pmt_t s_cmd_open = pmt_intern("cmd-open");
-static pmt_t s_response_open = pmt_intern("response-open");
-static pmt_t s_cmd_close = pmt_intern("cmd-close");
-static pmt_t s_response_close = pmt_intern("response-close");
-static pmt_t s_cmd_allocate_channel = pmt_intern("cmd-allocate-channel");
-static pmt_t s_response_allocate_channel = pmt_intern("response-allocate-channel");
-static pmt_t s_send_allocate_channel = pmt_intern("send-allocate-channel");
-static pmt_t s_cmd_deallocate_channel = pmt_intern("cmd-deallocate-channel");
-static pmt_t s_response_deallocate_channel = pmt_intern("response-deallocate-channel");
-static pmt_t s_send_deallocate_channel = pmt_intern("send-deallocate-channel");
-static pmt_t s_cmd_max_capacity = pmt_intern("cmd-max-capacity");
-static pmt_t s_response_max_capacity = pmt_intern("response-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_response_ntx_chan = pmt_intern("response-ntx-chan");
-static pmt_t s_response_nrx_chan = pmt_intern("response-nrx-chan");
-static pmt_t s_cmd_current_capacity_allocation = pmt_intern("cmd-current-capacity-allocation");
-static pmt_t s_response_current_capacity_allocation = pmt_intern("response-current-capacity-allocation");
-static pmt_t s_cmd_xmit_raw_frame = pmt_intern("cmd-xmit-raw-frame");
-static pmt_t s_response_xmit_raw_frame = pmt_intern("response-xmit-raw-frame");
-
-bool loopback_p = false;
-bool counting_p = false;
-bool fake_usrp_p = false;
-char *prog_name;
-
-static void
-set_progname (char *path)
-{
- char *p = strrchr (path, '/');
- if (p != 0)
- prog_name = p+1;
- else
- prog_name = path;
-}
-
-static void
-usage()
-{
- fprintf (stderr, "usage: %s [-l]\n", prog_name);
- fprintf (stderr, " [-l] digital loopback in FPGA\n");
- fprintf (stderr, " [-c] counting in FPGA\n");
- fprintf (stderr, " [-f] fake usrp\n");
-
- exit(1);
-}
-
-int
-main(int argc, char **argv)
-{
- int ch;
-
- set_progname(argv[0]);
-
- mb_runtime_sptr rt = mb_make_runtime();
- pmt_t result = PMT_T;
-
- while ((ch = getopt(argc, argv, "flc")) != EOF) {
- switch(ch) {
-
- case 'l':
- loopback_p = true;
- break;
-
- case 'c':
- counting_p = true;
- break;
-
- case 'f':
- fake_usrp_p = true;
- break;
-
- default:
- usage();
- }
- }
-
-
- std::cout << "[test_usrp_inband] Starting...\n";
-
- rt->run("top", "test_usrp_inband_top", PMT_F, &result);
-}
-
-class test_usrp_inband_top : public mb_mblock
-{
- mb_port_sptr d_tx;
- mb_port_sptr d_cs;
-
- long d_tx_chan;
-
- public:
- test_usrp_inband_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
- ~test_usrp_inband_top();
- void initial_transition();
- void handle_message(mb_message_sptr msg);
-
- protected:
- void open_usrp();
- void close_usrp();
- void check_message(mb_message_sptr msg);
- void allocate_channel();
- void send_packets();
-};
-
-test_usrp_inband_top::test_usrp_inband_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
- : mb_mblock(runtime, instance_name, user_arg)
-{
- std::cout << "[TEST_USRP_INBAND_TOP] 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);
-
- // Test the TX side
-
- // Pass a dictionary to usrp_server which specifies which interface to use, the stub or USRP
- pmt_t usrp_server_dict = pmt_make_dict();
-
- if(fake_usrp_p)
- pmt_dict_set(usrp_server_dict, pmt_intern("usrp-interface"), pmt_intern("usrp_usb_interface_stub"));
-
- define_component("server", "usrp_server", usrp_server_dict);
- connect("self", "tx0", "server", "tx0");
- connect("self", "cs", "server", "cs");
-}
-
-test_usrp_inband_top::~test_usrp_inband_top()
-{
-}
-
-void
-test_usrp_inband_top::initial_transition()
-{
- open_usrp();
-}
-
-void
-test_usrp_inband_top::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 metadata = msg->metadata();
- pmt_t status;
-
- if (pmt_eq(port_id, d_cs->port_symbol())) { // message came in on our control/status port
-
- //---------- OPEN RESPONSE ----------//
- if (pmt_eq(event, s_response_open)) {
- status = pmt_nth(1, data);
-
- if(pmt_eq(status, PMT_T)) {
- std::cout << "[TEST_USRP_INBAND_TOP] Success opening USRP\n";
- }
- else {
- std::cout << "[TEST_USRP_INBAND_TOP] Received error message opening USRP\n";
- shutdown_all(PMT_F);
- }
-
- allocate_channel();
-
- return;
- }
- //--------- CLOSE RESPONSE -----------//
- else if (pmt_eq(event, s_response_close)) {
- status = pmt_nth(1, data);
-
- if(pmt_eq(status, PMT_T)) {
- std::cout << "[TEST_USRP_INBAND_TOP] Successfully closed USRP\n";
- }
- else {
- std::cout << "[TEST_USRP_INBAND_TOP] Received error message closing USRP\n";
- shutdown_all(PMT_F);
- }
-
- shutdown_all(PMT_T);
-
- return;
- }
- }
-
- if (pmt_eq(port_id, d_tx->port_symbol())) {
-
- //---------- ALLOCATE RESPONSE ---------//
- if(pmt_eq(event, s_response_allocate_channel)) {
- status = pmt_nth(1, data);
- pmt_t channel = pmt_nth(2, data);
-
- if(pmt_eq(status, PMT_T)) {
- d_tx_chan = pmt_to_long(channel);
- std::cout << "[TEST_USRP_INBAND_TOP] Received allocation on channel " << d_tx_chan << "\n";
- }
- else {
- std::cout << "[TEST_USRP_INBAND_TOP] Error allocating channel\n";
- shutdown_all(PMT_F);
- }
-
- send_packets();
-
- return;
- }
- //----------- XMIT RESPONSE ------------//
- else if(pmt_eq(event, s_response_xmit_raw_frame)) {
- status = pmt_nth(1, data);
-
- if(pmt_eq(status, PMT_T)) {
- std::cout << "[TEST_USRP_INBAND_TOP] Transmission successful\n";
- }
- else {
- std::cout << "[TEST_USRP_INBAND_TOP] Failed transmission\n";
- shutdown_all(PMT_F);
- }
-
- close_usrp();
-
- return;
- }
- }
-
- std::cout << "[TEST_USRP_INBAND_TOP] Received unhandled message: " << event << "\n";
-}
-
-void
-test_usrp_inband_top::allocate_channel()
-{
- std::cout << "[TEST_USRP_INBAND_TOP] Requesting channel allocation...\n";
-
- d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
-}
-
-void
-test_usrp_inband_top::send_packets()
-{
- std::cout << "[TEST_USRP_INBAND_TOP] Sending single packet..\n";
- d_tx->send(s_cmd_xmit_raw_frame, pmt_list4(pmt_from_long(1), pmt_from_long(d_tx_chan), pmt_make_u32vector(transport_pkt::max_payload()/4, 0), pmt_from_long(0)));
-
-}
-
-void
-test_usrp_inband_top::open_usrp()
-{
- pmt_t usrp = pmt_from_long(0);
-
- long rx_mode = 0;
-
- if(loopback_p)
- rx_mode |= usrp_standard_rx::FPGA_MODE_LOOPBACK;
- if(counting_p)
- rx_mode |= usrp_standard_rx::FPGA_MODE_COUNTING;
-
- d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, usrp));
-}
-
-void
-test_usrp_inband_top::close_usrp()
-{
- d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
-}
-
-REGISTER_MBLOCK_CLASS(test_usrp_inband_top);
diff --git a/usrp/host/lib/inband/usrp_inband_usb_packet.cc b/usrp/host/lib/inband/usrp_inband_usb_packet.cc
index ee4cb22f3..2f02ecc3f 100644
--- a/usrp/host/lib/inband/usrp_inband_usb_packet.cc
+++ b/usrp/host/lib/inband/usrp_inband_usb_packet.cc
@@ -30,6 +30,14 @@
#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();
@@ -44,18 +52,20 @@ bool usrp_inband_usb_packet::align32()
if((MAX_PAYLOAD - p_len) < bytes_needed)
return false;
- p_len += bytes_needed;
-
- int h_flags = flags();
- int h_chan = chan();
- int h_tag = tag();
- int h_payload_len = p_len;
-
- set_header(h_flags, h_chan, h_tag, h_payload_len);
+ 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())
@@ -78,17 +88,20 @@ bool usrp_inband_usb_packet::cs_ping(long rid, long ping_val)
*payload = host_to_usrp_u32(ping);
// Update payload length
- int h_flags = flags();
- int h_chan = chan();
- int h_tag = tag();
- int h_payload_len = payload_len() + CS_FIXED_LEN + CS_PING_LEN;
-
- set_header(h_flags, h_chan, h_tag, h_payload_len);
+ 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())
@@ -111,16 +124,20 @@ bool usrp_inband_usb_packet::cs_ping_reply(long rid, long ping_val)
*payload = host_to_usrp_u32(ping);
// Update payload length
- int h_flags = flags();
- int h_chan = chan();
- int h_tag = tag();
- int h_payload_len = payload_len() + CS_FIXED_LEN + CS_PING_LEN;
-
- set_header(h_flags, h_chan, h_tag, h_payload_len);
+ 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())
@@ -149,16 +166,19 @@ bool usrp_inband_usb_packet::cs_write_reg(long reg_num, long val)
*payload = host_to_usrp_u32((uint32_t) val);
// Rebuild the header to update the payload length
- int h_flags = flags();
- int h_chan = chan();
- int h_tag = tag();
- int h_payload_len = payload_len() + CS_FIXED_LEN + CS_WRITEREG_LEN;
-
- set_header(h_flags, h_chan, h_tag, h_payload_len);
+ 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())
@@ -190,16 +210,19 @@ bool usrp_inband_usb_packet::cs_write_reg_masked(long reg_num, long val, long ma
*payload = host_to_usrp_u32((uint32_t) mask);
// Rebuild the header to update the payload length
- int h_flags = flags();
- int h_chan = chan();
- int h_tag = tag();
- int h_payload_len = payload_len() + CS_FIXED_LEN + CS_WRITEREGMASKED_LEN;
-
- set_header(h_flags, h_chan, h_tag, h_payload_len);
+ 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())
@@ -222,16 +245,22 @@ bool usrp_inband_usb_packet::cs_read_reg(long rid, long reg_num)
*payload = host_to_usrp_u32(read_reg);
// Update payload length
- int h_flags = flags();
- int h_chan = chan();
- int h_tag = tag();
- int h_payload_len = payload_len() + CS_FIXED_LEN + CS_READREG_LEN;
-
- set_header(h_flags, h_chan, h_tag, h_payload_len);
+ 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())
@@ -258,16 +287,19 @@ bool usrp_inband_usb_packet::cs_read_reg_reply(long rid, long reg_num, long reg_
*payload = host_to_usrp_u32((uint32_t) reg_val);
// Update payload length
- int h_flags = flags();
- int h_chan = chan();
- int h_tag = tag();
- int h_payload_len = payload_len() + CS_FIXED_LEN + CS_READREGREPLY_LEN;
-
- set_header(h_flags, h_chan, h_tag, h_payload_len);
+ 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())
@@ -289,16 +321,16 @@ bool usrp_inband_usb_packet::cs_delay(long ticks)
*payload = host_to_usrp_u32(delay);
// Update payload length
- int h_flags = flags();
- int h_chan = chan();
- int h_tag = tag();
- int h_payload_len = payload_len() + CS_FIXED_LEN + CS_DELAY_LEN;
-
- set_header(h_flags, h_chan, h_tag, h_payload_len);
+ 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())
@@ -328,16 +360,20 @@ bool usrp_inband_usb_packet::cs_i2c_write(long i2c_addr, uint8_t *i2c_data, size
memcpy(payload, i2c_data, data_len);
// Update payload length
- int h_flags = flags();
- int h_chan = chan();
- int h_tag = tag();
- int h_payload_len = payload_len() + CS_FIXED_LEN + i2c_len;
-
- set_header(h_flags, h_chan, h_tag, h_payload_len);
+ 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())
@@ -367,16 +403,20 @@ bool usrp_inband_usb_packet::cs_i2c_read(long rid, long i2c_addr, long n_bytes)
*payload = host_to_usrp_u32(word1);
// Update payload length
- int h_flags = flags();
- int h_chan = chan();
- int h_tag = tag();
- int h_payload_len = payload_len() + CS_FIXED_LEN + CS_I2CREAD_LEN;
-
- set_header(h_flags, h_chan, h_tag, h_payload_len);
+ 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())
@@ -406,16 +446,16 @@ bool usrp_inband_usb_packet::cs_i2c_read_reply(long rid, long i2c_addr, uint8_t
memcpy(payload, i2c_data, i2c_data_len);
// Update payload length
- int h_flags = flags();
- int h_chan = chan();
- int h_tag = tag();
- int h_payload_len = payload_len() + CS_FIXED_LEN + i2c_len;
-
- set_header(h_flags, h_chan, h_tag, h_payload_len);
+ 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())
@@ -454,16 +494,16 @@ bool usrp_inband_usb_packet::cs_spi_write(long enables, long format, long opt_he
memcpy(payload, spi_data, spi_data_len);
// Update payload length
- int h_flags = flags();
- int h_chan = chan();
- int h_tag = tag();
- int h_payload_len = payload_len() + CS_FIXED_LEN + spi_len;
-
- set_header(h_flags, h_chan, h_tag, h_payload_len);
+ 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())
@@ -508,16 +548,17 @@ bool usrp_inband_usb_packet::cs_spi_read(long rid, long enables, long format, lo
*payload = host_to_usrp_u32(word);
// Update payload length
- int h_flags = flags();
- int h_chan = chan();
- int h_tag = tag();
- int h_payload_len = payload_len() + CS_FIXED_LEN + CS_SPIREAD_LEN;
+ incr_header_len(CS_FIXED_LEN + CS_SPIREAD_LEN);
- set_header(h_flags, h_chan, h_tag, h_payload_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())
@@ -546,30 +587,32 @@ bool usrp_inband_usb_packet::cs_spi_read_reply(long rid, uint8_t *spi_data, long
memcpy(payload, spi_data, spi_data_len);
// Update payload length
- int h_flags = flags();
- int h_chan = chan();
- int h_tag = tag();
- int h_payload_len = payload_len() + CS_FIXED_LEN + spi_len;
-
- set_header(h_flags, h_chan, h_tag, h_payload_len);
+ incr_header_len(CS_FIXED_LEN + spi_len);
return true;
}
-// Takes an offset to the beginning of a subpacket and extracts the
-// length of the subpacket
+/*!
+ * \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;
}
-// The following method takes an offset within the packet payload to extract
-// a control/status subpacket and construct 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.
+/*!
+ * \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)));
diff --git a/usrp/host/lib/inband/usrp_inband_usb_packet.h b/usrp/host/lib/inband/usrp_inband_usb_packet.h
index 8c19b1aeb..8f59d1b65 100644
--- a/usrp/host/lib/inband/usrp_inband_usb_packet.h
+++ b/usrp/host/lib/inband/usrp_inband_usb_packet.h
@@ -31,6 +31,7 @@
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 {
//
@@ -150,6 +151,10 @@ public:
| ((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);
diff --git a/usrp/host/lib/inband/usrp_rx.cc b/usrp/host/lib/inband/usrp_rx.cc
index caa2d7175..71c042a50 100644
--- a/usrp/host/lib/inband/usrp_rx.cc
+++ b/usrp/host/lib/inband/usrp_rx.cc
@@ -40,25 +40,30 @@ 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(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);
- //d_disk_write=true;
-
if(d_disk_write) {
- d_ofile.open("rx_data.dat",std::ios::binary|std::ios::out);
+ 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_ofile.close();
+ d_ofile0.close();
+ d_ofile1.close();
d_cs_ofile.close();
}
}
@@ -69,6 +74,12 @@ 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)
{
@@ -85,6 +96,17 @@ usrp_rx::handle_message(mb_message_sptr msg)
}
}
+/*!
+ * \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)
{
@@ -104,7 +126,7 @@ usrp_rx::read_and_respond(pmt_t data)
std::cout << "[usrp_rx] Waiting for packets..\n";
// Read by 512 which is packet size and send them back up
- while(1) {
+ while(!usrp_rx_stop) {
pmt_t v_pkt = pmt_make_u8vector(pkt_size, 0);
transport_pkt *pkt =
@@ -124,19 +146,38 @@ usrp_rx::read_and_respond(pmt_t data)
d_cs->send(s_response_usrp_rx_read,
pmt_list3(PMT_NIL, PMT_T, v_pkt));
- if(verbose)
+ if(verbose && 0)
std::cout << "[usrp_rx] Read 1 packet\n";
if(d_disk_write) {
- if(pkt->chan() == 0x1f)
+ if(pkt->chan() == CONTROL_CHAN)
d_cs_ofile.write((const char *)pkt, transport_pkt::max_pkt_size());
- else
- d_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_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);
diff --git a/usrp/host/lib/inband/usrp_rx.h b/usrp/host/lib/inband/usrp_rx.h
index e1a90a781..10104bd66 100644
--- a/usrp/host/lib/inband/usrp_rx.h
+++ b/usrp/host/lib/inband/usrp_rx.h
@@ -26,6 +26,8 @@
class usrp_standard_rx;
+extern bool usrp_rx_stop; // used to communicate a 'stop' to the RX stub
+
/*!
* \brief Implements the low level usb interface to the USRP
*/
@@ -35,7 +37,9 @@ class usrp_rx : public mb_mblock
usrp_standard_rx *d_urx;
bool d_disk_write;
- std::ofstream d_ofile;
+ bool d_disk_write_pkt;
+ std::ofstream d_ofile0;
+ std::ofstream d_ofile1;
std::ofstream d_cs_ofile;
public:
diff --git a/usrp/host/lib/inband/usrp_rx_stub.cc b/usrp/host/lib/inband/usrp_rx_stub.cc
index 4bdb106b1..1c96b7a7a 100644
--- a/usrp/host/lib/inband/usrp_rx_stub.cc
+++ b/usrp/host/lib/inband/usrp_rx_stub.cc
@@ -43,7 +43,7 @@ typedef usrp_inband_usb_packet transport_pkt;
static const bool verbose = false;
-bool usrp_rx_stop;
+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.
@@ -52,15 +52,32 @@ 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 = 128e6 / interp;
+ double sample_rate = 64e6 / interp;
d_nco.set_freq(2*M_PI * freq/sample_rate);
//d_disk_write = true;
@@ -68,7 +85,7 @@ usrp_rx_stub::usrp_rx_stub(mb_runtime *rt, const std::string &instance_name, pmt
if(d_disk_write)
d_ofile.open("raw_rx.dat",std::ios::binary|std::ios::out);
- usrp_rx_stop = false;
+ usrp_rx_stop_stub = false;
}
usrp_rx_stub::~usrp_rx_stub()
@@ -80,7 +97,6 @@ usrp_rx_stub::~usrp_rx_stub()
void
usrp_rx_stub::initial_transition()
{
-
}
void
@@ -90,94 +106,121 @@ usrp_rx_stub::handle_message(mb_message_sptr msg)
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())) {
+ 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...\n";
+ std::cout << "[USRP_RX_STUB] Starting with decim @ "
+ << d_decim_rx << std::endl;
- if(pmt_eqv(event, s_cmd_usrp_rx_start_reading))
- read_and_respond(data);
+ start_packet_timer();
}
}
+// Setup a periodic timer which will drive packet generation
void
-usrp_rx_stub::read_and_respond(pmt_t data)
+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;
+ }
- while(!usrp_rx_stop) {
+ schedule_periodic_timeout(d_t0 + frame_rate, mb_time(frame_rate), PMT_T);
+}
- long nsamples_this_frame = d_samples_per_frame;
+void
+usrp_rx_stub::read_and_respond()
+{
- 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_writeable_elements(uvec, ignore);
+ long nsamples_this_frame = d_samples_per_frame;
- // fill in the complex sinusoid
+ 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_writeable_elements(uvec, ignore);
- for (int i = 0; i < nsamples_this_frame; i++){
+ // fill in the complex sinusoid
- 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);
+ for (int i = 0; i < nsamples_this_frame; i++){
- // write 16-bit i & q
- samples[2*i] = (int16_t) s.real();
- samples[2*i+1] = (int16_t) s.imag();
- }
+ 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();
}
-
- 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_writeable_elements(v_pkt, ignore);
+ else {
+ gr_complex s(d_amplitude, d_amplitude);
- 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";
+ // write 16-bit i & q
+ samples[2*i] = (int16_t) s.real();
+ samples[2*i+1] = (int16_t) s.imag();
}
-
}
- usrp_rx_stop = false;
+ 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_writeable_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));
- if(verbose)
- std::cout << "[USRP_RX_STUB] Got fake RX stop\n";
+ // 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";
+ }
}
diff --git a/usrp/host/lib/inband/usrp_rx_stub.h b/usrp/host/lib/inband/usrp_rx_stub.h
index 5a75bf00a..9cf308a99 100644
--- a/usrp/host/lib/inband/usrp_rx_stub.h
+++ b/usrp/host/lib/inband/usrp_rx_stub.h
@@ -31,9 +31,12 @@
typedef usrp_inband_usb_packet transport_pkt;
-extern bool usrp_rx_stop; // used to communicate a 'stop' to the RX stub
+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
*/
@@ -45,6 +48,10 @@ class usrp_rx_stub : public mb_mblock
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;
@@ -61,8 +68,9 @@ class usrp_rx_stub : public mb_mblock
void handle_message(mb_message_sptr msg);
private:
- void read_and_respond(pmt_t data);
+ void read_and_respond();
void read_data();
+ void start_packet_timer();
};
diff --git a/usrp/host/lib/inband/usrp_server.cc b/usrp/host/lib/inband/usrp_server.cc
index 1948a43b2..6a3643e56 100644
--- a/usrp/host/lib/inband/usrp_server.cc
+++ b/usrp/host/lib/inband/usrp_server.cc
@@ -29,6 +29,8 @@
#include <vector>
#include <usrp_usb_interface.h>
#include <string.h>
+#include <fpga_regs_common.h>
+#include <fpga_regs_standard.h>
#include <symbols_usrp_server_cs.h>
#include <symbols_usrp_channel.h>
@@ -53,13 +55,42 @@ str(long x)
usrp_server::usrp_server(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg)
: mb_mblock(rt, instance_name, user_arg),
+ d_fpga_debug(false),
+ d_interp_tx(128), // these should match the lower level defaults (rx also)
+ d_decim_rx(128),
d_fake_rx(false)
{
if(verbose)
std::cout << "[USRP_SERVER] Initializing...\n";
// Dictionary for arguments to all of the components
- pmt_t usrp_dict = user_arg;
+ d_usrp_dict = user_arg;
+
+ if (pmt_is_dict(d_usrp_dict)) {
+
+ if(pmt_t fpga_debug = pmt_dict_ref(d_usrp_dict,
+ pmt_intern("fpga-debug"),
+ PMT_NIL)) {
+ if(pmt_eqv(fpga_debug, PMT_T))
+ d_fpga_debug=true;
+ }
+
+ // Read the TX interpolations
+ if(pmt_t interp_tx = pmt_dict_ref(d_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(d_usrp_dict,
+ pmt_intern("decim-rx"),
+ PMT_NIL)) {
+ if(!pmt_eqv(decim_rx, PMT_NIL))
+ d_decim_rx = pmt_to_long(decim_rx);
+ }
+ }
// control & status port
d_cs = define_port("cs", "usrp-server-cs", true, mb_port::EXTERNAL);
@@ -82,7 +113,7 @@ usrp_server::usrp_server(mb_runtime *rt, const std::string &instance_name, pmt_t
mb_port::EXTERNAL));
}
- define_component("usrp", "usrp_usb_interface", usrp_dict);
+ define_component("usrp", "usrp_usb_interface", d_usrp_dict);
connect("self", "cs_usrp", "usrp", "cs");
d_defer=false;
@@ -108,6 +139,10 @@ usrp_server::usrp_server(mb_runtime *rt, const std::string &instance_name, pmt_t
//d_fake_rx=true;
}
+/*!
+ * \brief resets the assigned capacity and owners of each RX and TX channel from
+ * allocations.
+ */
void
usrp_server::reset_channels()
{
@@ -136,6 +171,11 @@ usrp_server::initial_transition()
// the initial transition
}
+/*!
+ * \brief Reads all incoming messages to USRP server from the TX, RX, and the CS
+ * ports. This drives the state of USRP server and dispatches based on the
+ * message.
+ */
void
usrp_server::handle_message(mb_message_sptr msg)
{
@@ -178,6 +218,9 @@ usrp_server::handle_message(mb_message_sptr msg)
pmt_t status = pmt_nth(1, data);
d_cs->send(s_response_open, pmt_list2(invocation_handle, status));
+ //reset_all_registers();
+ //initialize_registers();
+
if(pmt_eqv(status,PMT_T)) {
d_opened = true;
d_defer = false;
@@ -209,7 +252,7 @@ usrp_server::handle_message(mb_message_sptr msg)
// Do not report back responses if they were generated from a
// command packet
- if(channel == 0x1f)
+ if(channel == CONTROL_CHAN)
return;
// Find the port through the owner of the channel
@@ -470,7 +513,14 @@ usrp_server::handle_message(mb_message_sptr msg)
std::cout << "[USRP_SERVER] unhandled msg: " << msg << std::endl;
}
-// Return -1 if it is not an RX port, or an index
+/*!
+ * \brief Takes a port_symbol() as parameter \p port_id and is used to determine
+ * if the port is a TX port, or to find an index in the d_tx vector which stores
+ * the port.
+ *
+ * \returns -1 if \p port_id is not in the d_tx vector (i.e., it's not a TX
+ * port), otherwise returns an index in the d_tx vector which stores the port.
+ */
int usrp_server::tx_port_index(pmt_t port_id) {
for(int i=0; i < (int) d_tx.size(); i++)
@@ -480,7 +530,14 @@ int usrp_server::tx_port_index(pmt_t port_id) {
return -1;
}
-// Return -1 if it is not an RX port, or an index
+/*!
+ * \brief Takes a port_symbol() as parameter \p port_id and is used to determine
+ * if the port is an RX port, or to find an index in the d_rx vector which
+ * stores the port.
+ *
+ * \returns -1 if \p port_id is not in the d_rx vector (i.e., it's not an RX
+ * port), otherwise returns an index in the d_rx vector which stores the port.
+ */
int usrp_server::rx_port_index(pmt_t port_id) {
for(int i=0; i < (int) d_rx.size(); i++)
@@ -490,8 +547,12 @@ int usrp_server::rx_port_index(pmt_t port_id) {
return -1;
}
-// Go through all TX and RX channels, sum up the assigned capacity
-// and return it
+/*!
+ * \brief Determines the current total capacity allocated by all RX and TX
+ * channels.
+ *
+ * \returns the total allocated capacity
+ */
long usrp_server::current_capacity_allocation() {
long capacity = 0;
@@ -504,6 +565,14 @@ long usrp_server::current_capacity_allocation() {
return capacity;
}
+
+/*!
+ * \brief Called by the handle_message() method if the incoming message to
+ * usrp_server is to allocate a channel (cmd-allocate-channel). The method
+ * checks if the requested capacity exists and if so it will reserve it for the
+ * caller on the channel that is returned via a response-allocate-channel
+ * signal.
+ */
void
usrp_server::handle_cmd_allocate_channel(
mb_port_sptr port,
@@ -564,9 +633,13 @@ usrp_server::handle_cmd_allocate_channel(
return;
}
-// Check the port type and deallocate assigned capacity based on this, ensuring
-// that the owner of the method invocation is the owner of the port and that the
-// channel number is valid.
+/*!
+ * \brief Called by the handle_message() method if the incoming message to
+ * usrp_server is to deallocate a channel (cmd-deallocate-channel). The method
+ * ensures that the sender of the signal owns the channel and that the channel
+ * number is valid. A response-deallocate-channel signal is sent back with the
+ * result of the deallocation.
+ */
void
usrp_server::handle_cmd_deallocate_channel(
mb_port_sptr port,
@@ -591,8 +664,26 @@ usrp_server::handle_cmd_deallocate_channel(
return;
}
-void usrp_server::handle_cmd_xmit_raw_frame(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data) {
-
+/*!
+ * \brief Called by the handle_message() method if the incoming message to
+ * usrp_server is to transmit a frame (cmd-xmit-raw-frame). The method
+ * allocates enough memory to support a burst of packets which contain the frame
+ * over the bus of the frame, sets the packet headers, and sends a signal to the
+ * lower block for the data (packets) to be written to the bus.
+ *
+ * The \p port the command was sent on and the channel info (\p chan_info) of
+ * the channel the frame is to be transmitted on are passed to ensure that the
+ * caller owns the channel.
+ *
+ * The \p data parameter is in the format of a cmd-xmit-raw-frame signal.
+ *
+ * The properties
+ */
+void usrp_server::handle_cmd_xmit_raw_frame(
+ mb_port_sptr port,
+ std::vector<struct channel_info> &chan_info,
+ pmt_t data)
+{
size_t n_bytes, psize;
long max_payload_len = transport_pkt::max_payload();
@@ -667,7 +758,8 @@ void usrp_server::handle_cmd_xmit_raw_frame(mb_port_sptr port, std::vector<struc
<< invocation_handle << std::endl;
// The actual response to the write will be generated by a
- // s_response_usrp_write
+ // s_response_usrp_write since we cannot determine whether to transmit was
+ // successful until we hear from the lower layers.
d_cs_usrp->send(s_cmd_usrp_write,
pmt_list3(invocation_handle,
pmt_from_long(channel),
@@ -676,7 +768,29 @@ void usrp_server::handle_cmd_xmit_raw_frame(mb_port_sptr port, std::vector<struc
return;
}
-void usrp_server::handle_cmd_to_control_channel(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data)
+/*!
+ * \brief Called by the handle_message() method to parse incoming control/status
+ * signals (cmd-to-control-channel).
+ *
+ * The \p port the command was sent on and the channel info (\p chan_info) of
+ * the channel are passed to ensure that the caller owns the channel.
+ *
+ * The \p data parameter is in the format of a PMT list, where each element
+ * follows the format of a control/status signal (i.e. op-ping-fixed).
+ *
+ * The method will parse all of the C/S commands included in \p data and place
+ * the commands in to a lower level packet sent to the control channel. The
+ * method will pack as many commands as possible in t oa single packet, and once
+ * it is fill generate as many lower level packets as needed.
+ *
+ * Anything that needs to be returned to the sender of the signal (i.e. the
+ * value of a register) will be generated by the parse_control_pkt() method as
+ * the responses to the commands are read back from the USRP.
+ */
+void usrp_server::handle_cmd_to_control_channel(
+ mb_port_sptr port,
+ std::vector<struct channel_info> &chan_info,
+ pmt_t data)
{
pmt_t invocation_handle = pmt_nth(0, data);
@@ -687,7 +801,10 @@ void usrp_server::handle_cmd_to_control_channel(mb_port_sptr port, std::vector<s
size_t psize;
long payload_len = 0;
- long channel = 0x1f;
+ long channel = CONTROL_CHAN;
+
+ if(verbose)
+ std::cout << "[USRP_SERVER] Handling " << n_subpkts << " commands\n";
// The design of the following code is optimized for simplicity, not
// performance. To performance optimize this code, the total size in bytes
@@ -990,8 +1107,22 @@ void usrp_server::handle_cmd_to_control_channel(mb_port_sptr port, std::vector<s
return;
}
+/*!
+ * \brief Called by the handle_message() method when the incoming signal is a
+ * command to start reading samples from the USRP (cmd-start-recv-raw-samples).
+ *
+ * The \p port the command was sent on and the channel info (\p chan_info) of
+ * the channel are passed to ensure that the caller owns the channel.
+ *
+ * The \p data parameter should be in the format of a cmd-start-recv-raw-samples
+ * command where the first element in the list is an invocation handle, and the
+ * second is the channel the signal generator wants to receive the samples on.
+ */
void
-usrp_server::handle_cmd_start_recv_raw_samples(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data)
+usrp_server::handle_cmd_start_recv_raw_samples(
+ mb_port_sptr port,
+ std::vector<struct channel_info> &chan_info,
+ pmt_t data)
{
pmt_t invocation_handle = pmt_nth(0, data);
long channel = pmt_to_long(pmt_nth(1, data));
@@ -1032,6 +1163,18 @@ usrp_server::handle_cmd_start_recv_raw_samples(mb_port_sptr port, std::vector<st
return;
}
+/*!
+ * \brief Called by the handle_message() method when the incoming signal is to
+ * stop receiving samples from the USRP (cmd-stop-recv-raw-samples).
+ *
+ * The \p port the command was sent on and the channel info (\p chan_info) of
+ * the channel are passed to ensure that the caller owns the channel.
+ *
+ * The \p data parameter should be in the format of a cmd-stop-recv-raw-samples
+ * command where the first element in the list is an invocation handle, and the
+ * second is the channel the signal generator wants to stop receiving the
+ * samples from.
+ */
void
usrp_server::handle_cmd_stop_recv_raw_samples(
mb_port_sptr port,
@@ -1067,7 +1210,22 @@ usrp_server::handle_cmd_stop_recv_raw_samples(
return;
}
-// Read the packet header, determine the port by the channel owner
+/*!
+ * \brief Called by the handle_message() method when an incoming signal is
+ * generated to USRP server that contains raw samples from the USRP. This
+ * method generates the response-recv-raw-samples signals that are the result of
+ * a cmd-start-recv-raw-samples signal.
+ *
+ * The raw lower-level packet is extracted from \p data, where the format for \p
+ * data is a PMT list. The PMT \p data list should contain an invocation handle
+ * as the first element, the status of the lower-level read as the second
+ * element, and a uniform vector representation of the packets as the third
+ * element.
+ *
+ * The packet contains a channel field that the samples are destined to, and the
+ * method determines where to send the samples based on this channel since each
+ * channel has an associated port which allocated it.
+ */
void
usrp_server::handle_response_usrp_read(pmt_t data)
{
@@ -1106,7 +1264,7 @@ usrp_server::handle_response_usrp_read(pmt_t data)
return;
// If the packet is a C/S packet, parse it separately
- if(channel == 0x1f) {
+ if(channel == CONTROL_CHAN) {
parse_control_pkt(invocation_handle, pkt);
return;
}
@@ -1137,14 +1295,28 @@ usrp_server::handle_response_usrp_read(pmt_t data)
PMT_T);
d_rx[port]->send(s_response_recv_raw_samples,
- pmt_list5(invocation_handle,
+ pmt_list6(invocation_handle,
status,
v_samples,
pmt_from_long(pkt->timestamp()),
+ pmt_from_long(channel),
properties));
return;
}
+/*!
+ * \brief Called by handle_response_usrp_read() when the incoming packet has a
+ * channel of CONTROL_CHAN. This means that the incoming packet contains a
+ * response for a command sent to the control channel, which this method will
+ * parse.
+ *
+ * The \p pkt parameter is a pointer to the full packet (transport_pkt) in
+ * memory.
+ *
+ * Given that all commands sent to the control channel that require responses
+ * will carry an RID (request ID), the method will use the RID passed back with
+ * the response to determine which port the response should be sent on.
+ */
void
usrp_server::parse_control_pkt(pmt_t invocation_handle, transport_pkt *pkt)
{
@@ -1190,6 +1362,9 @@ usrp_server::parse_control_pkt(pmt_t invocation_handle, transport_pkt *pkt)
return;
pmt_t owner = d_rids[srid].owner;
+
+ // Return the RID
+ d_rids[srid].owner = PMT_NIL;
// FIXME: should be 1 response for all subpackets here ?
if((port = tx_port_index(owner)) != -1)
@@ -1225,6 +1400,9 @@ usrp_server::parse_control_pkt(pmt_t invocation_handle, transport_pkt *pkt)
return;
pmt_t owner = d_rids[srid].owner;
+
+ // Return the RID
+ d_rids[srid].owner = PMT_NIL;
// FIXME: should be 1 response for all subpackets here ?
if((port = tx_port_index(owner)) != -1)
@@ -1261,6 +1439,9 @@ usrp_server::parse_control_pkt(pmt_t invocation_handle, transport_pkt *pkt)
return;
pmt_t owner = d_rids[srid].owner;
+
+ // Return the RID
+ d_rids[srid].owner = PMT_NIL;
if((port = tx_port_index(owner)) != -1)
d_tx[port]->send(s_response_from_control_channel,
@@ -1294,6 +1475,9 @@ usrp_server::parse_control_pkt(pmt_t invocation_handle, transport_pkt *pkt)
return;
pmt_t owner = d_rids[srid].owner;
+
+ // Return the RID
+ d_rids[srid].owner = PMT_NIL;
if((port = tx_port_index(owner)) != -1)
d_tx[port]->send(s_response_from_control_channel,
@@ -1317,6 +1501,10 @@ usrp_server::parse_control_pkt(pmt_t invocation_handle, transport_pkt *pkt)
}
}
+/*!
+ * \brief Used to recall all incoming signals that were deferred when USRP
+ * server was in the initialization state.
+ */
void
usrp_server::recall_defer_queue()
{
@@ -1335,6 +1523,25 @@ usrp_server::recall_defer_queue()
return;
}
+/*!
+ * \brief Commonly called by any method which handles outgoing frames or control
+ * packets to the USRP to check if the port on which the signal was sent owns
+ * the channel the outgoing packet will be associated with. This helps ensure
+ * that applications do not send data on other application's ports.
+ *
+ * The \p port parameter is the port symbol that the caller wishes to determine
+ * owns the channel specified by \p chan_info.
+ *
+ * The \p signal_info parameter is a PMT list containing two elements: the
+ * response signal to use if the permissions are invalid, and the invocation
+ * handle that was passed. This allows the method to generate detailed failure
+ * responses to signals without having to return some sort of structured
+ * information which the caller must then parse and interpret to determine the
+ * failure type.
+ *
+ * \returns true if \p port owns the channel specified by \p chan_info, false
+ * otherwise.
+ */
bool
usrp_server::check_valid(mb_port_sptr port,
long channel,
@@ -1346,7 +1553,7 @@ usrp_server::check_valid(mb_port_sptr port,
pmt_t invocation_handle = pmt_nth(1, signal_info);
// not a valid channel number?
- if(channel >= (long)chan_info.size() && channel != 0x1f) {
+ if(channel >= (long)chan_info.size() && channel != CONTROL_CHAN) {
port->send(response_signal,
pmt_list2(invocation_handle,
s_err_channel_invalid));
@@ -1377,8 +1584,12 @@ usrp_server::check_valid(mb_port_sptr port,
return true;
}
-// Goes through the vector of RIDs and retreieves an
-// available one for use
+/*!
+ * \brief Finds the next available RID for internal USRP server use with control
+ * and status packets.
+ *
+ * \returns the next valid RID or -1 if no more RIDs are available.
+ */
long
usrp_server::next_rid()
{
@@ -1386,7 +1597,264 @@ usrp_server::next_rid()
if(pmt_eqv(d_rids[i].owner, PMT_NIL))
return i;
+ if(verbose)
+ std::cout << "[USRP_SERVER] No RIDs left\n";
return -1;
}
+/*!
+ * \brief Called by handle_message() when USRP server gets a response that the
+ * USRP was opened successfully to initialize the registers using the new
+ * register read/write control packets.
+ */
+void
+usrp_server::initialize_registers()
+{
+ // We use handle_cmd_to_control_channel() to create the register writes using
+ // PMT_NIL as the response port to tell usrp_server not to pass the response
+ // up to any application.
+ if(verbose)
+ std::cout << "[USRP_SERVER] Initializing registers...\n";
+
+ // RX mode to normal (0)
+ set_register(FR_MODE, 0);
+
+ // FPGA debugging?
+ if(d_fpga_debug) {
+ set_register(FR_DEBUG_EN, 1);
+ // FIXME: need to figure out exact register writes to control daughterboard
+ // pins that need to be written to
+ } else {
+ set_register(FR_DEBUG_EN, 0);
+ }
+
+ // Set the transmit sample rate divisor, which is 4-1
+ set_register(FR_TX_SAMPLE_RATE_DIV, 3);
+
+ // Dboard IO buffer and register settings
+ set_register(FR_OE_0, (0xffff << 16) | 0x0000);
+ set_register(FR_IO_0, (0xffff << 16) | 0x0000);
+ set_register(FR_OE_1, (0xffff << 16) | 0x0000);
+ set_register(FR_IO_1, (0xffff << 16) | 0x0000);
+ set_register(FR_OE_2, (0xffff << 16) | 0x0000);
+ set_register(FR_IO_2, (0xffff << 16) | 0x0000);
+ set_register(FR_OE_3, (0xffff << 16) | 0x0000);
+ set_register(FR_IO_3, (0xffff << 16) | 0x0000);
+
+ // zero Tx side Auto Transmit/Receive regs
+ set_register(FR_ATR_MASK_0, 0);
+ set_register(FR_ATR_TXVAL_0, 0);
+ set_register(FR_ATR_RXVAL_0, 0);
+ set_register(FR_ATR_MASK_1, 0);
+ set_register(FR_ATR_TXVAL_1, 0);
+ set_register(FR_ATR_RXVAL_1, 0);
+ set_register(FR_ATR_MASK_2, 0);
+ set_register(FR_ATR_TXVAL_2, 0);
+ set_register(FR_ATR_RXVAL_2, 0);
+ set_register(FR_ATR_MASK_3, 0);
+ set_register(FR_ATR_TXVAL_3, 0);
+ set_register(FR_ATR_RXVAL_3, 0);
+
+ // Configure TX mux, this is a hacked value
+ set_register(FR_TX_MUX, 0x00000081);
+
+ // Set the interpolation rate, which is the rate divided by 4, minus 1
+ set_register(FR_INTERP_RATE, (d_interp_tx/4)-1);
+
+ // Apparently this register changes again
+ set_register(FR_TX_MUX, 0x00000981);
+
+ // Set the receive sample rate divisor, which is 2-1
+ set_register(FR_RX_SAMPLE_RATE_DIV, 1);
+
+ // DC offset
+ set_register(FR_DC_OFFSET_CL_EN, 0x0000000f);
+
+ // Reset the DC correction offsets
+ set_register(FR_ADC_OFFSET_0, 0);
+ set_register(FR_ADC_OFFSET_1, 0);
+
+ // Some hard-coded RX configuration
+ set_register(FR_RX_FORMAT, 0x00000300);
+ set_register(FR_RX_MUX, 1);
+
+ // RX decimation rate is divided by two, then subtract 1
+ set_register(FR_DECIM_RATE, (d_decim_rx/2)-1);
+
+ // More hard coding
+ set_register(FR_RX_MUX, 0x000e4e41);
+
+ // Resetting RX registers
+ set_register(FR_RX_PHASE_0, 0);
+ set_register(FR_RX_PHASE_1, 0);
+ set_register(FR_RX_PHASE_2, 0);
+ set_register(FR_RX_PHASE_3, 0);
+ set_register(FR_RX_FREQ_0, 0x28000000);
+ set_register(FR_RX_FREQ_1, 0);
+ set_register(FR_RX_FREQ_2, 0);
+ set_register(FR_RX_FREQ_3, 0);
+
+ // Enable debug bus
+ set_register(FR_DEBUG_EN, 0xf);
+ set_register(FR_OE_0, -1);
+ set_register(FR_OE_1, -1);
+ set_register(FR_OE_2, -1);
+ set_register(FR_OE_3, -1);
+
+ // DEBUGGING
+ //check_register_initialization();
+}
+
+// FIXME: used for debugging to determine if all the registers are actually
+// being set correctly
+void
+usrp_server::check_register_initialization()
+{
+ // RX mode to normal (0)
+ read_register(FR_MODE);
+
+ // FPGA debugging?
+ if(d_fpga_debug) {
+ read_register(FR_DEBUG_EN);
+ // FIXME: need to figure out exact register writes to control daughterboard
+ // pins that need to be written to
+ } else {
+ read_register(FR_DEBUG_EN);
+ }
+
+ // Set the transmit sample rate divisor, which is 4-1
+ read_register(FR_TX_SAMPLE_RATE_DIV);
+
+ // Dboard IO buffer and register settings
+ read_register(FR_OE_0);
+ read_register(FR_IO_0);
+ read_register(FR_OE_1);
+ read_register(FR_IO_1);
+ read_register(FR_OE_2);
+ read_register(FR_IO_2);
+ read_register(FR_OE_3);
+ read_register(FR_IO_3);
+
+ // zero Tx side Auto Transmit/Receive regs
+ read_register(FR_ATR_MASK_0);
+ read_register(FR_ATR_TXVAL_0);
+ read_register(FR_ATR_RXVAL_0);
+ read_register(FR_ATR_MASK_1);
+ read_register(FR_ATR_TXVAL_1);
+ read_register(FR_ATR_RXVAL_1);
+ read_register(FR_ATR_MASK_2);
+ read_register(FR_ATR_TXVAL_2);
+ read_register(FR_ATR_RXVAL_2);
+ read_register(FR_ATR_MASK_3);
+ read_register(FR_ATR_TXVAL_3);
+ read_register(FR_ATR_RXVAL_3);
+
+ // Configure TX mux, this is a hacked value
+ read_register(FR_TX_MUX);
+
+ // Set the interpolation rate, which is the rate divided by 4, minus 1
+ read_register(FR_INTERP_RATE);
+
+ // Apparently this register changes again
+ read_register(FR_TX_MUX);
+
+ // Set the receive sample rate divisor, which is 2-1
+ read_register(FR_RX_SAMPLE_RATE_DIV);
+
+ // DC offset
+ read_register(FR_DC_OFFSET_CL_EN);
+
+ // Reset the DC correction offsets
+ read_register(FR_ADC_OFFSET_0);
+ read_register(FR_ADC_OFFSET_1);
+
+ // Some hard-coded RX configuration
+ read_register(FR_RX_FORMAT);
+ read_register(FR_RX_MUX);
+
+ // RX decimation rate is divided by two, then subtract 1
+ read_register(FR_DECIM_RATE);
+
+ // More hard coding
+ read_register(FR_RX_MUX);
+
+ // Resetting RX registers
+ read_register(FR_RX_PHASE_0);
+ read_register(FR_RX_PHASE_1);
+ read_register(FR_RX_PHASE_2);
+ read_register(FR_RX_PHASE_3);
+ read_register(FR_RX_FREQ_0);
+ read_register(FR_RX_FREQ_1);
+ read_register(FR_RX_FREQ_2);
+ read_register(FR_RX_FREQ_3);
+}
+
+/*!
+ * \brief Used to generate FPGA register write commands to reset all of the FPGA
+ * registers to a value of 0.
+ */
+void
+usrp_server::reset_all_registers()
+{
+ for(int i=0; i<64; i++)
+ set_register(i, 0);
+}
+
+/*!
+ * \brief Used internally by USRP server to generate a control/status packet
+ * which contains a register write.
+ *
+ * The \p reg parameter is the register number that the value \p val will be
+ * written to.
+ */
+void
+usrp_server::set_register(long reg, long val)
+{
+ size_t psize;
+ long payload_len = 0;
+
+ pmt_t v_packet = pmt_make_u8vector(sizeof(transport_pkt), 0);
+ transport_pkt *pkt = (transport_pkt *) pmt_u8vector_writeable_elements(v_packet, psize);
+
+ pkt->set_header(0, CONTROL_CHAN, 0, payload_len);
+ pkt->set_timestamp(0xffffffff);
+
+ pkt->cs_write_reg(reg, val);
+
+ d_cs_usrp->send(s_cmd_usrp_write,
+ pmt_list3(PMT_NIL,
+ pmt_from_long(CONTROL_CHAN),
+ v_packet));
+}
+
+/*!
+ * \brief Used internally by USRP server to generate a control/status packet
+ * which contains a register read. This is important to use internally so that
+ * USRP server can bypass the use of RIDs with register reads, as they are not
+ * needed and it would use up the finite number of RIDs available for use for
+ * applications to receive responses.
+ *
+ * The \p reg parameter is the register number that the value should be read
+ * from.
+ */
+void
+usrp_server::read_register(long reg)
+{
+ size_t psize;
+ long payload_len = 0;
+
+ pmt_t v_packet = pmt_make_u8vector(sizeof(transport_pkt), 0);
+ transport_pkt *pkt = (transport_pkt *) pmt_u8vector_writeable_elements(v_packet, psize);
+
+ pkt->set_header(0, CONTROL_CHAN, 0, payload_len);
+ pkt->set_timestamp(0xffffffff);
+
+ pkt->cs_read_reg(0, reg);
+
+ d_cs_usrp->send(s_cmd_usrp_write,
+ pmt_list3(PMT_NIL,
+ pmt_from_long(CONTROL_CHAN),
+ v_packet));
+}
+
REGISTER_MBLOCK_CLASS(usrp_server);
diff --git a/usrp/host/lib/inband/usrp_server.h b/usrp/host/lib/inband/usrp_server.h
index 81dceb1f4..09c82faac 100644
--- a/usrp/host/lib/inband/usrp_server.h
+++ b/usrp/host/lib/inband/usrp_server.h
@@ -51,6 +51,13 @@ public:
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;
@@ -114,6 +121,11 @@ private:
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 */
diff --git a/usrp/host/lib/inband/usrp_server.mbh b/usrp/host/lib/inband/usrp_server.mbh
index 3fd0db139..ed7943fc3 100644
--- a/usrp/host/lib/inband/usrp_server.mbh
+++ b/usrp/host/lib/inband/usrp_server.mbh
@@ -202,7 +202,7 @@
(:incoming
- (response-recv-raw-samples invocation-handle status samples timestamp properties)
+ (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
diff --git a/usrp/host/lib/inband/usrp_tx.cc b/usrp/host/lib/inband/usrp_tx.cc
index a7a5e4a89..da8777513 100644
--- a/usrp/host/lib/inband/usrp_tx.cc
+++ b/usrp/host/lib/inband/usrp_tx.cc
@@ -66,6 +66,10 @@ 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)
{
@@ -82,6 +86,14 @@ usrp_tx::handle_message(mb_message_sptr msg)
}
}
+/*!
+ * \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)
{
@@ -121,7 +133,7 @@ usrp_tx::write(pmt_t data)
for(int i=0; i < n_packets; i++) {
if(d_disk_write) {
- if(pkts[i].chan() == 0x1f)
+ 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());
diff --git a/usrp/host/lib/inband/usrp_tx_stub.cc b/usrp/host/lib/inband/usrp_tx_stub.cc
index 7a9876322..6cff3b4ee 100644
--- a/usrp/host/lib/inband/usrp_tx_stub.cc
+++ b/usrp/host/lib/inband/usrp_tx_stub.cc
@@ -103,7 +103,7 @@ usrp_tx_stub::write(pmt_t data)
for(long i=0; i<n_packets; i++) {
if(d_disk_write) {
- if(pkts[i].chan() == 0x1f)
+ 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());
@@ -112,7 +112,7 @@ usrp_tx_stub::write(pmt_t data)
d_ofile.flush();
}
- if(pkts[i].chan() == 0x1f)
+ if(pkts[i].chan() == CONTROL_CHAN)
parse_cs(invocation_handle, pkts[i]);
}
@@ -140,7 +140,7 @@ usrp_tx_stub::parse_cs(pmt_t invocation_handle, transport_pkt pkt)
transport_pkt *q_pkt =
(transport_pkt *) pmt_u8vector_writeable_elements(v_pkt, ignore);
- q_pkt->set_header(0, 0x1f, 0, 0);
+ 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
diff --git a/usrp/host/lib/inband/usrp_usb_interface.cc b/usrp/host/lib/inband/usrp_usb_interface.cc
index 269ed2706..51b6d4646 100644
--- a/usrp/host/lib/inband/usrp_usb_interface.cc
+++ b/usrp/host/lib/inband/usrp_usb_interface.cc
@@ -47,12 +47,16 @@ static pmt_t s_shutdown = pmt_intern("%shutdown");
static const bool verbose = false;
-
-// need to take number of TX and RX channels as parameter
+/*!
+ * \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_fpga_debug(false),
d_fake_usrp(false),
+ d_rx_reading(false),
d_interp_tx(128),
d_decim_rx(128),
d_rf_freq(10e6),
@@ -86,7 +90,7 @@ usrp_usb_interface::usrp_usb_interface(mb_runtime *rt, const std::string &instan
d_interp_tx = pmt_to_long(interp_tx);
}
- // Read the RX interpolations
+ // Read the RX decimation rate
if(pmt_t decim_rx = pmt_dict_ref(usrp_dict,
pmt_intern("decim-rx"),
PMT_NIL)) {
@@ -134,8 +138,8 @@ usrp_usb_interface::usrp_usb_interface(mb_runtime *rt, const std::string &instan
d_tx_cs = define_port("tx_cs", "usrp-tx-cs", false, mb_port::INTERNAL);
// Connect to TX and RX
- define_component("tx", tx_interface, PMT_F);
- define_component("rx", rx_interface, PMT_F);
+ 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");
@@ -146,8 +150,6 @@ usrp_usb_interface::usrp_usb_interface(mb_runtime *rt, const std::string &instan
d_utx = NULL;
d_urx = NULL;
- d_fpga_debug=true; // WARNING: DO NOT ENABLE WITH D'BOARDS OTHER THAN BASIC TX/RX
-
}
usrp_usb_interface::~usrp_usb_interface()
@@ -161,6 +163,10 @@ 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)
{
@@ -256,6 +262,13 @@ usrp_usb_interface::handle_message(mb_message_sptr msg)
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)
{
@@ -290,7 +303,7 @@ usrp_usb_interface::handle_cmd_open(pmt_t data)
return;
}
- if(!d_utx->set_tx_freq (0,d_rf_freq)) { // try setting center freq to 0
+ if(!d_utx->set_tx_freq (0,d_rf_freq) || !d_utx->set_tx_freq(1,d_rf_freq)) { // try setting center freq to 0
if (verbose)
std::cout << "[USRP_USB_INTERFACE] Failed to set center frequency on TX\n";
reply_data = pmt_list2(invocation_handle, PMT_F);
@@ -298,6 +311,14 @@ usrp_usb_interface::handle_cmd_open(pmt_t data)
return;
}
+ if(!d_utx->set_mux(0xBA98)) {
+ if (verbose)
+ std::cout << "[USRP_USB_INTERFACE] Failed to set TX mux\n";
+ reply_data = pmt_list2(invocation_handle, PMT_F);
+ d_cs->send(s_response_usrp_open, reply_data);
+ return;
+ }
+
d_utx->start();
if (verbose)
@@ -321,33 +342,44 @@ usrp_usb_interface::handle_cmd_open(pmt_t data)
return;
}
- if(!d_urx->set_rx_freq (0, d_rf_freq)) {
+ if(!d_urx->set_rx_freq (0, -d_rf_freq) || !d_urx->set_rx_freq(1, -d_rf_freq)) {
if (verbose)
std::cout << "[usrp_server] 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(d_fpga_debug) {
- 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);
-
-// while(1){
-// for(int i=0; i<0xffff; i++)
-// d_urx->write_io(0, i, 0xffff);
-// }
- }
+ // Two channels ... this really needs to end up being set correctly by
+ // querying for what dboards are connected
+ if(!d_urx->set_mux(0x32103210)) {
+ if (verbose)
+ std::cout << "[USRP_USB_INTERFACE] Failed to set RX mux\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)
{
@@ -366,6 +398,13 @@ usrp_usb_interface::handle_cmd_write(pmt_t data)
return;
}
+/*!
+ * \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)
{
@@ -381,9 +420,18 @@ usrp_usb_interface::handle_cmd_start_reading(pmt_t data)
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)
{
@@ -392,22 +440,40 @@ usrp_usb_interface::handle_cmd_stop_reading(pmt_t 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 = true; // extern to communicate with stub to wait
+ 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;
diff --git a/usrp/host/lib/inband/usrp_usb_interface.h b/usrp/host/lib/inband/usrp_usb_interface.h
index 8efce2ff6..6c2c15768 100644
--- a/usrp/host/lib/inband/usrp_usb_interface.h
+++ b/usrp/host/lib/inband/usrp_usb_interface.h
@@ -42,10 +42,10 @@ class usrp_usb_interface : public mb_mblock
long d_ntx_chan;
long d_nrx_chan;
- long d_fpga_debug;
-
bool d_fake_usrp;
+ bool d_rx_reading;
+
long d_interp_tx;
long d_decim_rx;
diff --git a/usrp/host/lib/legacy/fusb_linux.cc b/usrp/host/lib/legacy/fusb_linux.cc
index 60687a149..6dce8d9e0 100644
--- a/usrp/host/lib/legacy/fusb_linux.cc
+++ b/usrp/host/lib/legacy/fusb_linux.cc
@@ -386,14 +386,6 @@ fusb_ephandle_linux::stop ()
{
if (!d_started)
return true;
-
- d_devhandle->_cancel_pending_rqsts (this);
- d_devhandle->_reap (false);
-
-
- usbdevfs_urb *urb;
- while ((urb = completed_list_get ()) != 0)
- free_list_add (urb);
if (d_write_work_in_progress){
free_list_add (d_write_work_in_progress);
@@ -407,11 +399,19 @@ fusb_ephandle_linux::stop ()
d_read_buffer_end = 0;
}
- if (d_free_list.size () != (unsigned) d_nblocks)
- fprintf (stderr, "d_free_list.size () = %d, d_nblocks = %d\n",
- d_free_list.size (), d_nblocks);
-
- assert (d_free_list.size () == (unsigned) d_nblocks);
+ d_devhandle->_cancel_pending_rqsts (this);
+ d_devhandle->_reap (false);
+
+ while (1){
+ usbdevfs_urb *urb;
+ while ((urb = completed_list_get ()) != 0)
+ free_list_add (urb);
+
+ if (d_free_list.size () == (unsigned) d_nblocks)
+ break;
+
+ d_devhandle->_reap(true);
+ }
d_started = false;
return true;