Editing GRAndWalkthroughUSRP

Jump to navigation Jump to search

Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.

Latest revision Your text
Line 7: Line 7:
See the main [[Android]] page for a list of devices that have been tested and work with USRPs.
See the main [[Android]] page for a list of devices that have been tested and work with USRPs.


I suspect that network-connected USRPs will work pretty easily with Android. The biggest challenge with the B2xx series of USRPs is that they must have their firmware and FPGA images programmed in every time they are powered on. A network-connected USRP like an N200/N210 or X310 is pre-programmed and does not require the same workarounds for permissions issues that we face with USB devices. The only permission for a networked USRP is the "android.permission.INTERNET", which we have been using, anyways, for access to ControlPort.
I suspect that network-connected USRPs will work pretty easily with Android. The biggest challenge with the B2xx series of USRPs is that they must have their firmware and FPGA images programmed in every time they are powered on. A network-connected USRP like an N200/N210 or X310 is pre-programmed and does not require the same workarounds for permissions issues that we face with USB devices. The only permission for a networked USRP is the "android.permission.INTERNET", which we have been using, anyways, for access to ControlPort.


RTL-SDR devices can also work with GNU Radio for Android apps. Like the USRP B2xx devices, these need the USB permissions workaround, but they do not need to be programmed. We build the RTL-SDR library as well as gr-osmosdr support for them into our GR for Android dependency bundle. I suspect, too, that adding support for other USB-based devices like the BladeRF, HackRF, Airspy, etc. will also be fairly straight-forward.
RTL-SDR devices can also work with GNU Radio for Android apps. Like the USRP B2xx devices, these need the USB permissions workaround, but they do not need to be programmed. We build the RTL-SDR library as well as gr-osmosdr support for them into our GR for Android dependency bundle. I suspect, too, that adding support for other USB-based devices like the BladeRF, HackRF, Airspy, etc. will also be fairly straight-forward.
Line 19: Line 19:
Second, clone and build the [https://github.com/trondeau/GrHardwareService GrHardwareService application]. Install this app onto your Android device. If you don't have a USRP plugged in when this first starts, it will just crash (not particularly nice, I know, but we'll get there). With this loaded onto your machine, it installs the USRP firmware and FPGA images for the B2xx devices and starts listening for USB connections. And USB device that's plugged in where the vendor and produce IDs match any of the known-working USRPs, this app is launched and starts programming the device. It will have to ask you for permission to use the device twice, once to program the firmware and then again to program the FPGA image. Once that's done, the hardware is programmed and ready to go.
Second, clone and build the [https://github.com/trondeau/GrHardwareService GrHardwareService application]. Install this app onto your Android device. If you don't have a USRP plugged in when this first starts, it will just crash (not particularly nice, I know, but we'll get there). With this loaded onto your machine, it installs the USRP firmware and FPGA images for the B2xx devices and starts listening for USB connections. And USB device that's plugged in where the vendor and produce IDs match any of the known-working USRPs, this app is launched and starts programming the device. It will have to ask you for permission to use the device twice, once to program the firmware and then again to program the FPGA image. Once that's done, the hardware is programmed and ready to go.


If the program crashes on you when you first plug in a USRP, it's likely a permissions issue. I've noticed that on Marshmallow (Android version 6), I had to go into the App section under Settings, find the GrHardwareService app, go in there to Permissions, and enable the Storage permission. This is a new "feature" in [https://developer.android.com/training/permissions/requesting.html Marshmallow], and there are standard ways to handle it inside of the app. I'm not worrying about that here because I don't want to confuse the code any more than we have to by having version-specific checks.
If the program crashes on you when you first plug in a USRP, it's likely a permissions issue. I've noticed that on Marshmallow (Android version 6), I had to go into the App section under Settings, find the GrHardwareService app, go in there to Permissions, and enable the Storage permission. This is a new "feature" in [https://developer.android.com/training/permissions/requesting.html Marshmallow], and there are standard ways to handle it inside of the app. I'm not worrying about that here because I don't want to confuse the code any more than we have to by having version-specific checks.


== Adding Support for USB Devices ==
== Adding Support for USB Devices ==
Line 47: Line 47:
         // Create the seekBar to move update the amplitude
         // Create the seekBar to move update the amplitude
         SeekBar ampSeekBar = (SeekBar) findViewById(R.id.seekBar);
         SeekBar ampSeekBar = (SeekBar) findViewById(R.id.seekBar);
         ampSeekBar.setMax(100);      // max value -> 1.0
         ampSeekBar.setMax(100);      // max value -> 1.0
         ampSeekBar.setProgress(50);  // match 0.5 starting value
         ampSeekBar.setProgress(50);  // match 0.5 starting value
         ampSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
         ampSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
Line 56: Line 56:
                         new RPCConnection.KnobInfo(mult_knob_name, amp,
                         new RPCConnection.KnobInfo(mult_knob_name, amp,
                                 BaseTypes.DOUBLE);
                                 BaseTypes.DOUBLE);
                 HashMap _map = new HashMap<>();
                 HashMap _map = new HashMap&lt;&gt;();
                 _map.put(mult_knob_name, _k);
                 _map.put(mult_knob_name, _k);
                 postSetKnobMessage(_map);
                 postSetKnobMessage(_map);
Line 203: Line 203:
         final String[] paths = deviceName.split("/");
         final String[] paths = deviceName.split("/");
         final StringBuilder sb = new StringBuilder();
         final StringBuilder sb = new StringBuilder();
         for (int i = 0; i < paths.length - 2; i++)
         for (int i = 0; i &lt; paths.length - 2; i++)
             if (i == 0)
             if (i == 0)
                 sb.append(paths[i]);
                 sb.append(paths[i]);
Line 243: Line 243:
First, we need to pass the '''fd''' and '''usrpfs_path''' values to the flowgraph. Change the function signature in '''fg.cpp''' to this:
First, we need to pass the '''fd''' and '''usrpfs_path''' values to the flowgraph. Change the function signature in '''fg.cpp''' to this:


<syntaxhighlight lang="Java">JNIEXPORT void JNICALL
<pre>JNIEXPORT void JNICALL
Java_org_gnuradio_grtemplateusrp_MainActivity_FgInit(JNIEnv* env,
Java_org_gnuradio_grtemplateusrp_MainActivity_FgInit(JNIEnv* env,
                                                     jobject thiz,
                                                     jobject thiz,
                                                     int fd, jstring devname)</syntaxhighlight>
                                                     int fd, jstring devname)</pre>
And in '''MainActivity.java''' where we declare the JNI functions, we need to add the two arguments:
And in '''MainActivity.java''' where we declare the JNI functions, we need to add the two arguments:


<syntaxhighlight lang="Java">public native void FgInit(int fd, String usbfs_path);</syntaxhighlight>
<pre>public native void FgInit(int fd, String usbfs_path);</pre>
And in '''SetupRadio''', make sure to pass this information as "FgInit(fd, usbfs_path)".
And in '''SetupRadio''', make sure to pass this information as &quot;FgInit(fd, usbfs_path)&quot;.


We then extract the information and format a device argument string for the usrp_source block:
We then extract the information and format a device argument string for the usrp_source block:


<syntaxhighlight lang="Java">
<pre>#include  
#include <gnuradio/uhd/usrp_source.h>


....
....


   const char *usbfs_path = env->GetStringUTFChars(devname, NULL);
   const char *usbfs_path = env-&gt;GetStringUTFChars(devname, NULL);
   std::stringstream args;
   std::stringstream args;
   args << "uhd,fd=" << fd << ",usbfs_path=" << usbfs_path;
   args &lt;&lt; &quot;uhd,fd=&quot; &lt;&lt; fd &lt;&lt; &quot;,usbfs_path=&quot; &lt;&lt; usbfs_path;
   GR_INFO("fg", boost::str(boost::format("Using UHD args=%1%") % args.str()));
   GR_INFO(&quot;fg&quot;, boost::str(boost::format(&quot;Using UHD args=%1%&quot;) % args.str()));


   uhd::stream_args_t stream_args;
   uhd::stream_args_t stream_args;
   stream_args.cpu_format = "fc32";
   stream_args.cpu_format = &quot;fc32&quot;;
   stream_args.otw_format = "sc16";
   stream_args.otw_format = &quot;sc16&quot;;


   ....
   ....
Line 276: Line 275:
   src = gr::uhd::usrp_source::make(args.str(), stream_args);
   src = gr::uhd::usrp_source::make(args.str(), stream_args);


   src->set_samp_rate(200e3);
   src-&gt;set_samp_rate(200e3);
   src->set_center_freq(101.1e6);
   src-&gt;set_center_freq(101.1e6);
   src->set_gain(20); // adjust as needed</syntaxhighlight>
   src-&gt;set_gain(20); // adjust as needed</pre>
The '''src''' is now a complex source. So what I'll do is create a simple flowgraph that looks like:
The '''src''' is now a complex source. So what I'll do is create a simple flowgraph that looks like:


<syntaxhighlight lang="Java">usrp_source -> complex_to_real -> multiply_const_ff -> opensl_sink</syntaxhighlight>
<pre>usrp_source -&gt; complex_to_real -&gt; multiply_const_ff -&gt; opensl_sink</pre>
The full flowgraph '''FgInit''' looks like this
The full flowgraph '''FgInit''' looks like this


<syntaxhighlight lang="Java">// Get any GNU Radio headers
<pre>// Get any GNU Radio headers
#include <gnuradio/top_block.h>
#include  
#include <gnuradio/uhd/usrp_source.h>
#include  
#include <gnuradio/blocks/complex_to_real.h>
#include  
#include <gnuradio/blocks/multiply_const_ff.h>
#include  
#include <grand/opensl_sink.h>
#include  


// Declare the global virtual machine and top-block objects
// Declare the global virtual machine and top-block objects
Line 295: Line 294:
gr::top_block_sptr tb;
gr::top_block_sptr tb;


extern "C" {
extern &quot;C&quot; {


JNIEXPORT void JNICALL
JNIEXPORT void JNICALL
Line 302: Line 301:
                                                     int fd, jstring devname)
                                                     int fd, jstring devname)
{
{
   GR_INFO("fg", "FgInit Called");
   GR_INFO(&quot;fg&quot;, &quot;FgInit Called&quot;);


   const char *usbfs_path = env->GetStringUTFChars(devname, NULL);
   const char *usbfs_path = env-&gt;GetStringUTFChars(devname, NULL);
   std::stringstream args;
   std::stringstream args;
   args << "uhd,fd=" << fd << ",usbfs_path=" << usbfs_path;
   args &lt;&lt; &quot;uhd,fd=&quot; &lt;&lt; fd &lt;&lt; &quot;,usbfs_path=&quot; &lt;&lt; usbfs_path;
   GR_INFO("fg", boost::str(boost::format("Using UHD args=%1%") % args.str()));
   GR_INFO(&quot;fg&quot;, boost::str(boost::format(&quot;Using UHD args=%1%&quot;) % args.str()));


   uhd::stream_args_t stream_args;
   uhd::stream_args_t stream_args;
   stream_args.cpu_format = "fc32";
   stream_args.cpu_format = &quot;fc32&quot;;
   stream_args.otw_format = "sc16";
   stream_args.otw_format = &quot;sc16&quot;;


   float samp_rate = 48e3;  // 48 kHz
   float samp_rate = 48e3;  // 48 kHz
Line 322: Line 321:


   // Construct the objects for every block in the flowgraph
   // Construct the objects for every block in the flowgraph
   tb = gr::make_top_block("fg");
   tb = gr::make_top_block(&quot;fg&quot;);
   src = gr::uhd::usrp_source::make(args.str(), stream_args);
   src = gr::uhd::usrp_source::make(args.str(), stream_args);
   c2r = gr::blocks::complex_to_real::make();
   c2r = gr::blocks::complex_to_real::make();
Line 328: Line 327:
   snk = gr::grand::opensl_sink::make(int(samp_rate));
   snk = gr::grand::opensl_sink::make(int(samp_rate));


   src->set_samp_rate(200e3);
   src-&gt;set_samp_rate(200e3);
   src->set_center_freq(101.1e6);
   src-&gt;set_center_freq(101.1e6);
   src->set_gain(20); // adjust as needed
   src-&gt;set_gain(20); // adjust as needed


   // Connect up the flowgraph
   // Connect up the flowgraph
   tb->connect(src, 0, c2r, 0);
   tb-&gt;connect(src, 0, c2r, 0);
   tb->connect(c2r, 0, mult, 0);
   tb-&gt;connect(c2r, 0, mult, 0);
   tb->connect(mult, 0, snk, 0);
   tb-&gt;connect(mult, 0, snk, 0);
}
}


....</syntaxhighlight>
....</pre>
This flowgraph does nothing particularly useful with the USRP, but we should be able to listen to static. We are not event setting up the sample rate, frequency, or gain values, so the incoming samples have no connection to anything real.
This flowgraph does nothing particularly useful with the USRP, but we should be able to listen to static. We are not event setting up the sample rate, frequency, or gain values, so the incoming samples have no connection to anything real.


For more complex usage of a USRP app, take a look at the [https://github.com/trondeau/GrRxFM GrRxFM], which uses a USRP to receive and demodulate broadcast FM signals. It sets up sliders to adjust the frequency and gain as well as handles sample rates and rate changes within the flowgraph.
For more complex usage of a USRP app, take a look at the [https://github.com/trondeau/GrRxFM GrRxFM], which uses a USRP to receive and demodulate broadcast FM signals. It sets up sliders to adjust the frequency and gain as well as handles sample rates and rate changes within the flowgraph.

Please note that all contributions to GNU Radio are considered to be released under the Creative Commons Attribution-ShareAlike (see GNU Radio:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!

To edit this page, please answer the question that appears below (more info):

Cancel Editing help (opens in new window)