Hi Sunny,

I have attached the file.

Jonathon

On Mon, Mar 15, 2021 at 7:06 PM Sunny Sam <[email protected]> wrote:

> I would like to use the *rfnoc_gain_example.cpp* file to test the gain
> block I created following the RFNoC 4 workshop tutorial. It was provided
> with the RFNoC 3 tutorial in  /rfnoc-workshop/src/gain-app-example/  but I
> can seem to be able to find it.
>
> The file is referenced in the
> https://kb.ettus.com/images/f/f6/rfnoc3_workshop_slides_202008_part_2.pdf
> page 105.
>
> Any help would be greatly appreciated.
>
> Thanks,
> Sunny
>
>
> _______________________________________________
> USRP-users mailing list -- [email protected]
> To unsubscribe send an email to [email protected]
>
/* -*- c++ -*- */
/*
 * Copyright 2018 Ettus Research, a National Instruments Company
 *
 * SPDX-License-Identifier: GPL-3.0-or-later
 *
 * This 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.
 *
 * gr-ettus 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 gr-ettus; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street,
 * Boston, MA 02110-1301, USA.
 */
#include <iostream>
#include <thread>
#include <complex>
#include <vector>
#include <exception>
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/program_options.hpp>
#include <uhd/utils/safe_main.hpp>
#include <uhd/utils/thread.hpp>
#include <uhd/device3.hpp>
#include <uhd/rfnoc/block_ctrl.hpp>
#include <uhd/transport/udp_simple.hpp>

namespace po = boost::program_options;

static volatile bool stop = false;

void tx_thread(
    uhd::tx_streamer::sptr tx_stream,
    const size_t wave_table_length,
    const float wave_ampl,
    const size_t spp)
{
    // Setup sine wave table
    std::vector< std::complex<float> > wave_table(wave_table_length);
    for (size_t i = 0; i < wave_table.size(); i++) {
        static const double pi = std::acos(-1.0);
        wave_table[i].real(wave_ampl*std::cos(2.0*pi*i/wave_table.size()));
        wave_table[i].imag(wave_ampl*std::sin(2.0*pi*i/wave_table.size()));
    }

    std::vector<std::complex<float> > buff(spp);
    std::vector<std::complex<float> *> buffs(1, &buff.front());
    uhd::tx_metadata_t md;
    md.start_of_burst = false;
    md.end_of_burst   = false;
    md.has_time_spec  = false;

    size_t index = 0;
    while (not stop) {
        // Fill buffer
        for (size_t n = 0; n < buff.size(); n++) {
            buff[n] = wave_table[index];
            if (index < wave_table.size()-1) {
                index++;
            }
            else {
                index = 0;
            }
        }
        tx_stream->send(buffs, buff.size(), md);
        // Reduce overall rate to prevent UDP source in GR from dropping packets
        for (size_t i = 0; i < 10e6; i++) {
            asm("nop");
        }
    }
}

void rx_thread(
    uhd::rx_streamer::sptr rx_stream,
    std::string udp_addr,
    std::string udp_port,
    const size_t spp)
{
    uhd::rx_metadata_t md;
    std::vector<std::complex<float> > buff(spp);
    auto udp_xport = uhd::transport::udp_simple::make_connected(udp_addr, udp_port);

    // Start streaming
    uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
    stream_cmd.stream_now = true;
    rx_stream->issue_stream_cmd(stream_cmd);

    while(not stop) {
        // Grab samples from stream
        size_t num_rx_samps = rx_stream->recv(&buff.front(), buff.size(), md);

        // Print out any error codes
        if (md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE) {
            if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT) {
                stop = true;
            }
            std::string error = str(boost::format("\nReceive error: %s\n") % md.strerror());
            std::cerr << error << std::endl;
        } 
        else {
            // Send samples over UDP
            try {
                udp_xport->send(boost::asio::buffer(buff, num_rx_samps*sizeof(buff.front())));
            }
            catch (const std::exception &ex) {
                stop = true;
                std::cout << "\nSending UDP packet failed: \"" << ex.what() << "\"" << std::endl;
            }
        }
    }
}

void set_gain_thread(uhd::rfnoc::block_ctrl_base::sptr gain_block_ctrl) {
    while (not stop) {
        std::string s;

        std::cout << "\nEnter gain (ctrl-c to exit): ";
        std::cin >> s;

        if ((s.length() > 0) && (not stop)) {
            try {
                uint16_t gain = boost::lexical_cast<uint16_t>(s);
                gain_block_ctrl->sr_write("GAIN", gain);
            }
            catch (boost::bad_lexical_cast) {
                std::cout << "Invalid gain." << std::endl;
            }
        }
    }
}

int UHD_SAFE_MAIN(int argc, char *argv[]){
    uhd::set_thread_priority_safe();

    // Command line options
    std::string usrp_args, udp_addr, udp_port;
    size_t spp, wave_table_length;
    float wave_ampl;
    po::options_description desc("Allowed options");
    desc.add_options()
        ("help", "help message")
        ("args", po::value<std::string>(&usrp_args)->default_value("type=x300"), "USRP device args")
        ("udp-addr", po::value<std::string>(&udp_addr)->default_value("127.0.0.1"), "UDP source address")
        ("udp-port", po::value<std::string>(&udp_port)->default_value("7124"), "UDP source port")
        ("spp", po::value<size_t>(&spp)->default_value(128), "Samples per packet")
        ("wave-table-length", po::value<size_t>(&wave_table_length)->default_value(200),
            "Wave table length, frequency is the reciprocal of table length")
        ("wave-ampl", po::value<float>(&wave_ampl)->default_value(0.1), "Wave amplitude")
    ;
    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, desc), vm);
    po::notify(vm);

    auto usrp = uhd::device3::make(std::string(usrp_args));

    // Grab block controllers, block id name comes from block descript XML tag <blockname>
    auto fifo_block_ctrl = usrp->get_block_ctrl(uhd::rfnoc::block_id_t(0, "FIFO"));
    auto gain_block_ctrl = usrp->get_block_ctrl(uhd::rfnoc::block_id_t(0, "gain"));

    // Create and connect
    auto graph = usrp->create_graph("gain_graph");
    graph->connect(fifo_block_ctrl->get_block_id(), gain_block_ctrl->get_block_id());

    // Setup receive streamer
    uhd::stream_args_t rx_stream_args("fc32", "sc16");
    rx_stream_args.args["block_id"] = gain_block_ctrl->get_block_id();
    rx_stream_args.args["spp"] = boost::lexical_cast<std::string>(spp);
    auto rx_stream = usrp->get_rx_stream(rx_stream_args);

    // Setup transmit streamer
    uhd::stream_args_t tx_stream_args("fc32", "sc16");
    tx_stream_args.args["block_id"] = fifo_block_ctrl->get_block_id();
    tx_stream_args.args["spp"] = boost::lexical_cast<std::string>(spp);
    auto tx_stream = usrp->get_tx_stream(tx_stream_args);

    auto tx_thread_inst = std::thread(&tx_thread, tx_stream, wave_table_length, wave_ampl, spp);
    auto rx_thread_inst = std::thread(&rx_thread, rx_stream, udp_addr, udp_port, spp);
    auto set_gain_thread_inst = std::thread(&set_gain_thread, gain_block_ctrl);
    tx_thread_inst.join();
    rx_thread_inst.join();
    set_gain_thread_inst.detach();

    std::cout << std::endl << "Done!" << std::endl << std::endl;
    return EXIT_SUCCESS;
}
_______________________________________________
USRP-users mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to